Second AMEND from the verifier. Five blockers, all inside the 16-path fence; no
new path taken and no GREEN implemented.
1. The run carried an out-of-band `process.exit unexpectedly called with "1"`,
raised by main.ts:71 self-invoking on import and rejecting after the importing
case had returned. Vitest attributes that to no case and warns it can produce
false positives; it also falsified the document's "zero non-assertion
failures". The import is now wrapped so `process.exit` is stubbed
non-throwing and the case awaits a settle turn — the behavioral red is
unchanged, the error is owned, and the run reports `Errors 0`.
2. Two inventory cases demanded the raw values 'standalone' and 'postgres',
which the value-free classification unions cannot represent, so no compliant
implementation could have turned them green. They assert 'non-local' and
'non-pglite'.
3. SourceReadability gained `absent`. Without it an absent source has to be
reported `readable` — the one value meaning "read, and clean" — collapsing
the distinction the refusal path is built on. The invariant
`present === false` iff `readability === 'absent'` is now asserted per state
and across all seven rows at once.
4. Acceptance #6 had no positive anchor: an empty `bootstrap()` and an
always-refusing `onModuleInit()` satisfied every case, so "safe" could have
meant "does not work". Two cases now fail against that — bootstrap must reach
NestFactory.create and listen under the frozen policy with zero independent
read, and the sterile local lifecycle must actually run both migrations with
no Postgres handle. Both in-process and substituted at their seams; no port
is bound and nothing connects.
5. Every mkdtemp site in the six files now registers teardown at the point of
creation, including the child route's root created inside the spawn
arguments. The matrix leaves zero /tmp/kbn-02a-* residue, measured.
Focused matrix: 82 failing / 16 passing (98 cases, 6 files), Errors 0.
Typecheck, lint, Prettier, diff --check clean.
Author phase only; still no implementation. Kept as a distinct fifth commit so
the RED baseline, the contract restoration, the span audit and this supplement
remain separately reviewable.
The finding that mattered: every frozen-policy case mocked ./main.js wholesale,
so nothing executed main.ts, AppModule or the ConfigModule provider, and the
three independent reads at main.ts:28, app.module.ts:39 and config.module.ts:12
could all have survived a fully green matrix. Fence revision 15 -> 16 (granted
solely for apps/gateway/src/main.spec.ts) is used to import the real modules
with no ./main.js mock and assert no independent loadConfig, no tier probe and
no NestFactory.create. The existing anchoring case is left red-in-place rather
than deleted: its import-time-exit premise is the opposite of the new contract,
so it must be migrated by whoever implements GREEN.
Also closes: the executed dev:local child-process route, which requires a
LOCAL_START_* code AND the absence of the BETTER_AUTH_SECRET throw, since a
nonzero exit alone is satisfied by a crash; the real database onModuleInit
lifecycle, asserting migrations never run; the full disposable state-root
contract (absent, not-a-directory, symlink, non-private, foreign-owner), with
ownership substituted at lstat because a filesystem-built case passes trivially
wherever CI runs as root; unreadable and malformed sources, which refuse rather
than being skipped, built as EISDIR so they cannot be vacuous under any uid;
per-source non-local tier detection for all seven labels; canary retention and
console cases; post-freeze source-mutation cases; and a three-form static-import
guard.
Two defects of my own are fixed rather than papered over. The non-canonical
state-root case normalized to the valid path before the policy saw it, so it
demanded a refusal on input identical to the accepted one — a red that could
never go green for its stated reason. And the first substitution of @nestjs/core
was wholesale, which dropped APP_GUARD and killed app.module.ts at import, so
two cases failed for a reason they did not state.
Classification types are unions, not strings: a declaredTier?: string is
value-free only by convention, and a two-member union cannot carry a canary.
77 failing / 15 passing (92 cases, 6 files). Typecheck, lint and Prettier clean.
Zero non-assertion failures. Seven of the fifteen greens are vacuous against the
stub, up from three; that rise is recorded in the document so it cannot later be
read as coverage. The first RED report's implication that the GREEN targets were
covered behaviorally is corrected there too.
Refs: KBN-101-02a (Stack #1178)
Scrappy's ruling, verified independently at
docs/scratchpads/771-kbn101-db-role-split.md:98, which records
apps/gateway/Dockerfile explicitly as 'a planned KBN-101-05 artifact'.
The row names something intended to exist, not a mis-naming of
docker/gateway.Dockerfile, so it is not the inverse defect I filed it as.
The correction sharpens the proposed control: a link check failing on any
absent ownership path would have flagged this row and been wrong. The
check needs a planned marker, and an unmarked absent path is the failure.
Negative existence evidence retained; classification corrected.
Commissioned with -02a on the board ruling. Four findings: the -02
local-start hold is carried by eight files not five (AGENTS.md and
README.md among them, so -02a's completion surface is wider than its
record); a candidate defect of the same shape at -05, whose scope row
contains neither 'process-exec' nor 'LoadCredential' though three guides
condition deployment on that interface; a negative result confirming the
-00/-03/-05 activation hold spans correctly; and the structural hole that
makes all of them unverifiable, whose inverse form is the -05 rows naming
apps/gateway/Dockerfile, a path that does not exist.
Additive to section 10 only. No other item's rows altered; the Dockerfile
discrepancy is reported, not corrected — that row is -05's.
b4c468b3 wrote the -02a path-ownership manifest OVER the frozen KBN-101
contract (#774, #902) rather than appending to it, deleting 272 lines
including the KBN-101-05 exclusive-ownership row, the K101-REQ-04
traceability row and the -03 runner/manifest contract.
Sections 1-9 are restored byte-identical to 216cd722. The -02a amendment
is re-added as additive section 10 with its headings demoted. No other
item's ownership rows are altered.
Self-reported to the verifier; the defect class is the same span/scope
failure -02a exists to close.
Author phase only. No implementation: the scaffolding is deliberately
permissive so every refusal assertion fails behaviorally rather than on a
missing module. A `not implemented` throw would have satisfied `.toThrow()`
and produced a green matrix that proved nothing.
Adds the path-ownership manifest and 60 behavioral cases across the nine
mutation->guard rows: inherited env, shared dotenv, daemon JSON, app JSON,
root JSON, MOSAIC_GATEWAY_HOME redirect, exact local tier, exact PGlite plus
disposable state root, and one-shot freeze with dynamic import.
50 red / 10 green. Zero non-assertion failures. The ten greens are itemized
in the manifest, including three that are vacuous until the implementation
exists.
Enforcement sits at the apps/gateway seam. Nothing in packages/db or
packages/config is touched: -02a proves the local entrypoint never reaches
those paths rather than modifying code owned by -01, -03 and -10.
Refs: KBN-101-02a (Stack #1178)
First-pass structural reference for the Vite SPA migration (apps/web): dual-app
tree during migration, shared lib/ networking layer, origin-relative/same-origin
serving model, build scripts, the P1-P6 increment map, and the #1145 P5 blocker.
Living doc — details to be fleshed out by follow-up.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
Docs-only plan PR. FRED_APPROVED_REF=0629361ca39a4dd7fb3e575d11c64bea9e545dae (review 147). Merged by fred (orchestrator) via API: pr-merge.sh policy predates the next lane (main-only hardcode) — wrapper fix tracked separately.
Co-authored-by: Velma <[email protected]>