Repository navigation
Prove the M0 legacy/canonical isolation boundary (REQ-MIGRATION-004) - #43
Conversation
Adds a static cross-runtime reference scanner (src/diagnostics/isolationBoundary.ts) that audits src/**/*.ts and TradeCraftSimulation/**/*.cs for textual evidence one runtime names the other's implementation, with fixture-based negative-control tests proving the scanner rejects a genuine prohibited reference. Documents scope and limits in docs/spec/MIGRATION_BOUNDARY.md. Also reconciles the REQ-MIGRATION-002 row in IMPLEMENTATION_STATUS.md now that PR #40 (closing Issue #39) has merged at 6063ed9, per AUTHOR_RUNBOOK.md section 1. Closes #41 Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Operator QA: REQUEST_CHANGESHead bfe8969. This is an operator QA finding with a reproduced false negative, not a substitute for the independent ACCEPTOR merge decision.
Please repair within #41, update the current-head handoff, and rerun all checks. No workflow permission, economic change, or broad scanner redesign is requested. Temporary local reproducer files were removed; no PR branch content was changed by this review. |
ACCEPTOR verdict: REQUEST_CHANGES(Posted as a comment: GitHub refuses a same-account review — "Review Can not Head I independently reproduced the defect the operator QA comment above flagged Defect — exclusion bypass in the isolation-boundary guard itself const GUARD_MODULE_BASENAME = "isolationBoundary";
function excludingGuardModule(files: SourceFile[]): SourceFile[] {
return files.filter((file) => !file.path.includes(GUARD_MODULE_BASENAME));
}This is a substring match on the whole relative path, not an exact match on the This fails the Issue's own acceptance criterion: "Add a named automated regression What would satisfy it: narrow the exclusion to an exact, normalized Secondary, lower-severity: Per |
There was a problem hiding this comment.
Confirmed at bfe8969: the substring-based exclusion in excludingGuardModule silently drops src/domain/isolationBoundaryBridge.ts from the repository audit despite its prohibited legacy import. Both operator QA and ACCEPTOR independently reproduced the false negative. Please implement exact normalized path exclusions, a full-audit negative control for similarly named files/directories, and the CI check-name correction documented in #43 (comment) . All existing checks must be rerun at the corrected head. This formal review restates the same defect, not a new scope.
excludingGuardModule matched any path containing the substring "isolationBoundary", so a genuine prohibited cross-runtime reference in a similarly-named file (e.g. src/domain/isolationBoundaryBridge.ts) silently escaped the real-tree audit. Both operator QA and the ACCEPTOR independently reproduced this against PR #43's head. Narrow the exclusion to exact, normalized repository-relative paths for the guard's own two files, and add a negative-control test that drives the fixture through the full auditRepositoryIsolationBoundary traversal (not just the pure scan) to prove the bypass is closed. Also correct MIGRATION_BOUNDARY.md, which named build-and-test as the check running npm test; per ci.yml that's the typescript job. Closes #41
abogun-product
left a comment
There was a problem hiding this comment.
Operator QA finding resolved at e814eca. Inspected the exact normalized two-path exclusion and full traversal negative-control test; reproduced the original false negative earlier, and the new full-audit regression now passes on Windows. Independently ran clean npm ci, typecheck, all 11 TypeScript tests, Vite build and policy_guard (passed). All three required CI checks are SUCCESS at this head in run 33872690685, including legacy .NET tests. The CI job-name documentation correction is present. This resolves my previous formal change request; final independent acceptance/merge remains with the ACCEPTOR workflow.
ACCEPTOR verdict: ACCEPTHead
No changes to |
…IZATION-003) (#45) * Publish the M0 Milestone Preview on existing GitHub Pages (REQ-VISUALIZATION-003) Adds a "Migration status" panel to docs/index.html that reads a static one-way JSON diagnostic (docs/m0-preview.json) showing the M0 milestone label, the frozen legacy baseline seed/turns/hash, and the canonical TypeScript scaffolding status. A Vitest regression test keeps the JSON honest against docs/spec/LEGACY_BASELINE.md and src/index.ts's real toolchainStatus(). Also carries the AUTHOR_RUNBOOK section 1 reconciliation: REQ-MIGRATION-004 flips to IMPLEMENTED now that PR #43 has merged. * Fix M0 preview panel CSS grid overflow at narrow viewports The two-column CSS grid dl layout blew out at narrow widths (each hash character on its own line, horizontal overflow) — verified with a headless-Chromium screenshot at 360px. Replaced it with a simple stacked label/value layout, re-verified at 360px and 1280px. * Normalize CRLF before parsing LEGACY_BASELINE.md in m0Preview test An LF-only fence regex silently failed to find the expected-hash on a Windows checkout, where docs/spec/LEGACY_BASELINE.md is checked out with CRLF line endings (npm test 14/15 on Windows, per PR #45 review at 23a58b4). Extract the parsing logic into a pure function that normalizes \r\n to \n first, and add a regression covering both LF and CRLF input directly, without depending on the checkout's own line endings. Addresses changes requested on PR #45 (#42). --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
) GitHub refuses a same-account formal review, so ACCEPTOR sometimes posts its REQUEST_CHANGES/ACCEPT verdict as a PR comment instead of a formal review. AUTHOR_RUNBOOK section 2 item 1 only described the formal-review path, so a real change request could go unaddressed while a later run reported green with nothing fixed (Issue #44, reproduced from PR #43 / Issue #41). Add exact detection steps for both verdict forms, tied to the pull request's current head so a superseded comment can't cause repeat work or an endless retry, and tighten item 6's trigger so a run that finds nothing eligible after 1-5 always leaves a durable record instead of exiting silently. Closes #44 Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Closes #41
Achieved outcome
The M0 legacy/canonical isolation boundary (REQ-MIGRATION-004) now has automated
evidence, not just inspection. A static cross-runtime reference scanner audits every
.tsfile undersrc/and every.csfile underTradeCraftSimulation/for textualevidence that one runtime names the other's implementation, and a regression test
proves the real repository currently has zero such references. Three negative-control
tests prove the scanner actually rejects a genuine prohibited reference rather than
passing vacuously, including one that drives a similarly-named-but-distinct fixture
through the full
auditRepositoryIsolationBoundarytraversal — closing a realexclusion-bypass defect that operator QA and the ACCEPTOR independently reproduced
against this PR's first revision (
bfe8969). The boundary, the check's coverage andits explicit limits are documented in
docs/spec/MIGRATION_BOUNDARY.md.This PR also carries the AUTHOR_RUNBOOK.md section 1 reconciliation: the
REQ-MIGRATION-002row indocs/spec/IMPLEMENTATION_STATUS.mdreferenced Issue #39and a "pending PR"; that PR (#40) has since merged, so the row now records its merge
commit and proving test and moves to
IMPLEMENTED.Fix for review round 1 (operator QA + ACCEPTOR, both CHANGES_REQUESTED)
At
bfe8969,excludingGuardModulefiltered files withfile.path.includes("isolationBoundary")— a substring match on the whole path, notan exact match on the guard's own two files. Both operator QA
(#43 (comment)) and
the ACCEPTOR independently reproduced a real false negative: a file such as
src/domain/isolationBoundaryBridge.ts, containing a genuine prohibitedTradeCraftSimulationreference, silently escaped the real-tree audit because itspath merely contains the text
isolationBoundary.Fixed at
e814ecaby:excludingGuardModuleto an exact, normalized repository-relative pathmatch against
diagnostics/isolationBoundary.tsanddiagnostics/isolationBoundary.test.tsonly (GUARD_MODULE_RELATIVE_PATHS);file in a temporary directory and runs it through the real
auditRepositoryIsolationBoundarytraversal (not just the purefindCrossRuntimeReferencesscan the original two negative controls used) to provethe bypass is closed;
docs/spec/MIGRATION_BOUNDARY.mdsaid thebuild-and-testrequired check runsnpm test; per.github/workflows/ci.ymlthat's actually thetypescriptjob(
build-and-testis the legacydotnetjob). Also expanded the doc's descriptionof the exclusion to state it is an exact-path match and to name the new test.
Tested revision
e814eca5317d39d1c79d82fd90346262605a8290Changed artifacts
src/diagnostics/isolationBoundary.ts—collectSourceFiles(recursive filewalk),
findCrossRuntimeReferences(pure scan over in-memorySourceFile[]), andauditRepositoryIsolationBoundary(wires the two marker lists —CANONICAL_INTO_LEGACY_MARKERS,LEGACY_INTO_CANONICAL_MARKERS— against the realsrc/andTradeCraftSimulation/trees). The guard's own module/test files are nowexcluded from the real-tree audit by exact repository-relative path, not substring.
src/diagnostics/isolationBoundary.test.ts— the real-tree audit assertion, threenegative-control tests (two pure-scan fixtures, one full-traversal
similarly-named-file fixture via a temporary directory), and one "does not flag an
unrelated marker" sanity test.
docs/spec/MIGRATION_BOUNDARY.md— the two entry points and their authoritativestocks as they exist today, what the guard checks, the exact-path exclusion and what
the negative-control tests (including the new one) prove, the corrected required
check name, and an explicit "limits of this evidence" section.
docs/spec/IMPLEMENTATION_STATUS.md— flipsREQ-MIGRATION-002toIMPLEMENTEDwith PR Pin the expected seed-7/30-turn legacy baseline hash (REQ-MIGRATION-002) #40's merge commit and proving test;
REQ-MIGRATION-004row staysIN_PROGRESS, now naming this PR (Prove the M0 legacy/canonical isolation boundary (REQ-MIGRATION-004) #43) and the third negative-control test.package.json/package-lock.json— adds@types/node(devDependency only) soisolationBoundary.tscan importnode:fs/node:path/node:osunder stricttypecheck.
tsconfig.json— adds"node"to thetypesarray alongside the existing"vitest/globals".Acceptance criteria
shared authoritative stock write/bridge in the current M0 implementation — see
the "two entry points" table in
docs/spec/MIGRATION_BOUNDARY.md.negative control proving the check rejects an intentionally introduced
prohibited bridge/dependency, using a contained test fixture rather than a live
bridge — three tests in
src/diagnostics/isolationBoundary.test.ts:rejects a canonical file that imports the legacy tree,rejects a legacy file that reads canonical module output, and (new)auditRepositoryIsolationBoundary rejects a similarly-named-but-distinct file that the guard-module exclusion must not swallow, the last of which exercisesthe real traversal path where the original bypass lived.
obligation in later milestones — "Limits of this evidence" in
docs/spec/MIGRATION_BOUNDARY.mdis explicit that this is a source-level guard,not a runtime/CI-wiring proof, and that the marker lists may need extending once
canonical stocks exist from M1 onward.
remain green — 11/11
npm test(6 files; 1 new negative control added thisround), 45/45
TradeCraftSimulation.Tests, unchanged.see Checks below.
REQ-MIGRATION-004is recorded asIN_PROGRESS, referencing this Issue and "pending PR Prove the M0 legacy/canonical isolation boundary (REQ-MIGRATION-004) #43", notIMPLEMENTED,until this PR merges and a future run records the merge commit.
Checks
npm cie814ecanpm run typechecknpm testnpm run builddist/canonical.jsbuilt (unchanged — the guard is not part of the public entry point)dotnet restoredotnet build --configuration Releasedotnet test --configuration Releasepython3 scripts/policy_guard.py --base origin/masterpython3 -m unittest discover -s scripts/testsNot checked
Nothing required by this Issue's Verification section was skipped. The guard is not
wired as a CI job distinct from
npm test— it already gates every PR as part of theexisting
typescriptrequired check (corrected from the earlier, wrongbuild-and-testattribution), but a reviewer looking for a separately named"isolation boundary" job in CI will not find one; this is noted explicitly in
docs/spec/MIGRATION_BOUNDARY.mdrather than left implicit.Assumptions and unknowns
be defeated by a straightforward literal reference (an import path, a
File.Readcall, a namespace name), which is the realistic shape a prohibited bridge would take
at M0 given the two runtimes cannot share memory in-process, but it could in
principle be defeated by deliberate obfuscation (string concatenation, indirection
through a config value). Given no untrusted contributor path exists in this
repository's authoring model, that is judged out of scope for M0 rather than a gap
to close now.
@types/nodeis pinned to^22.20.1, matching the existingengines.node: ">=22"constraint; it is a type-only devDependency and does not change runtime behavior or
the build output.
Highest-risk area for review
The same file as before, now fixed and independently verified by re-running the
reviewer's own reproduction shape as a permanent test:
src/diagnostics/isolationBoundary.ts'sexcludingGuardModule. It now matches onlythe two exact, normalized repository-relative paths of the guard's own module and
test file, and a temporary-directory-backed negative-control test proves a
similarly-named-but-distinct file is not swept up by the exclusion. A reviewer should
confirm the exact-path set really is limited to those two files and that the new test
genuinely exercises
auditRepositoryIsolationBoundary(the real traversal entrypoint) rather than only the pure scan function.
Remaining gate
None for this Issue's scope. This PR does not merge itself — it is handed off again
for independent ACCEPTOR review per
AGENTS.md.