[GH-ISSUE #5136] [Bug] Changed reference roots become invalid dot-path graph entries #3159

Closed
opened 2026-10-31 00:37:19 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @morluto on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5136

Area / interface / earliest failure

Evidence, artifacts, or reconstruction / Other (shared reference importer) / Artifact or evidence registration.

Observed behavior

A successfully admitted reference-source root that changes after enumeration makes importReferenceSource return code: parse, losing the graph of already observed children. The error is Expected a normalized relative POSIX path without traversal at entries[0].path.

Reproduction actually run

At 95c8f57aa2eafab4c8d7d43482b33ceefaf96b16, create a temporary root containing source.txt. Use an isolated filesystem-module wrapper to await the root directory handle's real close, then perform a real rename of that file to renamed.txt. Call the production application importer with an awaited ArtifactResourceScope and no exclusion policy. Scheduling is injected; enumeration, close, rename and metadata are actual host operations.

Executed npx vitest run tests/process-global/referenceSourceSymlinkRace.test.ts in the pinned baseline checkout as part of three exact regression files. The independent root-close case failed with the parse outcome above. No symlink or synthetic errno is needed for this case. It also arose while checking the end-to-end outcome of #5135.

Expected behavior / typed recovery

Keep the already observed child graph, mark inventory partial, and preserve the root enumeration failure as a root-level limitation. Initial root admission failures should still return their existing typed error. Root identity/state uncertainty must not be turned into a valid child path or discarded.

Relevant source and diagnosis

At the tested revision, ReferenceSourceReaderEntries.ts emits a failed directory entry at path: "." after root revalidation fails. ReferenceSourceImportEntries.ts projects it as a child graph entry. The graph's child-path schema correctly excludes .. The producing representation confuses a root observation with its child inventory; weakening child path validation would lose that distinction.

Impact, version, platform, and limits

Observed failed import for one deterministically scheduled root mutation, with a readable child previously captured. REA source 95c8f57aa2eafab4c8d7d43482b33ceefaf96b16, Node 24.18.0, Darwin 25.3.0 arm64. Temporary plain-text source fixture, no analysis provider. Natural incidence, other operating systems, and compiled CLI/MCP race reproduction: NOT_ENOUGH_INFO (not run/measured).

Searched open/closed reports for Reference root changed and reference-root partial failures; #3401 covers initial admission diagnostics, and #5135 covers readlink replacement. No credentials or sensitive target data included.

Originally created by @morluto on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5136 ### Area / interface / earliest failure Evidence, artifacts, or reconstruction / Other (shared reference importer) / Artifact or evidence registration. ### Observed behavior A successfully admitted reference-source root that changes after enumeration makes `importReferenceSource` return `code: parse`, losing the graph of already observed children. The error is `Expected a normalized relative POSIX path without traversal` at `entries[0].path`. ### Reproduction actually run At `95c8f57aa2eafab4c8d7d43482b33ceefaf96b16`, create a temporary root containing `source.txt`. Use an isolated filesystem-module wrapper to await the root directory handle's real close, then perform a real rename of that file to `renamed.txt`. Call the production application importer with an awaited `ArtifactResourceScope` and no exclusion policy. Scheduling is injected; enumeration, close, rename and metadata are actual host operations. Executed `npx vitest run tests/process-global/referenceSourceSymlinkRace.test.ts` in the pinned baseline checkout as part of three exact regression files. The independent root-close case failed with the parse outcome above. No symlink or synthetic errno is needed for this case. It also arose while checking the end-to-end outcome of #5135. ### Expected behavior / typed recovery Keep the already observed child graph, mark inventory partial, and preserve the root enumeration failure as a root-level limitation. Initial root admission failures should still return their existing typed error. Root identity/state uncertainty must not be turned into a valid child path or discarded. ### Relevant source and diagnosis At the tested revision, [`ReferenceSourceReaderEntries.ts`](https://github.com/morluto/rea/blob/95c8f57aa2eafab4c8d7d43482b33ceefaf96b16/src/reference/ReferenceSourceReaderEntries.ts) emits a failed directory entry at `path: "."` after root revalidation fails. [`ReferenceSourceImportEntries.ts`](https://github.com/morluto/rea/blob/95c8f57aa2eafab4c8d7d43482b33ceefaf96b16/src/application/ReferenceSourceImportEntries.ts) projects it as a child graph entry. The graph's child-path schema correctly excludes `.`. The producing representation confuses a root observation with its child inventory; weakening child path validation would lose that distinction. ### Impact, version, platform, and limits Observed failed import for one deterministically scheduled root mutation, with a readable child previously captured. REA source `95c8f57aa2eafab4c8d7d43482b33ceefaf96b16`, Node 24.18.0, Darwin 25.3.0 arm64. Temporary plain-text source fixture, no analysis provider. Natural incidence, other operating systems, and compiled CLI/MCP race reproduction: **NOT_ENOUGH_INFO** (not run/measured). Searched open/closed reports for `Reference root changed` and reference-root partial failures; #3401 covers initial admission diagnostics, and #5135 covers readlink replacement. No credentials or sensitive target data included.
bsakaguchi 2026-10-31 00:37:19 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
Author
Owner

@morluto commented on GitHub (Oct 19, 2026):

Fixed on main in 6296fdf56, addressing #5135 and #5136 together.

The producer now handles replacement EINVAL at the actual readlink boundary rather than widening the generic I/O catch. An admitted root's later enumeration failure has its own typed rootFailure field; it is no longer fabricated as a child entry at .. The shared reader uses that fact for unresolved symlink coverage, and the importer projects it as a root-level graph limitation. Revalidation preserves the validator's parsed failure code/reason. Initial admission, cancellation and cleanup errors keep their separate outcomes; previously observed child facts survive.

Validation: the final isolated regression file failed all 4 cases on unchanged baseline 95c8f57aa, then passed after the fix. Cases exercise reader and importer with a real nested symlink→regular replacement and host EINVAL, plus real child/root renames after the actual root directory handle closes. Nesting guarantees the sibling was observed before descent rather than assuming OS enumeration order. The final focused run passed 106 checks across 14 reader/application/domain/compiled-CLI files, with 2 Windows-specific cases skipped on macOS. This includes existing mixed read/close failure and cancellation/cleanup ownership tests, and a root-coverage regression retaining nearer completed directories/exclusions. Full static/architecture checks, docs checks and 1604-file discovery passed.

Six stable compiled import-reference-source --json controls preserved the exact full graph digest. Repeated-process medians: elapsed 0.385→0.387 s, CPU 0.599→0.601 s, sampled process-family RSS 401.5→401.3 MB; arguments 33 and full response 281 cl100k-estimated tokens in both versions. One first and two repeated fresh processes per variant; OS caches were not flushed. No optimization claim, actual model usage, large/fault costs, or cross-host result is inferred.

The race scheduling is injected around real filesystem operations. Compiled CLI stable imports and ordinary failure projections were exercised; the race regressions themselves run through the production reader/application boundary, not a compiled CLI race. Native engines and Windows/Linux race behavior were not qualified. Existing directory-handle cleanup ownership remains intact. The breaking marker documents the partial-reader migration from the invalid . child to rootFailure.

<!-- gh-comment-id:6257196765 --> @morluto commented on GitHub (Oct 19, 2026): Fixed on main in [6296fdf56](https://github.com/morluto/rea/commit/6296fdf560f1ac4aa55985558edaa98300aacdbc), addressing #5135 and #5136 together. The producer now handles replacement `EINVAL` at the actual `readlink` boundary rather than widening the generic I/O catch. An admitted root's later enumeration failure has its own typed `rootFailure` field; it is no longer fabricated as a child entry at `.`. The shared reader uses that fact for unresolved symlink coverage, and the importer projects it as a root-level graph limitation. Revalidation preserves the validator's parsed failure code/reason. Initial admission, cancellation and cleanup errors keep their separate outcomes; previously observed child facts survive. Validation: the final isolated regression file failed **all 4 cases on unchanged baseline `95c8f57aa`**, then passed after the fix. Cases exercise reader and importer with a real nested symlink→regular replacement and host `EINVAL`, plus real child/root renames after the actual root directory handle closes. Nesting guarantees the sibling was observed before descent rather than assuming OS enumeration order. The final focused run passed **106 checks across 14 reader/application/domain/compiled-CLI files**, with 2 Windows-specific cases skipped on macOS. This includes existing mixed read/close failure and cancellation/cleanup ownership tests, and a root-coverage regression retaining nearer completed directories/exclusions. Full static/architecture checks, docs checks and 1604-file discovery passed. Six stable compiled `import-reference-source --json` controls preserved the exact full graph digest. Repeated-process medians: elapsed 0.385→0.387 s, CPU 0.599→0.601 s, sampled process-family RSS 401.5→401.3 MB; arguments 33 and full response 281 cl100k-estimated tokens in both versions. One first and two repeated fresh processes per variant; OS caches were not flushed. No optimization claim, actual model usage, large/fault costs, or cross-host result is inferred. The race scheduling is injected around real filesystem operations. Compiled CLI stable imports and ordinary failure projections were exercised; the race regressions themselves run through the production reader/application boundary, not a compiled CLI race. Native engines and Windows/Linux race behavior were not qualified. Existing directory-handle cleanup ownership remains intact. The breaking marker documents the partial-reader migration from the invalid `.` child to `rootFailure`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3159
No description provided.