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.
14 KiB
Foundation inspector — rocko build report r3 (FI-ROCKO-5: C2 correction under addendum FI-C2-1)
Author: rocko (Claude Fable 5.1). Coordinator: darkwing. Task: FI-ROCKO-5.
Written 2026-09-06 21:25 UTC. Supersedes nothing: the original report
(…-rocko-build.md, sha256 857470d97af6aeae4e7d7942c2a1d8455bfcda74ff68b8e1dc4ba8d066521fa4)
and the r2 report/manifest (…-rocko-build-r2.md 0dabd82fffdc3a56ebf9a1d8b851832c3acee2cb9332892bde9dbb13151d5e19,
…-rocko-build-manifest-r2.json 2e8b5f1998a3be6cc7fcc3fba308724d2a29ca166c08f005e1bca88ddbc14196)
are preserved unedited. This revision records the C2 correction only, what
changed, and the new frozen candidate.
0. Compatibility statement
FI-ROCKO-5 is compatible with the standing chain and with the FI-ROCKO-3 build request; no blocker. The open item of r2 §5 (the C2 pattern-class ruling) is closed by darkwing's written addendum FI-C2-1 as approved by filbert (FI-FILBERT-5). Nothing outside the original implementation/test allowlist was touched; C1 (Archify rev 3) remains HELD with no lane action.
Inputs bound to this revision:
| Input | sha256 |
|---|---|
Charter candidate 3 docs/plans/2026-09-06_foundation-inspector-charter.md (unchanged) |
19b6721128a627a2032ffdb95ece2d50abe69a8f6d521e9eff8bbdaff22798b6 |
Addendum FI-C2-1 2026-09-06_foundation-inspector-pattern-profile-addendum.md (exact bytes) |
afe2980be2f91e701dae5af3018831ac5c300474f52bcc06e740ce5b5cc68ca5 |
Filbert verdict 2026-09-06_foundation-inspector-pattern-profile-verdict.md |
03c979b77cc6b03b6685ba51ed1ce24c3f1d7b274ce8f772263a103670050da7 |
records.schema.json / check.py / records.fixtures.json (pinned, unchanged) |
05774aaf…72af6 / 82564a7d…4607 / d433d06d…da85 (full values re-verified by oracle gate 1 and listed in the manifest) |
Build request 2026-09-06_foundation-inspector-rocko-build-request.md |
90a1f329e859152d4ce8e157cbd6c56e6bcced16b4ed757822d2309514fa9a15 |
| Original report / r2 report / r2 manifest (preserved) | 857470d9…21fa4 / 0dabd82f…1e19 / 2e8b5f19…4196 |
| Integration HEAD (unchanged, nothing staged) | 9a5fbdbda74b16adf488fe28138b2ba69ea5e669 |
Machine-generated manifest 2026-09-06_foundation-inspector-rocko-build-manifest-r3.json |
3c2253b6c9f31e448c77aaac53977d41baecfb30e15845dcfffd8dc694428547 |
The charter, addendum and verdict hashes above are also asserted by a unit
test (resolve.test.mjs, "the unchanged charter, the exact addendum and its
verdict are bound"); a byte change to any of the three fails the suite.
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. Design of the correction (addendum FI-C2-1, point by point)
Schema column (genuine pinned compatibility). The pinned checker validates
pattern with Python re.search, whose $ matches at end of string or
before exactly one final \n. resolve.mjs now exports PINNED_PATTERNS
(id, runtimeId, digest), pinnedPatternMatches(re, v) =
re.test(v) || (v.endsWith("\n") && re.test(v.slice(0, -1))), and
strictPatternMatches(re, v) = re.test(v). The shape gate
(checkPattern) uses the pinned semantics for shape-pattern-mismatch, so the
four r2 witnesses become schema agreements and the schema column has zero
disagreements with no named exceptions (r2's KNOWN_DIVERGENCES set is gone).
Strict production profile. After the pinned check, checkPattern applies
the strict check on every occurrence of the three typed families (records,
scope ids, actor ids, supersedes, dependency refs, registry refs, payload ids,
unselected records, registry entries, artifacts, authorization, selection,
proposal and delegation inputs). A violation is recorded into a per-call
profileSink (path only; never the value). validateRecordShape returns
{ verdict: "valid", profileViolations: [...] } so the schema and profile
verdicts are independent. validateBundleShape collects violations from every
record and wrapper field and, after shape validation succeeds and before any
identity index or registry-digest profile, refuses with exit 2,
invalid-request, rule profile-pattern-mismatch, path of the first
violation in validation order. Closed §7 fields are unchanged; selection and
operation are withheld (null); the offending value is never echoed.
No trimming, normalization or waiver. The original string is preserved;
no identity index is built from a profile-invalid value; no case name is
whitelisted anywhere. Precedence: profile refusal wins over a dangling
reference on the same field, so a profile-invalid ref is distinguishable from
a missing one (unit test with ref-missing-dependency vs
profile-record-dependency-ref-id-dangling-one-final-lf).
Free-form text, time and path keep their semantics. Escaped newlines in
mission.objective / task.purpose stay schema- and profile-valid
(profile-escaped-newline-free-text-allowed, exit 0). time with a final LF
fails shape-pattern-mismatch (strptime refuses it in the pinned checker
too); relativePath with a final LF fails path-invalid. Neither is in the
profile.
Bridge. validate-record.mjs now reports schemaValid and
profileValid independently, with rule: "profile-pattern-mismatch" and the
first violating path when the record is schema-valid but profile-invalid.
Oracle. verify-schema.py builds an in-memory strict variant of the
pinned schema (only the three $defs patterns, trailing $ → \Z;
check_schema passes; pinned bytes untouched) and computes the profile
column with the real jsonschema validator, never by name. The four original
witnesses are preserved by name as declared probes (schema True / profile
False); a newline matrix (valid, one final LF, two final LF, CRLF, CR,
interior LF, U+2028, U+2029) runs across 8 sites of the three families with
declared schema/profile outcomes; every strict-only refusal must carry the
fixed rule and a path; a run with no refusals or an unobserved declared
refusal is a problem.
One incidental fix in the allowlist. The eight payload-level scope
re-checks previously re-validated rec.scope under the bare path scope,
which would have double-counted a profile violation; they now use
requireScopeKind (kind-only check with the proper record.scope.kind path).
No verdict of the 204 pre-existing fixtures changed (index.json gained 55
entries and nothing else; demo goldens byte-identical).
2. Filbert's FI-FILBERT-5 matrix, as implemented
Per family (id, runtimeId, digest): Python / Node schema / strict.
| Value | Python (pinned) | Node schema column | Strict profile | Inspector verdict |
|---|---|---|---|---|
| valid | T | T | T | proceeds |
| one final LF | T | T | F | exit 2 invalid-request profile-pattern-mismatch |
| two final LF, CRLF, CR, interior LF, U+2028, U+2029 | F | F | F | exit 2 invalid-request shape-pattern-mismatch |
Asserted three ways: unit test on the exported predicates, 55 CLI fixtures, and the oracle's declared probes against the real Python validators.
3. Changed files (r2 → r3 sha256; everything else byte-identical)
| File | Lines | r2 sha256 | r3 sha256 |
|---|---|---|---|
scripts/foundation/resolve.mjs |
1646→1713 | aa842898ebb0bb2a911406314c4c3a2c4079b46bfd674c4ffba0176a1e32766c |
eaa4a419618328915cd470ba192a88b8d313ee8fa48f600289ffe39df15280b2 |
scripts/foundation/validate-record.mjs |
→71 | e4e70f60cce68e535ef98b0627647c440d620432cf8ddaed074df4e252ecde58 |
dcff28b53501b68fe7368adcbf02db0526ab4273d1c1c42e47df9a78a0bd9b4b |
scripts/foundation/verify-schema.py |
467→575 | b61031b6c2cea126133afda70894e7f2429b08bf2cd50fc766ec6b99f348c966 |
e5fce462abd0e8c5be4e4543fd31146a35aba41a653d2aa105c28ca5a20deb67 |
scripts/foundation/resolve.test.mjs |
333→425 | 6bb6d40fa6ec90fb52db658f77ca9fd27cc3eb8673f040f52fc126e67983a571 |
d7de059015edcf0bded7c4da901a7302394a42bf1e38b86bd403fbb01f5327ff |
scripts/foundation/cli.test.mjs |
281→317 | ccec06c266e03d878c1ecd9e8c20ee3f1fb82f478daead25efa4661b7090d83f |
a0bda7779739021da7cbe03b46209e370f7443100f6ea56a512468003d60b74c |
scripts/foundation/fixtures/build-fixtures.mjs |
→979 | 094ecc811b85465cc0748a86b76b75c1784a2e0296f242b6ff2dbd1660b426a9 |
0386276f0e0ba8fbb3f4126ffabadd6afec90fc3a92749fe314783d26300aa5c |
scripts/foundation/fixtures/index.json |
204→259 cases | 74988a1dcd4b48b0be2243d3fefff3b6de5d90a947094be201c3486142ca12a2 |
c013090406bb6bbb7b490b952eb4020065b4c732e4aecb0e6cf5c5c8037a6663 |
scripts/foundation/fixtures/README.md |
→51 | aba48ba054d09247b048a8955507b87a275cd585870f1f658b7c6b826fc892bd |
ed0376589b203b1bcea6e1d82322311ec843eb7537756762bf917b8552d29523 |
scripts/test-foundation.sh |
132→143 | fdfa13ce247bc9ad8f3617e248913aef384029198924685ada3431006ffdf114 |
73417979d1f9320603b0244350f9665d2bdf1485084c0928002ba033929b3c19 |
Added: 55 bundle fixtures scripts/foundation/fixtures/bundles/profile-*.json
(generator output; listed individually in the manifest). Removed: none.
Unchanged: scripts/foundation-inspect.mjs, strict-json.mjs,
canonical.mjs, fixtures.test.mjs, canonical.test.mjs,
strict-json.test.mjs, all 19 raw fixtures, all 20 demo files and goldens
(demo aggregate 6a32862b…8956 and raw aggregate dbc620a7…60d3 identical to r2).
Manifest r3 aggregates (sha256 of the LC_ALL=C sorted sha256sum listing):
fixtures/bundles/ 240 files aa4836a4a4f989ecc70acf8df770b894c6ef77e85c4e913c24bb422b1aef0afa;
fixtures/ 282 3de4c896d63041db0b6b5beb961d9dfa6486f7681dd16f91abb5d8ef48c16bfb;
scripts/foundation/ 292 4fbdcfb8d71612d4ac21dc0b7f5b60064847d7087bfbe8ec215a9f1abdbafb9a;
scripts/ 294 e5f9039cf4614e8acc3f6c6a71f0a03dbc1c29002703029180d1ccef5757979c.
4. New fixture inventory (55 cases)
| Group | Rule | Count | Cases |
|---|---|---|---|
| profile | profile-pattern-mismatch |
34 | one final LF at 3 family sites (id-record-id, runtime-id-authorization-ref, digest-registry-ref) plus 31 further occurrence sites: record scope project/workspace ids, actor principal/execution ids, supersedes, dangling dependency ref, registry ref id, agent type, file root id, registration/assignment agent ids, criterion id, decision subject ref, unselected record id and its scope, registry id and plain/content-bearing digests, artifact run/id/digest, authorization, selection agent/project/workspace/assignment-ref ids and assignment-ref scope, proposal requester/target/context ids, delegation input decision ref |
| shape | shape-pattern-mismatch |
19 | two-final-lf, crlf, cr, interior-lf, u2028, u2029 at each of the 3 family sites (18) + profile-time-one-final-lf |
| shape | path-invalid |
1 | profile-path-one-final-lf |
| positive | — (exit 0) | 1 | profile-escaped-newline-free-text-allowed |
Every profile case is asserted to return selection: null, operation: null, and no \n inside any result string (loop in resolve.test.mjs).
5. Receipts (all run 2026-09-06 21:0x–21:23 UTC at HEAD 9a5fbdbd)
| Check | Result |
|---|---|
node --check on all 10 .mjs files; ast.parse on verify-schema.py |
OK |
node --test scripts/foundation/ |
63 tests, 63 pass, 0 fail (was 58; +5: binding, matrix, independence/order, precedence, CLI negative control) |
python3 scripts/foundation/verify-schema.py |
PASS, exit 0. Corpus 1539 records (38 pinned fixtures, 449 unique bundle records, 1052 typeCase/mutation/lexical). Schema column: agree-valid 519, agree-invalid 983, DISAGREEMENTS 0; strict-only (parser-bound) 27; unsupported-kind not assessed 10. Profile column: profile-valid 489, profile-invalid 30. profile refusals asserted: 30 … 12 declared by name; 73 named probes verified |
NO_COLOR=1 scripts/test-foundation.sh |
selftest: 43 passed, 0 failed (was 36/1); new checks: zero schema disagreements, refusals counted, profile exits 2/2/0, JSON refusal shape with value never echoed |
| CLI negative controls | selection agentId + one LF → status 2, invalid-request, profile-pattern-mismatch, selection/operation null, agent-a absent from JSON and text; two LFs → shape-pattern-mismatch; escaped newlines in free text → exit 0 |
python3 docs/plans/foundation-v1-candidate/check.py |
exit 0, PASS: 35 |
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 |
| Fixture regeneration | build-fixtures.mjs into a sandbox equals checked-in bundles/, raw/, index.json, demo bundles |
git rev-parse HEAD; git status |
9a5fbdbd…; nothing staged; only the pre-existing tracked modifications (BUILD-LOG.md, docs/SESSIONS.md, docs/plans/CURRENT.md) plus untracked candidate/review files |
scripts/foundation/__pycache__, docs/plans/foundation-v1-candidate/__pycache__ |
absent |
6. Constraints honoured and freeze
No edit to charter, addendum, verdict, pinned schema/checker/fixtures, prior
reports or manifests, CURRENT, shared logs, root/package files, policies or
runtime data. No new dependency. No staging, commit, checkout/reset or push
(Dewey's index untouched). No live, native/sync, credential or ~/.mosaic
work; no network; no engine launch. Tests spawn the inspector; the inspector
spawns nothing. Finite tests and static flags are evidence, not sandbox proof.
Frozen at the r3 manifest (manifest-r3.json, sha256 3c2253b6…8547; 294
files) for filbert's full code review. Rocko changes nothing under the
allowlist until darkwing returns reconciled findings. C1 (Archify rev 3)
remains HELD; no lane action taken.