CNA-BUG-245: misc/cnj.md and xnb.md say the content manifest services ResolveAssetPath's existence checks; ContentManager still probes the live filesystem on every Load

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

CNA's CNJ and XNB design notes describe the startup content-manifest scan as the cache that replaces ResolveAssetPath's std::filesystem::exists calls, but at TARGET the manifest is an introspection snapshot that Load<T> never consults.

Identifier
CNA-BUG-245
Category
Bug
Subsystem
Documentation & release tooling
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
ContentManager::Load<T> / ResolveAssetPath resolution and ContentManager::GetContentManifest / RefreshContentManifest, as described by misc/cnj.md and xnb.md

Expected behaviour

CNA's design notes describe the resolution path as implemented. ContentManager.hpp itself records the current contract at contentManifest_: the manifest is “NOT yet consulted by ResolveAssetPath()/Load<T>()'s own exists()-based resolution”, and wiring it in is “deliberately deferred” so that ContentManager keeps noticing a file the instant it is written.

Actual behaviour at TARGET

misc/cnj.md (the resolution-order rationale) says the extra failed .cnj existence check is “negligible, and now serviced by the content-manifest cache (see xnb.md's ‘Content manifest’ section) rather than a raw stat call”, and a later bullet calls the scan “an internal performance cache”. xnb.md (“Content manifest: startup Content-root scan”) says the manifest “replaces” ResolveAssetPath's per-candidate std::filesystem::exists() calls with one upfront walk, and that a file added after the scan is not found until RefreshContentManifest(). At TARGET, ResolveAssetPath (inline in ContentManager.hpp) calls std::filesystem::exists for the literal path, for the .cnj candidate and for each extension candidate, each after ResolveExistingAssetPath's live case-insensitive directory walk (ContentManager.cpp); the .xnb/.cnb probes before it use the same walk. The manifest is built only by GetContentManifest()/RefreshContentManifest(). Read together, the notes imply that Load<T> would miss a file added after the scan; in fact Load<T> finds it immediately, and only GetContentManifest() is a snapshot.

Source locations

Evidence

Checked by reading at 009d40f5; not executed. Read the two design notes, ContentManager.hpp (contentManifest_ comment, ResolveAssetPath, the .xnb/.cnb probes) and ContentManager::ResolveExistingAssetPath / RefreshContentManifest. The header comment and the code agree with each other and contradict both notes. The companion claim of a global cnjVersion ceiling of 1 is no longer made: misc/cnj.md documents per-type ceilings. None of these files changed between the earlier recorded revision and TARGET.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

ContentManagerManifestTests.cpp covers the manifest itself (native/.cnj/.xnb discovery, grouping, reader inventory, malformed files, RefreshContentManifest picking up new files). Nothing checks the design notes, and no test relates Load<T> to the manifest, which is correct for the current contract.

Regression test

Documentation fix: state in both notes that the manifest is an introspection snapshot and that Load<T> resolves against the live filesystem. If the manifest is later wired into ResolveAssetPath, a test that writes a file after the scan and loads it pins the chosen freshness rule.

Blast radius

Readers and maintainers of the content pipeline who rely on the design notes for resolution cost or freshness; no runtime behaviour is affected.

Workaround

Trust the contentManifest_ comment in ContentManager.hpp and the site's resolution rules: Load<T> never consults the manifest.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index