Files
stack/docs/plans/reviews/2026-09-06_foundation-inspector-rocko-build.md
jason.woltje 8ebddd6f93 feat(foundation): offline synthetic scope/permission inspector (FI-FILBERT-8 APPROVED r6)
Rocko-authored, Filbert-reviewed inspector (r6 manifest
a4a44930...) with full review/build/verdict evidence under
docs/plans/reviews. 43/0 selftests, oracle zero-disagreement,
foundation checker PASS. Owner A9 acceptance recorded separately.
2026-09-07 14:06:35 -05:00

321 lines
26 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FI-ROCKO-3 — synthetic inspector build report (review candidate)
Writer: rocko (sole implementation writer). Requester/integration owner: darkwing.
Independent reviewer: filbert (not yet dispatched to code review). Issue: #53.
Status: **delivered as a frozen review candidate, not accepted work.** No owner
acceptance is claimed. Code and fixtures are frozen at the hashes below until
darkwing reconciles filbert's findings; only rocko fixes owned code, producing a
newly hashed candidate.
## 1. Admission (returned 2026-09-06T17:05Z; unchanged)
- Compatible, no blocker. Archify C1 rev 3 stays bound and HELD for Jason's T2/T3
rulings (waiting state, no due action); nothing was displaced.
- All authorized paths were absent at admission and are new untracked files now.
No other helper path or specification decision was needed; nothing outside the
allowlist was written.
- Build request identity: admitted at sha256
`fd70962f36f81c515ffefae21fd9e56f90655718067bca8db11a9fc510fbb455` (17:01Z read).
The file on disk now hashes
`90a1f329e859152d4ce8e157cbd6c56e6bcced16b4ed757822d2309514fa9a15` (mtime 17:02:59Z).
Verified by diff against the copy read at admission: the only change is the
appended "Transport (2026-09-06 17:02 UTC)" footnote; the contract text is identical.
## 2. Pinned contract inputs versus measured integration state
| Input | Identity |
|---|---|
| Charter candidate 3 `docs/plans/2026-09-06_foundation-inspector-charter.md` | sha256 `19b6721128a627a2032ffdb95ece2d50abe69a8f6d521e9eff8bbdaff22798b6` |
| Filbert verdict r3 | sha256 `15f3d04cb74a7296be6a1a26f2c0907b9dd2b08fdd1eb0ef51c95c7a52ff0399` |
| r2 feasibility note (incorporated, overridden by charter §10) | sha256 `f2f47fcfe22dca79f10f885b83d87a2f846fdb560425a4e20705c40ce4a123e1` |
| Source/schema baseline | `d4696d09eb1b5dcf1028f30db2cd63735f51cb16` |
| Accepted map | `7345f330fc6bfae5aa1d896c78cfb7cbe62efbae` |
| `docs/plans/foundation-v1-candidate/records.schema.json` | sha256 `05774aaf6943cb69c113e39ff1c29676a2a230ca7bf665c50dbcaa8049672af6` |
| `docs/plans/foundation-v1-candidate/check.py` | sha256 `82564a7d3200afcdda0850a9454cac6e6cd6a76687d2162c13cf214d7eac4607` |
| `docs/plans/foundation-v1-candidate/records.fixtures.json` | sha256 `d433d06da5cd38baf9e51c8857244ee70375db3b68e02a5325a6d1c2cc47da85` |
| Measured integration HEAD (unchanged throughout the build) | `9a5fbdbda74b16adf488fe28138b2ba69ea5e669` |
The three pinned schema/checker files in the working tree hash identically to the
baseline; `verify-schema.py` re-checks these three hashes on every run and fails
closed on mismatch.
Toolchain (measured on this host): Node `v26.8.1`, Python `3.12.8`,
`jsonschema 4.26.0` (existing installation; nothing installed). No repo Node pin
exists; `node --test` (built-in runner) is the only test framework.
## 3. Changed-file list with SHA-256 (the frozen candidate manifest)
All files are new and untracked. Nothing existing was edited.
| File | Lines | SHA-256 |
|---|---|---|
| `scripts/foundation-inspect.mjs` (CLI) | 239 | `bfa1b78007c772c54fe1dab90a53e19e6bce7e4888a5adb2de0b2cfe43c5cddd` |
| `scripts/foundation/strict-json.mjs` | 327 | `7c31fe6be8cd29ee07662a21bb2e490a2ec799e263dec981ee257fcf7e6f6ebf` |
| `scripts/foundation/canonical.mjs` | 87 | `a7760882c4c49992b9d702eb125a3e8f63048be543516b0eba61231018b90172` |
| `scripts/foundation/resolve.mjs` | 1625 | `9ae8b4255b5dc1f1e9b0d36549865268c12dc53f010984eb1e5616b127d1d8a2` |
| `scripts/foundation/validate-record.mjs` (test-only bridge) | 66 | `e4e70f60cce68e535ef98b0627647c440d620432cf8ddaed074df4e252ecde58` |
| `scripts/foundation/verify-schema.py` (verification only) | 453 | `7e3098655b2e5f261391d788c2112a6ffb055895e357b427bc68e5f2fa7b52d7` |
| `scripts/foundation/strict-json.test.mjs` | 145 | `b40488edfc4eba6962e8c0949ddf1f92fdc15d630b7e9bdff72ac6d06bdb092e` |
| `scripts/foundation/canonical.test.mjs` | 106 | `f504321983b2c41eff5af7e6dc27e40e360e0aae299d0a9abc369c743f5384f7` |
| `scripts/foundation/resolve.test.mjs` | 294 | `05f27aa6c8a1b8ff2ee45e5de03a9aea5ed13cf011b2464c5865022dc9781449` |
| `scripts/foundation/cli.test.mjs` | 279 | `b7e9a13c11e3e6f487ada2779c892cdf848526de1ef8b21387d15d4a461ddb62` |
| `scripts/foundation/fixtures.test.mjs` | 93 | `2827de36214c8014471fed3478c42bf48eddb3fbdbff82cac9e27851646b15d2` |
| `scripts/foundation/fixtures/build-fixtures.mjs` (generator) | 908 | `094ecc811b85465cc0748a86b76b75c1784a2e0296f242b6ff2dbd1660b426a9` |
| `scripts/foundation/fixtures/index.json` (204 cases) | | `74988a1dcd4b48b0be2243d3fefff3b6de5d90a947094be201c3486142ca12a2` |
| `scripts/foundation/fixtures/README.md` | | `aba48ba054d09247b048a8955507b87a275cd585870f1f658b7c6b826fc892bd` |
| `scripts/test-foundation.sh` (executable) | 132 | `76fb7ba9da4345271b6ba93228a9da69c7e55c4e44b9f4033e84a8f4b430e8ec` |
Generated fixture trees (deterministic output of `build-fixtures.mjs`; the suite
fails if a checked-in file differs from a fresh generation):
| Tree | Files | Bytes | Manifest sha256 of `find <tree> -type f \| LC_ALL=C sort \| xargs sha256sum` (run in `scripts/foundation/fixtures/`) |
|---|---|---|---|
| `scripts/foundation/fixtures/bundles/` | 185 | 9,235,245 | `a804e4ab253839ba2bb8ad7475d27512b2ef88e70a9779f9093fee5478de4823` |
| `scripts/foundation/fixtures/raw/` | 19 | 1,336,985 | `508ad85208f4b69676f3d041faa4ff4cd4a2f8de74b7bde9b0b89123a8485cc4` |
Owner-demo copies and goldens (`scripts/foundation/fixtures/demo/`, 249,096 bytes):
| File | SHA-256 |
|---|---|
| `demo-read-w1.json` | `7a3cfc58c1356cc2a986e0a6ed8f9f2dffbc33277ea1b7800020bfc55624b750` |
| `demo-read-w1.expected.txt` | `8bfff519ce8275cfe59562efd04647c242c328a09b301b91d70491f030cf1600` |
| `demo-read-w1.expected.json` | `55e10c1693787cd8e39d3a66841d30e2336080d2ae4450a806a7ae8373db476b` |
| `demo-read-w1.expected.exit` (0) | `9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa` |
| `demo-file-change-src.json` | `7c0948d39abd3f1eeb0b0990766cbf584959712000faacaf47ae0d3501def3cc` |
| `demo-file-change-src.expected.txt` | `f5387217ca0a41d437468af33b7d87d06c0c5535ab5490b568f9866a13b2732e` |
| `demo-file-change-src.expected.json` | `88c7793c6af17ca255525451a499d9f8bb165155e50d2ee936bd68ba82a876a7` |
| `demo-file-change-src.expected.exit` (0) | `9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa` |
| `demo-change-w1.json` | `54aad9047f7fe86892889ead543403c42986f591722d0dd23e0e027c3b7191d5` |
| `demo-change-w1.expected.txt` | `2a1090e5f5ad08e2175830943a7c81928de970470893e803b1e440843152c348` |
| `demo-change-w1.expected.json` | `36c287cba327070f7ff3dd9846421bee3ebd0dd52e9c602b68e84fa620ef4fc5` |
| `demo-change-w1.expected.exit` (3) | `1121cfccd5913f0a63fec40a6ffd44ea64f9dc135c66634ba001d10bcf4302a2` |
| `adm-registration-revoked.json` | `ff7b859cd959876b2b6ede97fff90383a38acde765a16294b095ba220290c579` |
| `adm-registration-revoked.expected.txt` | `624c9e5991597d59fc3379343b16e7eab9cb6434f054da3a4df7518742e3b36c` |
| `adm-registration-revoked.expected.json` | `b966d939e0d2851ef731462a0fda932e75f53b9aac406216ad440f781e036d0f` |
| `adm-registration-revoked.expected.exit` (3) | `1121cfccd5913f0a63fec40a6ffd44ea64f9dc135c66634ba001d10bcf4302a2` |
| `prop-message-is-not-authority.json` | `f1c6bd523cdff161e51da156fd00cfaa652d193f41541686548fc023378fd8ab` |
| `prop-message-is-not-authority.expected.txt` | `e7b0e9fa64abe0c0f8c91fbc9aa565988ce76cb3967672bfacafab350e20d8be` |
| `prop-message-is-not-authority.expected.json` | `53884bfdea21185141b9a06d52aa1c0fe8e7bfae6627b465929403521f9bc4d8` |
| `prop-message-is-not-authority.expected.exit` (3) | `1121cfccd5913f0a63fec40a6ffd44ea64f9dc135c66634ba001d10bcf4302a2` |
Reviewer re-derivation (from the repository root):
```sh
sha256sum scripts/foundation-inspect.mjs scripts/test-foundation.sh scripts/foundation/*.mjs \
scripts/foundation/verify-schema.py scripts/foundation/fixtures/build-fixtures.mjs \
scripts/foundation/fixtures/index.json scripts/foundation/fixtures/README.md
(cd scripts/foundation/fixtures && sha256sum demo/*)
(cd scripts/foundation/fixtures && for d in bundles raw; do \
echo "$d $(ls $d | wc -l) $(find $d -type f | LC_ALL=C sort | xargs sha256sum | sha256sum | cut -d' ' -f1)"; done)
```
## 4. What was built (charter mapping)
- `strict-json.mjs` — byte-level strict JSON parser (charter §6, §10.5): UTF-8
validation with distinct codes (`utf8-invalid`, `utf8-overlong`, `utf8-surrogate`,
`utf8-out-of-range`, `utf8-truncated`), duplicate-key refusal with byte offset,
safe-integer-only numbers (no fraction/exponent/`-0`), raw controls in strings
refused, BOM/trailing content refused, bounds: input 1 MiB, string 4096 bytes,
container items 1024, nesting 32 (container nesting; a scalar inside the 32nd
container is depth 32), all reported as `StrictJsonError` with `byteOffset`.
Objects are built with null prototypes (`__proto__`/`constructor` keys are plain
own keys and never pollute).
- `canonical.mjs` — canonical form and `sha256:` digest (charter §6, vectors V1V5):
UTF-16 code-unit key ordering, ASCII-only strings, safe integers only,
depth 64, refusals typed as `CanonicalError` with reason `unsupported-capability`.
- `resolve.mjs` — pure evaluation (charter §§35, §7, §10.110.4): shape gate,
record validation (schema-equivalent field/pattern/enum/calendar/path rules),
identity/duplicate/reference/revision/cycle graph checks in the §10.4 fixed
sub-order, registration/delegation with explicit issuer bounds (§10.1),
structural ownership versus consulted work access (§10.2), direct declared
delegation inputs only (§10.3), mandatory ceilings (agent/project/workspace
policies, scope role, registration, execution, mission/task restrictions)
intersected by least privilege, four supported operations only, and the
reassignment proposal path whose only terminal outcomes are `refused` or
`unresolved` (assignment.change has no allowed branch). Closed vocabularies
`RULES` (108), `REASONS`, `RESULTS`, `PROPOSAL_STEPS`, `SUPPORTED_OPERATIONS`,
`RESULT_KEYS`; `buildResult` throws on any rule/reason outside them.
- `validate-record.mjs` — test-only bridge exposing per-record schema-shape
validity to the Python oracle (stdin JSON in, verdict JSON out). Not used by
the CLI.
- `foundation-inspect.mjs` — CLI: `node scripts/foundation-inspect.mjs [--json] <bundle.json>`.
Opens the input with `O_RDONLY|O_NOFOLLOW`, requires a regular file, refuses
size changes between fstat and read, applies the 1 MiB gate before parsing,
renders text or JSON from one result object, escapes every risky code point in
echoed identifiers/paths, exits with the result's `exit`. Imports only
`node:fs`, `node:url`, `node:path` and the local modules; the only `process.`
uses are `argv`, `exitCode`, `stdout`. It never spawns, never reads env/config/
HOME/cwd, never touches the network. Output starts with
`SYNTHETIC PREVIEW — NO LIVE EFFECTS` and carries the preview/authentication/
declarations disclaimers in both renderings.
- `verify-schema.py` — mandatory differential oracle against the pinned
`records.schema.json` with the explicit `jsonschema 4.26.0`; missing dependency
or hash mismatch is a failure, never a skip.
- Fixtures — 204 deterministic synthetic cases (185 bundles, 19 raw byte-exact
files) generated by `build-fixtures.mjs`, indexed with expected
exit/result/reason/rule/proposalRule (and byteOffset for lexical cases);
5 demo copies with byte-exact goldens.
- `test-foundation.sh` — repository-style selftest (syntax, fixture diff,
`node --test`, oracle, exit receipts, goldens, `env -i` sandbox non-effect and
canary checks).
## 5. Commands and results (all run from the repository root at HEAD 9a5fbdb)
```sh
node --version # v26.8.1
python3 --version # 3.12.8
python3 -c 'import importlib.metadata as m; print(m.version("jsonschema"))' # 4.26.0
node --test scripts/foundation/ # tests 57 pass 57 fail 0
python3 scripts/foundation/verify-schema.py # PASS (see lines below)
NO_COLOR=1 scripts/test-foundation.sh # selftest: 37 passed, 0 failed (rc 0)
python3 docs/plans/foundation-v1-candidate/check.py # PASS: 35 synthetic ... cases (rc 0)
scripts/test-config.sh # selftest: 24 passed, 0 failed (rc 0)
scripts/test-task.sh # selftest: 90 passed, 0 failed (rc 0)
scripts/test-release.sh # selftest: 14 passed, 0 failed (rc 0)
scripts/test-conductor.sh # selftest: 17 passed, 0 failed (rc 0)
scripts/test-auth.sh # selftest: 15 passed, 0 failed (rc 0)
```
Oracle summary lines (verbatim from the final run):
```
PASS: python 3.12.8 jsonschema 4.26.0
PASS: 38 pinned record fixtures agree with the pinned expectations
node v26.8.1; corpus 1431 records (38 pinned fixtures, 410 unique bundle records, 983 typeCase/mutation/lexical cases)
schema column agreement: 1388; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10
known divergences reproduced: 6/6
PASS: differential schema oracle (finite corpus; compatibility evidence, not equivalence proof)
```
Node test breakdown: strict-json 12, canonical 10, resolve 16, cli 14, fixtures 4
(= 57). The five repository suites were run unchanged against the same working
tree; they do not exercise the new code and are reported as integration receipts
only. Unrelated concurrent working-tree changes (not mine, untouched): modified
`BUILD-LOG.md`, `docs/SESSIONS.md`, `docs/plans/CURRENT.md`; untracked
`docs/plans/2026-09-06_*.md`, `docs/plans/foundation-v1-candidate/`,
`docs/plans/reviews/*` (except this report), `skills/ms-*`,
`tasks/foundation-phase2-source-facts.json`.
Git state: HEAD `9a5fbdbda74b16adf488fe28138b2ba69ea5e669` before and after;
nothing staged, committed, checked out, reset or pushed. Only read-only git
inspection was used. A stray `scripts/foundation/__pycache__/` produced by an
earlier `py_compile` syntax step was deleted and the suite now uses an
AST-only parse so no bytecode is written.
## 6. A1A8 coverage (named evidence, not aggregate counts)
Fixture groups from `index.json` (204 cases): positive 14, shape 37, profile 3,
identity 5, structure 5, cycle 4, continuity 2, ownership 9, operation 7,
admission 49, registration-delegation 13, proposal 37, lexical 19. Expected
outcome classes: exit 0 allowed 14; exit 2 invalid 102; exit 3 refused 86;
exit 3 unresolved 2. Every rule in `RULES` except the five CLI/I-O rules is
exercised by at least one fixture (`resolve.test.mjs` enforces this); the CLI
rules are exercised by `cli.test.mjs`.
| Gate | Evidence |
|---|---|
| A1 positive previews | Fixtures `demo-read-w1` (work.read), `demo-file-read-src`, `demo-file-change-src` (assigned file.change), `taskless-file-read`, `taskless-work-read`, `deleg-approved-file-read`, `mission-/execution-/registration-restrictions-narrow-ok`, `work-parent-project-mission`, `file-read-with-unaccepted-dependency`, `p2-inventory-unselected`. Byte-exact text/JSON/exit goldens (`fixtures.test.mjs` "owner demo goldens"); text derived from the same result as JSON (`cli.test.mjs` "text output is derived…"); determinism across HOME/config (`cli.test.mjs` "HOME/config independence"); disclaimer first line and closing `exit:` line checked for all 204 cases. |
| A2 unregistered/cross-project selection | `adm-workspace-registration-missing`, `adm-selected-workspace-missing`, `adm-project-registration-missing`, `adm-selected-project-missing`, `adm-cross-workspace-mission`, `adm-cross-project-dependency`, `adm-assignment-other-workspace`, `own-workspace-project-missing`, `prop-target-cross-project-*`. No fallback: selection shows `assignment null` and result is refused. No unrelated payload: every result is walked against the closed key vocabulary (`resolve.test.mjs` `unknownKeys`), and rendered text is scanned for raw risky code points for every case. |
| A3 graph negatives | Duplicates `dup-record-identity`, `dup-registry-identity`, `dup-artifact-identity`, `dup-authorization`, `dup-delegation-input`; references `ref-missing-*` (5); ownership `own-*` (9); revision/continuity `continuity-revision-gap`, `continuity-supersedes-other-identity`, `shape-record-rev1-with-supersedes`; cycles `cycle-dependency-self`, `cycle-dependency-pair`, `cycle-mission-self-parent`, `cycle-supersedes-self-rev2`. Detector unit tests (`findCycle` self/pair/diamond/missing/20000-node chain, `deepEqual`) are separate from the CLI fixture pass; §10.4 first-failure precedence asserted in `resolve.test.mjs`. |
| A4 ceilings and narrowing | Missing/empty authority: `adm-agent-policy-missing`, `adm-project-policy-missing`, `adm-workspace-policy-missing`, `adm-scope-role-missing`, `adm-authorization-undeclared`, `adm-dependency-grants-nothing`, `adm-policy-ceiling-stale`. Narrowing per layer: `adm-operation-not-permitted-{role,agent-policy,execution}`, `adm-path-not-permitted-{prefix-string,read-execution,task-narrows,write-outside}`, `rdeleg-issuer-ceiling-narrows-path`, `rdeleg-narrows-to-delegated-ops`, `rdeleg-exceeds-issuer-ceiling`. Cross-assignment union impossible: `adm-assignment-other-agent`, `adm-assignment-other-workspace`, `own-assignment-task-other-workspace`; unassigned change `adm-assignment-required-for-change`. Unit: `intersectLayers` (network none dominates, endpoint structural intersection, delegated ops), `intersectGrants`, `pathPermitted`. |
| A5 lexical versus schema/profile | Raw byte cases: `raw-duplicate-key`, `raw-bom-prefix`, `raw-invalid-utf8`, `raw-utf8-surrogate`, `raw-lone-escape-surrogate`, `raw-raw-control-in-string`, `raw-fraction-number`, `raw-exponent`, `raw-negative-zero`, `raw-unsafe-integer`, `raw-string-too-long`, `raw-array-too-long`, `raw-depth-33`, `raw-oversize-file`, `raw-empty-file`, `raw-not-object`, `raw-trailing-content`, `raw-proto-key`, `raw-constructor-key` (each with expected byteOffset). Schema/profile: `shape-record-bad-time`, `shape-record-calendar-invalid`, `shape-record-leap-second`, `shape-record-unknown-field`, `shape-unknown-top-field`, `shape-record-displayname-too-long`, `shape-target-{backslash,control-char,dotdot,empty-segment,wrong-root}`, `shape-registry-content-non-ascii`, `shape-unsupported-kind-session` (unsupported-kind, not invalid), `shape-unknown-kind`. Parser unit tests (12) and the oracle report schema agreement separately from parser-bound (27) and unsupported-kind (10) columns. |
| A6 no effects, no ambient lookup | Static import boundary test: pure modules import only `node:crypto` and local modules; the CLI imports only `node:fs`/`node:url`/`node:path` plus local; `process.` uses are exactly `argv`, `exitCode`, `stdout`; forbidden module names (`node:child_process`, `net`, `http`, `os`, `dns`, `tls`, `worker_threads`, `vm`, …) absent everywhere, and `process`, `Date`, `fetch`, `Math.random` and dynamic `import()` absent from the pure modules. Descriptor checks: symlink → exit 4 `input-open-failed` (O_NOFOLLOW), directory and FIFO → `input-not-regular`, chmod 000 → open failure, size change guard. Inventory comparison (path/type/size/mode/inode/mtime/sha256) of a disposable sandbox with fake HOME/.mosaic credentials, config, cwd, data-root before and after every run kind; canary strings never printed; `test-foundation.sh` repeats this under `env -i HOME=<sandbox> PATH=/nonexistent`. These are bounded evidence, not an OS sandbox proof (see §8). |
| A7 cross-lane proposal | 37 `prop-*` cases plus `demo-change-w1`, `op-change-without-proposal`. Both requester contexts: `prop-requester-context-wrong-{agent,scope}`, `prop-original-requester-{lacks-change,assignment-paused,registration-revoked}`, `prop-original-context-no-work-read`, `prop-target-requester-lacks-change`, `prop-target-{workspace-retired,task-stale,cross-project-*}`. Intent/delegation: `prop-intent-*`, `prop-delegation-*` (10), `prop-change-*`, `prop-message-is-not-authority`, `prop-subject-*`. Original selection preserved: `prop-selection-agent-mismatch`, `prop-selection-null-assignment`, and every proposal's `selectedAssignmentRef` equals the selection. Fully supplied mock evidence cannot yield allowed: `prop-all-pass-restricted-contexts``unresolved / unknown-effects / runtime-reconciliation-required`, exit 3. Index check: all 39 assignment.change bundles expect exit 2 or 3; the 14 exit-0 cases are work.read/file.read/file.change only. `PROPOSAL_STEPS` values are asserted to be only refused/unresolved. |
| A8 closed result contract | Result key order `RESULT_KEYS` and nested closed keys asserted for every case; `resultFor` mapping exit→result asserted; exit classes 0/2/3/4 all exercised: usage (2), oversize (2, null diagnostic), parse failure (2, byteOffset, inputPath null), I/O (4, inputPath echoed only there), refusals (3), unresolved (3), allowed (0). Escaping: ESC, U+2028, DEL, backslash and astral characters in agentId/paths are escaped in both renderings (`escapeText` unit vector), stdout is the only stream, stderr asserted empty for all 204 spawned runs. |
§10.110.5 fixture mapping: 10.1 `rdeleg-*` (13) and `shape-delegation-*`,
`shape-plan-with-delegated-operations`; 10.2 `adm-consulted-work-not-readable`,
`adm-cross-workspace-mission`, `own-*`, `work-parent-project-mission`,
`file-read-with-unaccepted-dependency`; 10.3 `rdeleg-subject-form-task`,
`rdeleg-subject-form-three`, `rdeleg-scope-not-modelled`, `prop-delegation-input-missing`;
10.4 precedence tests and the four `cycle-*` cases; 10.5 the raw lexical corpus,
the oracle's typeCase/mutation/lexical corpus (983 cases) and the platform notes
in §8 below.
## 7. Design decisions taken inside the charter (for reviewer attention)
1. Nesting bound counts containers only (a scalar inside the 32nd container is
depth 32; a 33rd container fails at its opener offset).
2. Oversize input (>1 MiB) is exit 2 `invalid-request` / `input-too-large` with a
null diagnostic; exactly 1 MiB is parsed.
3. `diagnostic.inputPath` is set only on I/O failure (exit 4); `byteOffset` only on
parse failure. No other path, cwd, HOME or locator is ever emitted.
4. `registration-ambiguous` (two current registrations for one identity) is an
invalid bundle (exit 2), not a refusal.
5. U+2028/U+2029 in relative paths are accepted (the pinned checker accepts them)
but always escaped on output; astral characters pass through unescaped.
6. Unsupported record kinds are refused at the kind gate (`unsupported-kind`) and
are not schema-assessed; the oracle reports them in a separate column.
7. Strict parser string bound is 4096 UTF-8 bytes, tighter than the schema's
4000 code points for non-ASCII text; the 27 oracle "strict-only" cases are
exactly that difference (parser refuses, schema would accept).
8. All generated fixtures are checked in (about 10.9 MB) rather than generated at
test time, so the reviewed candidate is byte-frozen; the suite diffs them
against a fresh generation.
## 8. Known limitations and untested limits
- Finite corpus: the oracle is compatibility evidence over 1431 records, not a
proof of schema equivalence. Six known, directional divergences are pinned and
must reproduce exactly: four trailing-newline pattern cases (python accepts,
inspector refuses, because Python `$` matches before a trailing newline) and
years 00010999 in `time` fields (python refuses because glibc `%Y` is unpadded
so its round-trip fails; the inspector accepts calendar-valid years 19999).
- Sandbox claims are bounded: canary/inventory/static-import checks and
`env -i` runs show no observed effect or lookup in the tested paths; they do not
prove absence of all reads, containment or crash safety. A temporary HOME is not
an OS sandbox.
- Node has no `fs.constants.O_CLOEXEC` on this host; the open flags are
`O_RDONLY|O_NOFOLLOW` plus fstat/regular-file/size-stability checks only.
- Authentication is not modelled; declarations are unverified simulation. No
mock evidence, however complete, reaches `allowed` for assignment.change.
- Hidden delegation chains are not detected (§10.3 by design); only direct
declared delegation inputs are evaluated.
- The FIFO test requires `mkfifo`; the chmod-000 test is skipped when run as root.
- Nothing native, sync, live-registry or runtime was touched or tested.
## 9. Owner-demo commands (A9, for darkwing to run with Jason after review)
All from the repository root; each prints the disclaimer first and changes no file.
```sh
# 1. selected agent/project/workspace with a permitted read preview (exit 0)
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/demo/demo-read-w1.json
# 2. assigned file.change permission preview (exit 0), then show nothing changed
sha256sum -c <(sha256sum scripts/foundation/fixtures/demo/*.json) >/dev/null && \
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/demo/demo-file-change-src.json; \
sha256sum -c <(sha256sum scripts/foundation/fixtures/demo/*.json)
# 3. unregistered workspace selected: refusal without fallback (exit 3, assignment null)
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/bundles/adm-workspace-registration-missing.json
# 4. cross-lane reassignment preview: original assignment stays selected, mock evidence cannot yield allowed (exit 3, unresolved)
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/demo/demo-change-w1.json
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/bundles/prop-all-pass-restricted-contexts.json
# additional negatives used in the goldens (exit 3)
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/demo/adm-registration-revoked.json
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/demo/prop-message-is-not-authority.json
# machine-readable form of any of the above
node scripts/foundation-inspect.mjs --json scripts/foundation/fixtures/demo/demo-read-w1.json
# full offline selftest
scripts/test-foundation.sh
```
Expected exits: step 1 → 0; step 2 → 0 with both checksum passes; step 3 → 3
(`workspace-registration-missing`); step 4 → 3 twice (`runtime-reconciliation-required`,
result `unresolved`). Jason's answer on clarity and acceptance is to be recorded
separately by darkwing; this report claims no acceptance.
## 10. Freeze
Code, tests and fixtures are frozen at the manifest in §3 for filbert's
independent review. Rocko will change nothing under the allowlist until darkwing
returns reconciled findings; any fix produces a newly hashed candidate and a new
report revision. No dependent live-registry/runtime work, migration, staging,
commit, push or issue closure follows from this delivery.