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.
22 KiB
Foundation inspector — rocko build report r2 (FI-ROCKO-4 dispositions)
Author: rocko (Claude Fable 5.1). Coordinator: darkwing. Task: FI-ROCKO-4.
Written 2026-09-06 18:35 UTC. Supersedes nothing: the original report
docs/plans/reviews/2026-09-06_foundation-inspector-rocko-build.md is preserved
unedited (sha256 857470d97af6aeae4e7d7942c2a1d8455bfcda74ff68b8e1dc4ba8d066521fa4,
unchanged since delivery); this revision records the admission findings, what
changed, and the new frozen candidate.
Inputs bound to this revision:
| Input | sha256 |
|---|---|
Admission findings 2026-09-06_foundation-inspector-build-admission-findings.md (as received, 18:04Z) |
59233c6126c2355df5a367f0e61df7798e6cccfaa682454992fcd0d0df39c82c |
| Same file now (darkwing's "Transport (2026-09-06 18:17 UTC)" footnote appended; no other change) | 8d9f7aab3b3bdf79345a07ba3595b966982b7667714ac7e3f669d65e328ca3d5 |
Charter candidate 3 docs/plans/2026-09-06_foundation-inspector-charter.md |
19b6721128a627a2032ffdb95ece2d50abe69a8f6d521e9eff8bbdaff22798b6 |
records.schema.json / check.py / records.fixtures.json |
05774aaf…72af6 / 82564a7d…4607 / d433d06d…da85 (full values re-verified by the oracle gate 1 and listed in the manifest) |
Build request 2026-09-06_foundation-inspector-rocko-build-request.md (now, transport footnote included) |
90a1f329e859152d4ce8e157cbd6c56e6bcced16b4ed757822d2309514fa9a15 |
| Integration HEAD (unchanged, nothing staged) | 9a5fbdbda74b16adf488fe28138b2ba69ea5e669 |
Machine-generated manifest 2026-09-06_foundation-inspector-rocko-build-manifest-r2.json |
2e8b5f1998a3be6cc7fcc3fba308724d2a29ca166c08f005e1bca88ddbc14196 |
Toolchain measured: Node v26.8.1, CPython 3.12.8, jsonschema 4.26.0, Linux
7.2.2-1-cachyos x86_64, glibc 2.44 (strftime("%Y") for year 999 → 999).
1. Per-finding dispositions
C1 — demo hash mismatch: transcription error, no drift
Disposition: typo in the original report, not evidence drift. Corrected; no evidence was regenerated to make anything match.
- Advertised (report line 96):
…548fc023…; measured then and now:f1c6bd523cdff161e51da156fd00cfaa652d193f41541686548cf023378fd8ab. The only difference is the transpositionfc→cfat positions 51–52; the other 62 hex characters are identical. - Evidence the file never changed: my scratch hash listing taken at 18:03:52 UTC
(before the report was written) already contains the measured value for
demo/prop-message-is-not-authority.json; the file's mtime is 17:52:58 UTC, earlier than that listing; the demo copy is byte-identical tobundles/prop-message-is-not-authority.json(same hash, 49,975 bytes; asserted byfixtures.test.mjs"demo copy drifted"); and both aggregate manifests reproduce the original report's values with the original method: bundles 185 files 9,235,245 bytesa804e4ab253839ba2bb8ad7475d27512b2ef88e70a9779f9093fee5478de4823, raw 19 files 1,336,985 bytes508ad85208f4b69676f3d041faa4ff4cd4a2f8de74b7bde9b0b89123a8485cc4. - Root cause: the original §3 tables were hand-transcribed. The r2 manifest is
written by a script (
manifest-r2.json: path, mode, size, sha256 for all 239 candidate files, aggregates, HEAD, toolchain, pinned inputs). No hash in this report or in the manifest is typed by hand except where a value is quoted from the original report to show the error.
C2 — oracle divergences were waived: waiver removed, one class remains as a spec blocker
Disposition: fixed for the calendar class; precise blocker for the pattern
class. The oracle no longer has a KNOWN_DIVERGENCES list; every
schema-column disagreement is a problem and the oracle FAILS.
Calendar class (2 cases, fixed): the pinned checker refuses years 0001–0999 on
this platform because strftime("%Y") is unpadded below 1000, so its
strptime/strftime round-trip fails. The inspector now refuses them identically
(isValidTime: year < 1000 refused; charter §8 "calendar semantics from the
pinned checker"). Witness:
python3 -c 'from datetime import datetime; print(datetime(999,1,1).strftime("%Y"))' → 999.
The oracle asserts this witness as gate 3 before comparing and fails with an
explicit "platform boundary" message on a platform that pads. Cases
calendar-year-0001, calendar-year-0999, calendar-year-0100 now agree
(both refuse). resolve.test.mjs adds the three boundary vectors.
Pattern class (4 cases, blocker, unchanged verdicts): the pinned checker
evaluates pattern through Python re.search, whose $ also matches
immediately before a trailing \n; ECMAScript $ does not. Consequently the
pinned checker ACCEPTS id, scope.projectId, authorizationRef (runtimeId
pattern) and policyRef.digest values that carry a trailing newline, and the
inspector REFUSES them (shape-pattern-mismatch). Witnesses:
python3 -c 'import re; print(bool(re.search(r"^[a-z0-9][a-z0-9._-]{0,63}$", "abc\n")))' # True
node -e 'console.log(/^[a-z0-9][a-z0-9._-]{0,63}$/.test("abc\n"))' # false
Current oracle output (verbatim, exit 1):
platform witness: strftime('%Y') for year 999 -> '999' (pinned checker refuses years 0001..0999)
node v26.8.1; corpus 1432 records (38 pinned fixtures, 410 unique bundle records, 984 typeCase/mutation/lexical cases)
schema column: agree-valid 476, agree-invalid 915, DISAGREEMENTS 4; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10
profile column (schema-valid records only): profile-valid 476, profile-invalid 0
problem: DISAGREEMENT pattern-authorization-ref-trailing-newline: pinned-checker schema True / inspector schema False (inspector profile False, rule shape-pattern-mismatch)
problem: DISAGREEMENT pattern-digest-trailing-newline: pinned-checker schema True / inspector schema False (inspector profile False, rule shape-pattern-mismatch)
problem: DISAGREEMENT pattern-id-trailing-newline: pinned-checker schema True / inspector schema False (inspector profile False, rule shape-pattern-mismatch)
problem: DISAGREEMENT pattern-scope-project-id-trailing-newline: pinned-checker schema True / inspector schema False (inspector profile False, rule shape-pattern-mismatch)
FAIL: 4 differential problems
Why I did not resolve it myself: the findings forbid implementing a waiver or
changing the pinned schema/checker, and the charter forbids weakening safe
input handling. Making the inspector accept an identifier with an embedded
newline would relax input handling merely to turn the count green (the newline
would then be carried into selection.projectId and the text rendering, and a
scope.projectId of p1\n would be a distinct identity from p1 that renders
almost identically). The schema-column comparison is therefore left honestly
red, and the suite reports selftest: 36 passed, 1 failed until this is ruled.
Proposed amendment (for darkwing/Jason; I implement nothing until ruled):
- (a) Recommended. Add to charter §8 (or the incorporated notes) a
"checker-dialect artifact" clause: "The pinned checker's
patternsemantics are Pythonre.search; its$accepts one trailing newline. This is a dialect artifact, not an intended grammar. The inspector applies the pattern with anchored (ECMAScript) semantics and refuses a trailing newline. The differential oracle records the cases in this class by name, with the two witnesses above, and reports them as an expected artifact-class difference separately from agreement counts; any other disagreement fails." Under (a) the oracle would carry a named, witnessed artifact class with exact direction (pinned True / inspector False) and fail on any other direction or any other case. This is the amendment I would implement; it needs a coordinator ruling because it is a policy choice about which side is authoritative. - (b) Against: relax the inspector to Python semantics. Rejected for the input handling reason above and because §8 keeps "record-schema verdict distinct from … refusal"; the inspector would have to accept an identifier the runtime would never mint.
- (c) Against: drop the four mutations from the corpus. Rejected: it hides a real, reproducible difference between the two implementations.
Until ruled, the candidate's differential gate is red by design, and this report does not claim oracle PASS.
C3 — exit outside the closed §7 fields: removed from the serialized result
Disposition: fixed; no charter amendment needed. Exit status is process
metadata derived from the emitted result (exitFor(result)), never a field
of it and never a text line.
resolve.mjs:RESULT_KEYSis exactly the 12 charter §7 names in charter order;buildResultbuilds noexitmember and throws if the requested exit is inconsistent with the derived result/reason; new exportexitFor(result)(allowed→0; refused/unresolved→3; invalid+io-failure→4; other invalid→2).evaluate()returns{ result, exit, detail }withexitoutsideresult.foundation-inspect.mjs:renderTextends with thediagnostic:line (noexit:line);run()returns{ json, result, exit };main()writes the rendering and setsprocess.exitCode = exit.- Tests whose expected keys come from the approved contract, not from the
implementation:
resolve.test.mjs"closed result fields equal the pinned charter §7 list" reads the charter file, asserts its sha256 is19b67211…798b6, parses the twelve- name:bullets under "Closed result fields, emitted on every outcome:", and asserts they equal both an independent literal copy in the test and the implementation'sRESULT_KEYS; it also assertsexitis absent, checksexitForon all four classes, and thatbuildResultthrows for four exit/reason inconsistencies.cli.test.mjsandfixtures.test.mjsassert!("exit" in parsed)for every spawned run and derive the expected process status from the parsed result; text renderings are asserted to end with the diagnostic line and to contain noexitline for all 204 cases.test-foundation.shasserts the--jsonkey list equals the twelve names literally. - Consequence: the ten demo goldens (
*.expected.txt,*.expected.json) were regenerated with the README loop because the contract fix removed one line / one member from each; the five*.expected.exitfiles are byte-identical to before (hashes9a271f2a…86aafor 0 and1121cfcc…02a2for 3, as in the original table).index.jsonis unchanged (itsexpect.exitwas always the process status). Demo tree total bytes 249,096 → 248,991 (−105 = 5 × (8-byte text line + 13-byte JSON member)).
C4 — demo step 2 could not show unchanged bytes: corrected
Disposition: fixed. The BEFORE manifest is saved in a separate scratch
location first, the preview runs, then sha256sum -c verifies against that
SAME manifest (plus an inventory of path/type/size/mode/inode/mtime and a file
count). Corrected commands are in §4; the receipt from running them is in §3.
C5 — report omitted O_NONBLOCK: prose corrected, flag kept
Disposition: fixed in prose only; no code change. The CLI opens the input
with O_RDONLY | O_NOFOLLOW | O_NONBLOCK (REQUIRED_FLAGS = those three
names) and refuses with open-flags-unavailable (exit 4) if any is not a
number on the platform. O_CLOEXEC is not used (charter §6). The original
report's lines 142 and 270 said O_RDONLY|O_NOFOLLOW only; that text was wrong
and is superseded by this paragraph. The FIFO test (cli.test.mjs "FIFO must be
refused after O_NONBLOCK open, not read") exercises the flag.
2. Changed files (old → new sha256; everything else byte-identical)
All under the FI-ROCKO-3 allowlist plus the two paths offered in the findings.
Nothing else in the working tree was touched; git status shows the same
pre-existing modified/untracked entries as before plus the two r2 documents.
| File | Lines | Original report sha256 | r2 sha256 |
|---|---|---|---|
scripts/foundation-inspect.mjs |
239→244 | bfa1b78007c772c54fe1dab90a53e19e6bce7e4888a5adb2de0b2cfe43c5cddd |
dad369490ca8396d3b4a7bd4a1b7fa87b677a2b8cf991bf61672d446e5aa3c93 |
scripts/foundation/resolve.mjs |
1625→1646 | 9ae8b4255b5dc1f1e9b0d36549865268c12dc53f010984eb1e5616b127d1d8a2 |
aa842898ebb0bb2a911406314c4c3a2c4079b46bfd674c4ffba0176a1e32766c |
scripts/foundation/verify-schema.py |
453→467 | 7e3098655b2e5f261391d788c2112a6ffb055895e357b427bc68e5f2fa7b52d7 |
b61031b6c2cea126133afda70894e7f2429b08bf2cd50fc766ec6b99f348c966 |
scripts/foundation/resolve.test.mjs |
294→333 | 05f27aa6c8a1b8ff2ee45e5de03a9aea5ed13cf011b2464c5865022dc9781449 |
6bb6d40fa6ec90fb52db658f77ca9fd27cc3eb8673f040f52fc126e67983a571 |
scripts/foundation/cli.test.mjs |
279→281 | b7e9a13c11e3e6f487ada2779c892cdf848526de1ef8b21387d15d4a461ddb62 |
ccec06c266e03d878c1ecd9e8c20ee3f1fb82f478daead25efa4661b7090d83f |
scripts/foundation/fixtures.test.mjs |
93→98 | 2827de36214c8014471fed3478c42bf48eddb3fbdbff82cac9e27851646b15d2 |
94e7508717efcafd11585a288a5d791e1e48a993794e2d470c6097f904befdb3 |
scripts/test-foundation.sh |
132 | 76fb7ba9da4345271b6ba93228a9da69c7e55c4e44b9f4033e84a8f4b430e8ec |
fdfa13ce247bc9ad8f3617e248913aef384029198924685ada3431006ffdf114 |
fixtures/demo/demo-read-w1.expected.txt |
8bfff519ce8275cfe59562efd04647c242c328a09b301b91d70491f030cf1600 |
8ba4bbe92819ac8912c72e7c635730e99eac7916c0d924fc81b75115b5939b53 |
|
fixtures/demo/demo-read-w1.expected.json |
55e10c1693787cd8e39d3a66841d30e2336080d2ae4450a806a7ae8373db476b |
42055bda71075ba5c710f011f83d470228f18097d93ac5585ba1b534cba0ef2a |
|
fixtures/demo/demo-file-change-src.expected.txt |
f5387217ca0a41d437468af33b7d87d06c0c5535ab5490b568f9866a13b2732e |
2cdd6d4e162fa904b03e8f8a88553a03065ac7fb646baabf21625d4f5962a79b |
|
fixtures/demo/demo-file-change-src.expected.json |
88c7793c6af17ca255525451a499d9f8bb165155e50d2ee936bd68ba82a876a7 |
7ea412916404ec948c94e929cc7b2ce120b394944c66c7bfcc811d0721dd82db |
|
fixtures/demo/demo-change-w1.expected.txt |
2a1090e5f5ad08e2175830943a7c81928de970470893e803b1e440843152c348 |
0e2807ab56d15670c51c8ad4a43f33b36c5672799937561f39e20c6e93be1dda |
|
fixtures/demo/demo-change-w1.expected.json |
36c287cba327070f7ff3dd9846421bee3ebd0dd52e9c602b68e84fa620ef4fc5 |
ecf8313993ca27450d1753c6178be1a063fb0637f14be8f091de923b8b722516 |
|
fixtures/demo/adm-registration-revoked.expected.txt |
624c9e5991597d59fc3379343b16e7eab9cb6434f054da3a4df7518742e3b36c |
c2fd118d44d21cbd709d30a2c2be2603740a81e628aa9d32f95d6eaf06d3a9a6 |
|
fixtures/demo/adm-registration-revoked.expected.json |
b966d939e0d2851ef731462a0fda932e75f53b9aac406216ad440f781e036d0f |
c44b0935ed329c1a381f986997b1bc4be702fc4229166d8a0b49e4e80f9b2fa8 |
|
fixtures/demo/prop-message-is-not-authority.expected.txt |
e7b0e9fa64abe0c0f8c91fbc9aa565988ce76cb3967672bfacafab350e20d8be |
388983ad6e4e31db6f5a688773ff2bf07d44d7ffe530eb7870e729a0f546278d |
|
fixtures/demo/prop-message-is-not-authority.expected.json |
53884bfdea21185141b9a06d52aa1c0fe8e7bfae6627b465929403521f9bc4d8 |
742e479ddbb4cf2138d49ec0ac40cd038b6c20f8b9c0e2daffc5a859db9f4145 |
|
fixtures/demo/prop-message-is-not-authority.json |
(report typo …548fc023…) |
f1c6bd523cdff161e51da156fd00cfaa652d193f41541686548cf023378fd8ab (file unchanged) |
Unchanged (same hash as the original table): strict-json.mjs, canonical.mjs,
validate-record.mjs, strict-json.test.mjs, canonical.test.mjs,
build-fixtures.mjs, index.json, fixtures/README.md, all five
*.expected.exit, all five demo *.json bundles, all 185 bundles and 19 raw
fixtures (aggregates above). Full per-file listing with modes: manifest-r2.json.
Aggregates (r2 manifest method: sha256 of the LC_ALL=C sorted sha256sum
listing with repo-relative paths): scripts/foundation/fixtures/ 227 files
36d99b91065ed7af03f17b7b9cc309b3f7805ca5e3a337ddb5f3536f2ccaa563;
scripts/foundation/ 237 files 6c111ad1165e0da219d566f919e25005af47fa004257a11e7e2750a4010b9ecb;
all 239 candidate files e0fe89d9cc5245031ce484e9e0fe15b93319dd2cdf040800c52555a26fb1c1a6.
Original-method demo aggregate (run in scripts/foundation/fixtures/,
sha256sum demo/* | sha256sum): 7000fdd9b2a5e92256429e148240541fab3f93d2ef009e47b08baddcbcef5216.
Source changes in words: resolve.mjs (isValidTime year ≥ 1000; exitFor;
RESULT_KEYS without exit; buildResult consistency guard; evaluate returns
exit beside result). foundation-inspect.mjs (no exit line; withExit; exit via
process.exitCode only). verify-schema.py (waiver list and waiver comparison
deleted; gate 3 platform witness; trailing-newline cases renamed
pattern-*-trailing-newline and kept; calendar boundary cases; separate
schema/profile column summary; every disagreement is a problem).
test-foundation.sh (JSON key-list assertion; oracle summary grep lines).
Tests as described under C3 and C2. No new dependency, no new file outside the
allowlist, no __pycache__ (verified absent after all runs).
3. Receipts (all run 2026-09-06 18:2x–18:30 UTC at HEAD 9a5fbdbd)
| Check | Result |
|---|---|
node --check on all 10 .mjs files; ast.parse on verify-schema.py |
OK |
node --test scripts/foundation/ |
58 tests, 58 pass, 0 fail (was 57; +1 charter-derived field test) |
python3 scripts/foundation/verify-schema.py |
FAIL, exit 1: exactly the 4 pattern-*-trailing-newline disagreements (output quoted under C2); gates 1–3 PASS; 38 pinned fixtures agree |
NO_COLOR=1 scripts/test-foundation.sh |
selftest: 36 passed, 1 failed; the one failure is the oracle gate above; all other checks OK (syntax, fixture regeneration equality, node tests, demo exits 0/0/3/3/3, usage 2, I/O 4 ×3, oversize 2, disclaimer, JSON key list, golden byte-match, sandboxed inventory unchanged, canaries never printed) |
python3 docs/plans/foundation-v1-candidate/check.py |
exit 0 |
scripts/test-config.sh / test-task.sh / test-release.sh / test-conductor.sh / test-auth.sh |
24/0, 90/0, 14/0, 17/0, 15/0 passed/failed |
git rev-parse HEAD; git status |
9a5fbdbd…; nothing staged; only the pre-existing entries plus the two r2 documents |
scripts/foundation/__pycache__, docs/plans/foundation-v1-candidate/__pycache__ |
absent |
Owner-demo receipt (corrected C4 procedure, verbatim outcome lines):
step 1 demo-read-w1.json → result: allowed … operation: work.read target null rc=0
step 2 before manifest: 227 files, sha256 cf2eed27c5e5b311d40e5346af89fbc5fdc7781488bf8ea9d663e66e7dd50d59
demo-file-change-src.json → result: allowed … operation: file.change target workspace:src/main.mjs rc=0
sha256sum -c against saved BEFORE manifest: all 227 OK
inventory (path/type/size/mode/inode/mtime) unchanged
file count unchanged: no file added
step 3 adm-workspace-registration-missing.json → refused / not-authorized / workspace-registration-missing, assignment null rc=3
step 4 demo-change-w1.json → unresolved / unknown-effects / runtime-reconciliation-required; selection keeps asg-a-w1 rev 1 rc=3
prop-all-pass-restricted-contexts.json → unresolved / unknown-effects / runtime-reconciliation-required rc=3
extra adm-registration-revoked → refused/registration-revoked rc=3; prop-message-is-not-authority → refused/message-is-not-authority rc=3
json keys = [disclaimer, preview, bundleVersion, authentication, declarations, result, reason, rule, selection, operation, proposal, diagnostic] rc=0
Every text rendering begins SYNTHETIC PREVIEW — NO LIVE EFFECTS and ends with
the diagnostic: line. These are bounded evidence (finite tests, inventory
comparison), not an OS-sandbox proof; the original report's §8 qualifications
stand.
4. Corrected owner-demo commands (A9; replaces original §9 step 2)
# 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 preview (exit 0); prove no fixture file changed:
# save the BEFORE manifest elsewhere first, run, then verify against that SAME manifest
BEFORE="$(mktemp)"
( cd scripts/foundation/fixtures && find . -type f | LC_ALL=C sort | xargs sha256sum ) > "$BEFORE"
node scripts/foundation-inspect.mjs scripts/foundation/fixtures/demo/demo-file-change-src.json
( cd scripts/foundation/fixtures && sha256sum -c --quiet "$BEFORE" ) && echo "all $(wc -l < "$BEFORE") files unchanged"
[ "$(cd scripts/foundation/fixtures && find . -type f | wc -l)" = "$(wc -l < "$BEFORE")" ] && echo "no file added"
# 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; even fully
# supplied mock declarations 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
# machine-readable form; process exit status is the only exit signal
node scripts/foundation-inspect.mjs --json scripts/foundation/fixtures/demo/demo-read-w1.json; echo "exit $?"
Step 5 (Jason's answer on clarity and acceptance) is darkwing's to record; this report claims no acceptance.
5. Open item and freeze
Open: the C2 pattern-class ruling (§1 C2, options a/b/c). Until ruled the
oracle and therefore test-foundation.sh are red on exactly those four named
cases; I have not weakened, waived or removed them.
Frozen at the r2 manifest (manifest-r2.json, sha256 2e8b5f19…4196; 239
files) for independent review. Rocko changes nothing under the allowlist until
darkwing returns a ruling or reconciled findings. No staging, commit,
checkout/reset, push, charter/schema/verdict/coordinator-record edit, live or
native/sync work, credential or ~/.mosaic read, network access or engine
launch occurred. C1 (Archify rev 3) remains HELD; no lane action taken.