Repository navigation
fix(architecture-audit): repair reachability drift detection (#187) - #1215
Draft
0xPlayerOne wants to merge 5 commits into
Draft
0xPlayerOne wants to merge 5 commits into
0xPlayerOne wants to merge 5 commits into
Conversation
…it with regression checks The CP #187 reachability audit could not detect several real drifts, and its controller discovery reported reachability for routes the API does not serve under the operation's own HTTP verb. Repairs in scripts/architecture-audit.mjs: - Controller routes are discovered per HTTP verb and carry their method, so reachability matches method and path instead of the path alone. The Nest URI-versioning defaults are read from the application, so a controller that pins VERSION_NEUTRAL is served unversioned instead of being dropped. - Profile port bindings are compared as a map, so a reordered but identical binding map is no longer read as drift. - Evidence must be a repository-relative regular file inside the audited checkout; absolute and escaping paths and directories are rejected. - Only HTTP verbs are read from an OpenAPI path item, and an OpenAPI operation with no SDK binding is now an error. - Served routes with no SDK binding, the Control API capability bindings that default to an unavailable implementation, and the per-profile set of capabilities a profile never binds are reported as warnings. - The persistence parity inventory must agree with the parity rows it summarises; the Bun lockfile workspace version is compared with the manifest; and the migration registry of both dialects is measured, with a PostgreSQL registry whose SQL files and journal disagree treated as an error. - A profile pair that shares one composition source digest is reported. The rendered report is unchanged, so the canonical architecture artifact and its generated report stay with their current owner. New scripts/m11-architecture-audit-regression.test.mjs holds 16 deterministic negative drift checks that fail closed on each of these conditions. It sits next to the tool it covers because it imports the audit script directly, and the workspace boundary rule rejects an import that leaves a package directory; a copy under tests/ would also require lane registration this work does not own. New docs/evidence/m11-architecture-reachability-trace-2026-10-21.md records the four-profile reachability trace, the final-candidate readback of the canonical audit against the current tree, the contract/OpenAPI/schema/ migration/SDK and SQLite/PostgreSQL parity matrices, the dead ends and disabled bindings, the independent re-verification of the retained state-machine, race and restart evidence, and the findings routed to their exact source owners.
The capability-binding detector matched names, so it read a commented example, a type-only declaration and an explicit `undefined` binding as a runtime binding. That can conceal a missing default: a capability named only in a comment, only in a type, or bound to `undefined` is in fact served by the Control API from its unavailable implementation. bindsCapabilityOption now reads the source with the TypeScript parser, so the language decides what is code, what is a type and what is a comment. A capability counts as bound only when a runtime object literal assigns it: a property assignment with a real value, or a shorthand property whose value is not `undefined`. A name in a comment, a `type` alias member, an `interface` member, a class property signature, a member access and an explicit `undefined` are not bindings. The measured per-profile binding matrix is unchanged: cloud binds 20 of the 21 unavailable-default capabilities, hosted-server 13, hosted-simple 16 and local 16, and the same capabilities remain unbound in each. The complete output of the architecture audit is byte-identical to the previous head. The parse is memoised per file identity (size and modification time), so repeated discovery in one process does not re-parse the tree. The dedicated regression file grows from 16 to 22 tests: one per reported finding (commented example, type-only declaration, explicit `undefined`), one for the positive runtime cases, one proving a commented binding cannot conceal a missing default in a real profile source, and one pinning the measured per-profile counts. docs/evidence/m11-architecture-audit-binding-detector-handoff-2026-10-21.md records the correction, the proof that the measurement did not change, the gate results and the proposed CI lane and owner handoff, which is proposed only and not applied.
…by symlink The evidence check resolved a path against the repository root, verified the result lexically and then followed symlinks for the file test. A symlink inside the repository that points outside it was therefore accepted, so an in-tree evidence path could cite a file anywhere on the host. validateEvidence now delegates to evidencePathError, which compares the repository root and the evidence target as canonical real paths. The root is canonicalised too, so a checkout reached through a symlinked path does not make every in-tree path look like an escape. The target is canonicalised before it is examined and the file test is applied to the canonical target, so no symlink is followed to a file outside the root. A target that cannot be resolved, for example a symlink loop, is rejected instead of being mistaken for a missing file. Ordinary in-tree evidence is unchanged: the repository has no symlink outside node_modules and dist, all 116 evidence paths in the canonical audit are regular existing files, and the canonical audit still validates with zero errors. The complete output of the architecture audit is byte-identical to the previous head. The dedicated regression file grows from 22 to 25 tests. The new evidence tests are hermetic: they build a synthetic repository root in a temporary directory with a synthetic target outside it, a symlink from the root to that target, an ordinary in-tree file, an in-tree symlink that stays inside the root, and a symlink that cannot be resolved. The external target holds only synthetic text, no real or sensitive file is read, and nothing is written into the checkout. This bundles into the same branch and draft pull request as the binding-parser repair. The handoff packet now covers both root findings, the proof that neither changes a measured value, the gate results and the proposed CI lane and owner handoff, which is proposed only and not applied.
… parsed The parsed-source cache was keyed by the relative path and validated by modification time and size, while the parse target was resolved against the checkout root. Sequential audits of two checkout roots could therefore reuse the wrong checkout's parse: the matching files had the same relative path, the same size and the same timestamp, and the second root reported the first root's answer. The cache entry is now keyed by the canonical target path and validated by the SHA-256 of the file contents, so an entry is reused only for the same canonical file with the same bytes. The parse is still reused, so the cost does not regress. The new regression is hermetic and deterministic: two synthetic checkout roots are written with contents of exactly the same byte length, one binding the capability and one binding it to undefined, and every file is given the same fixed modification time with utimes. The fixture asserts the two lengths match. Auditing the first root and then the second root in one process must produce different answers; against the previous cache the second assertion fails. The handoff packet records the scope inspection root asked for. The six admitted profile sources contain 20 shorthand capability bindings, each with a unique declaration that encloses the shorthand site, so no admitted source exercises shorthand shadowing or a lexical-scope divergence. The conservative first-declaration rule is therefore exact for the admitted sources; its limits and both possible error directions are documented, together with the pinned per-profile counts that would fail if a composition started declaring a capability name twice. This preserves the reviewed comment, type and undefined parser fixes and the realpath evidence-containment regression. The measured capability matrix is unchanged and the architecture audit output stays byte-identical to the previous head.
…ions The regressions for the three reviewed repairs are extended from the published draft pull request head, and the owned trace and handoff packets are finished. The parse cache now proves both halves of its identity. The existing check covers two checkout roots whose matching files share a relative path, byte length and modification time; it now also audits the first root again afterwards, so the second root cannot have overwritten the first root's entry. A second check rewrites the same paths with the same byte length and the same modification time and requires the sources to be parsed again, because the content hash is the change identity. Both checks fail against the previous relative-path keyed cache. The lexical-scope limit is pinned honestly. The detector resolves a shorthand property by taking the first declaration of that name anywhere in the file, so the answer follows file order rather than lexical scope. The new test shows an inner shorthand that binds undefined in both orderings being reported as not bound in one and as bound in the other. The test records what the rule does; it does not claim the rule is right, and it keeps the limit visible. The architecture trace packet is finished: it labels every per-profile reachability, capability binding and port statement as a static inventory of the sources rather than a runtime observation, records the three corrections made after the base head, updates the drift-check inventory to the current 28 tests, and separates the focused static checks from the wider suite that needs cross-fleet capacity to be rechecked first. The handoff packet records the pinned dependency resolution and the toolchain state, and the extended regressions. No runtime-profile proof is claimed and CP #187 is not claimed complete.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft PR published from the verified owner commit; auto-merge is off. This description records the bounded contribution and remaining acceptance gates.
20261021-f2w3-cp187-binding-and-evidence-path-repair-04d5356e88-2e73-49c1-bd22-4b9f8b2be4ac; terminal done, exit 0, cleanup confirmed.f2w3/cp187-architecture-audit//tmp/opencode-fleet-2-20261021/worktrees/F2W3.27f17bd55e0266439b5b3089163195c9e7a669be; head:fc169f506ec98432883af6cd26bcc8a0101570f3; tree:7e4f42e071f382b87ce8b9a46d3d95a32311dcae; clean; base ancestor verified.9e152c877711f268c6e691140cdc3371db22f0edc302f91157bf38b7f63b46be.docs/evidence/m11-architecture-audit-binding-detector-handoff-2026-10-21.mddocs/evidence/m11-architecture-reachability-trace-2026-10-21.mdscripts/architecture-audit.mjsscripts/m11-architecture-audit-regression.test.mjsFollow-up: cache-isolation regression repair
Published checked owner commit
70017bd9ae7a46a8a58aada372f9e75166004d02(tree824101a05885d18569cb48f8fb7acfbf51dee4a4), three files. It adds a deterministic regression for same-path/same-size/same-mtime source roots with different content; the architecture cache now keys by canonical path and validates content SHA-256.Checks: focused regression 26/0 (188 assertions); W1 architecture regression 7/0 (193 assertions);
bun run architecture:check, changed-file format and lint passed. No full build, coverage, or smoke run. Profile-source scan observed 20 shorthand bindings and no lexical-scope mismatches; live/production acceptance remains open. Patch SHA-256:9972ee2159c81b5ad8018ce3e7d4e2138cc8627c4b084729ccd6083ae64643aa. This is still a draft and not an issue closure.