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.
16 KiB
Foundation inspector — rocko build report r6 (FI-ROCKO-8: R5-1 total tie-break over the strict-JSON domain)
Author: rocko (Claude Fable 5.1). Coordinator: darkwing. Reviewer: filbert. Task: FI-ROCKO-8.
Written 2026-09-07 15:35 UTC. Supersedes nothing: the original report, the r2–r5
reports and manifests, the charter, the addendum, all verdicts, the corrections
request, the ordering follow-up and the demo test-gate decision are preserved unedited.
This revision corrects exactly the FI-FILBERT-7 finding R5-1 (verdict
docs/plans/reviews/2026-09-07_foundation-inspector-code-verdict-r5.md, sha256
154e7b5d804c059d6fec4c936c78e4ae33bb7fc273ba3a5eec7b00d0a9ce1e59), records what
changed r5 → r6, the new Unicode permutation regressions, and the frozen candidate for
independent re-review.
0. Admission, compatibility and blockers
FI-ROCKO-8 is admitted and compatible with the standing chain, the FI-ROCKO-3 build
request, the corrections request, the ordering follow-up, the demo test-gate decision
and the FI-FILBERT-7 verdict; the work stays inside the original source/test allowlist
plus the two r6 receipt paths named in the task. C1 (Archify rev 3) remains HELD with no
lane action. No open blocker. scripts/test-task.sh and scripts/test-release.sh
remain NOT RUN / DEFERRED under the owner decision (§7); no live test authority is
claimed.
Inputs bound to this revision (all hashes machine-read; full list in the r6 manifest
pinnedInputs, which adds the r5 report, the r5 manifest and the FI-FILBERT-7 verdict
to the r5 list):
| Input | sha256 |
|---|---|
charter docs/plans/2026-09-06_foundation-inspector-charter.md |
19b6721128a627a2032ffdb95ece2d50abe69a8f6d521e9eff8bbdaff22798b6 |
| addendum FI-C2-1 | afe2980be2f91e701dae5af3018831ac5c300474f52bcc06e740ce5b5cc68ca5 |
| code verdict FI-FILBERT-6 | e4cc5970aab20240e6ea3a9a1513ef942ff167fefbb03356b9a32c89999adb3d |
| code verdict FI-FILBERT-7 (r5, NOT APPROVED, R5-1) | 154e7b5d804c059d6fec4c936c78e4ae33bb7fc273ba3a5eec7b00d0a9ce1e59 |
| corrections request | 35c237f5c001832a0cfed23b03ff7530ffa78443612ffe11130fe456b968bd61 |
| ordering follow-up | e93a65b94fd4df8bd6e74c2f38afaf02e0f86b36632ff5a820fd8ac464c22101 |
| demo test-gate decision | 62cea74bea59e69f29c8a29a9c0311fdc6feffa2c337bc6a141db55149204898 |
| r5 report | 17c67427dfdf1bc5dac491c4d0223928e87fdfc67a26175ac239eb2b2f7b7dec |
| r5 manifest (369 files) | a63bb103e4cfe51bbd8a42cd95545f935ac83c1da51cf469298375cf94ced135 |
| pinned schema / checker / fixtures | 05774aaf…2af6 / 82564a7d…4607 / d433d06d…da85 |
Git: HEAD 9a5fbdbda74b16adf488fe28138b2ba69ea5e669 (main), unchanged throughout;
nothing staged. Tracked modifications present in the worktree: the pre-existing
BUILD-LOG.md, docs/SESSIONS.md, docs/plans/CURRENT.md, plus docs/TOOLS.md and
scripts/agent.sh, which were modified by another session at 15:04 UTC (outside the
allowlist; not touched, not inspected beyond git status, reported here only). All
candidate files remain untracked. Toolchain: node v26.8.1, Python 3.12.8, jsonschema
4.26.0, Linux 7.2.2-1-cachyos.
1. Evidence preservation
- r5 report and manifest: unedited, hashes above re-verified after the r6 build. The r5 §3(a) claim that "two entries with equal typed key and equal canonical content are indistinguishable" was wrong for non-ASCII entries (R5-1); it is corrected here (§2), not by editing r5.
- r4 report/manifest, r3 report (
ec0444c9…5508) and manifest (3c2253b6…8547): unedited. The r4 §3(g) correction stands and is repeated so it stays visible: the r3test-task.sh90/0 receipt did execute the suite's Docker and live branches, contradicting r3 §6 "no engine launch". r3 is not relabeled; those actions were not repeated in r4, r5 or r6 (§7). - Charter, addendum, both verdicts, corrections request, follow-up, decision doc,
pinned schema/checker/fixtures,
canonical.mjs(a7760882…0172, the mock-digest canonicalizer): unedited. - Every pre-existing fixture bundle, raw case, demo copy and golden is byte-identical
to r5 (manifest diff r5 → r6: 5 files changed, 13 bundles added, 0 removed; §4).
Every prior
index.jsonexpectation is unchanged; only 13 cases were appended.
2. Correction of R5-1
2.1 The defect
r5 stableOrder broke equal-key and unkeyed ties on canonicalize(), the ASCII-only
mock content-digest canonicalizer, and mapped its CanonicalError to the empty string.
Every entry containing a non-ASCII string therefore had the same tie-break form, and
two distinct such entries with equal typed keys (duplicates) or no readable key fell
through to the input index, restoring input-order-dependent first failures — exactly
filbert's six reversed-pair witnesses. The defect was a wrong choice of domain: the
mock digest domain is deliberately narrower than the strict-JSON input domain (Unicode
record values and logical paths are permitted input), so a digest canonicalizer can
never be a total order over inputs.
2.2 Implementation (scripts/foundation/resolve.mjs, r6 lines 719–771)
orderingForm(value)(exported, new): a total ordering form over the strict-JSON parser's output domain (null, booleans, safe integers, any well-formed Unicode string, arrays, objects): literals as JSON literals, strings and keys asJSON.stringifyliterals, arrays in order, objects with keys sorted by UTF-16 code unit, compact separators, no normalization or case folding, no length or depth limit beyond the parser's own bounds. Every parser-producible value has exactly one form and distinct values have distinct forms (injective), so the index fallback instableOrdernow decides only between byte-identical entries. It throws a plainErroronly for non-JSON values, whichparseStrictnever yields; there is noCanonicalErrorpath. It is not a digest, is never emitted or compared with a declared digest, and is not a validity judgement:canonical.mjsand theinspector-content-digest/1domain are untouched andmock-content-unsupportedsemantics are unchanged.stableOrder(items, keyOf): unchanged except that the memoized tie-break callsorderingForm(items[i])instead of thecanonicalize/CanonicalErrorfallback. Typed keys, keyed-before-unkeyed, component comparison and the input-index locator are exactly r5.ORDER_KEYS,checkInventory,shapeValidationOrder, the digest/identity/structural traversals andModel.orderare unchanged.- Nothing else changed: no blanket Unicode rejection (the Unicode positive controls
stay
allowed), semantic sequence arrays are still never reordered, family and stage precedence are unchanged,detailremains internal and no value is echoed, the closed rule/reason/exit vocabulary is unchanged, no new dependency.
2.3 Regressions (fixtures in build-fixtures.mjs 1231–1266; tests in resolve.test.mjs 723–801)
The fixtures rebuild filbert's witnesses from the base bundle. Each pair carries two
different shape failures on two distinct entries with a legitimate non-ASCII value,
forward and reversed; the expected first rule is the same in both orders and in every
permutation (assertPermutationStable, all permutations for ≤ 4 entries, the fixed
deterministic family beyond that).
| Case | Content | Expected first rule (both orders) |
|---|---|---|
shape-order-unkeyed-unicode-{records,registries,artifacts,delegation-inputs}-{forward,reversed} (shape) |
[{"extra":"é"}, "é"] as the whole inventory: two unreadable-key entries |
shape-type-mismatch at the string entry (form "… sorts before {…); r5 flipped to shape-unknown-field/shape-missing-field in one order |
shape-order-equal-key-unicode-records-{forward,reversed} (shape) |
two agent-definition/agent-a/system/1 copies, both displayName: "Café", one status: "invalid-status", the other an unknown payload.extra |
shape-unknown-field at .payload.extra (the copy with the extra key sorts first: "extra" < "harnessRef"); removing the extra key yields shape-enum-mismatch (the pair really carries two errors) |
shape-order-equal-key-unicode-registries-{forward,reversed} (shape) |
two agent-policy/ap-full/1/<same digest> copies, readPaths[0].path: "café", one network: "everything", the other an unknown restrictions.extra |
shape-unknown-field at .content.restrictions.extra; removing the extra key yields shape-enum-mismatch |
positive-unicode-display-name-allowed (positive) |
displayName: "Café 😀" on agent-a |
allowed |
Unit tests: "R5-1: the ordering form is total and injective…" (37 hand-built values
covering every parser type, NFC/NFD and case-distinct strings, NBSP/U+2028, escapes,
nested arrays/objects, Unicode keys and values: 37 distinct forms; 12 of them (test bound ≥ 12)
are refused by canonicalize() with CanonicalError, proving the domains differ; key
order independent of insertion order and by code unit; array order semantic; string
form equals JSON.stringify; stableOrder on the unkeyed and equal-key Unicode pairs
in both input orders for all four families; only a structuredClone duplicate falls
back to the index), "R5-1: unkeyed Unicode entries…" (per family: permutation-stable
shape-type-mismatch with a null locator key, the two fixtures are exact reversals,
and the located entry is the string in both), "R5-1: equal-key Unicode entries…"
(permutation-stable shape-unknown-field with the asserted agent-a key and
.payload.extra / .content.restrictions.extra tails, the sibling enum error is
reachable, the Unicode positive stays allowed). The existing stableOrder unit test
keeps its r5 expectations ("not-an-entry" still precedes {registry: 7}).
Filbert's own witness files (/tmp/fi-filbert-7.239u2bco-evidence/witnesses/, read
only) through the r6 inspector: all six Unicode pairs now report the same rule in
both orders (shape-type-mismatch for the four unkeyed pairs, shape-unknown-field
for the two equal-key pairs).
Mutation witness (scratchpad copy only, discarded): with the r5 tie-break
(canonicalize + CanonicalError → "") restored in the r6 tree, the three R5-1 unit
tests and the "evaluate over every bundle fixture" index check fail (the 13 new
index.json expectations flip), while all 34 other resolve tests pass; the r6
regressions therefore detect the r5 behaviour.
3. Disclosures for the reviewer
- (a) Index fallback.
a.i - b.iremains as the final comparator and now decides only between byte-identical entries (equal forms ⇒ equal values). The r5 §3(a) wording was wrong for non-ASCII entries; the corrected claim is asserted by the injectivity test and the equal-key fixtures. - (b) Ordering form vs. canonical digest. Two different serializations now exist
in
resolve.mjs/canonical.mjson purpose: the digest form is the frozen mock domain (ASCII,CanonicalErrorfor everything else, unchanged); the ordering form is total. They agree on the shared ASCII domain up to representation but are never compared with each other. The ordering form is never written to output. - (c) Cost. The form is computed at most once per entry per
stableOrdercall (memoized) and only for ties; inputs are already bounded by the strict parser (MAX_ITEMS/MAX_DEPTH/MAX_STRING_BYTES), so no new resource bound is introduced. - (d)
registry-declaration-missingsemantics: unchanged; the FI-FILBERT-7 verdict confirms them as consistent. - (e) Permutation family for large inventories remains the fixed deterministic subset (r5 §3(d)); the new unkeyed pairs have two entries (all permutations); the equal-key records pair sits in the 36-record inventory (35 base records plus the copy) (deterministic family).
- (f) r3 live-branch correction (r4 §3(g)) remains in force and unrelabeled (§1, §7).
4. Changed files (r5 → r6 sha256; everything else byte-identical, 13 fixtures added, 0 removed)
| File | r6 sha256 | Change |
|---|---|---|
scripts/foundation/resolve.mjs |
c4951014828080caf9a5038845104afdac02465af10e94a2fddd3558b29621a3 |
orderingForm; stableOrder tie-break (§2.2) |
scripts/foundation/resolve.test.mjs |
dca397f268cfd39feffae3839f57afc61fe74ca324645dd1d916219f38d4b15b |
three R5-1 tests; orderingForm/canonicalize imports; two comment/title words |
scripts/foundation/fixtures/build-fixtures.mjs |
ea5a54028b75cc6f3fbce1666f6fad04b3df774a137b0fd281da0a1abb0d0cab |
13 FI-ROCKO-8 cases (§2.3) |
scripts/foundation/fixtures/index.json |
e5b2cf8d6ad0bab6aa232edf80492ca58dae260940f52cf87e34525b166b459a |
347 cases (was 334) |
scripts/foundation/fixtures/README.md |
c69c64a15b0a20105c46d6b8e04e32a80d8c9b025f9f47aa9e18679a69da8ed2 |
tie-break wording; FI-ROCKO-8 paragraph |
scripts/foundation/fixtures/bundles/* |
13 added (manifest) | none modified |
Group counts (index.json): admission 62, continuity 2, cycle 6, identity 7, lexical
19, operation 7, ownership 10, positive 22 (+1), profile 47, proposal 48,
registration-delegation 13, shape 97 (+12), structure 7.
5. Receipts (run 2026-09-07 15:2x UTC at HEAD 9a5fbdbd; logs kept in the session scratchpad)
| Check | Result |
|---|---|
NO_COLOR=1 PYTHONDONTWRITEBYTECODE=1 scripts/test-foundation.sh |
43 passed, 0 failed |
node --test scripts/foundation/ |
80 tests, 80 pass, 0 fail (was 77) |
python3 scripts/foundation/verify-schema.py (jsonschema 4.26.0, pinned hashes) |
PASS; corpus 1568 records; schema column agree-valid 540, agree-invalid 991, DISAGREEMENTS 0; profile refusals asserted 30 |
python3 docs/plans/foundation-v1-candidate/check.py |
PASS |
scripts/test-config.sh / test-conductor.sh / test-auth.sh |
24/0, 17/0, 15/0 |
scripts/test-task.sh, scripts/test-release.sh |
NOT RUN / DEFERRED (owner decision, §7) |
every new fixture through the CLI (env -i, PATH=/nonexistent, HOME=/nonexistent) |
13/13 match index.json; every pre-existing case unchanged; fresh generation equals the checked-in tree |
| filbert's six Unicode witness pairs through the r6 CLI | same rule in both orders for all six (§2.3) |
| git | HEAD unchanged, nothing staged, no candidate file tracked; no __pycache__ created |
6. Constraints honoured
No edit to charter, addendum, verdicts, corrections request, follow-up, decision doc,
pinned schema/checker/fixtures, canonical.mjs, prior reports or manifests, CURRENT,
shared logs, root/package files, policies or runtime data. No blanket Unicode
rejection. 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 or container launch. Tests spawn the inspector; the inspector spawns
nothing. Finite tests and static flags are evidence, not sandbox proof. No fake
full-suite pass, no new waiver.
7. Deferred coverage (owner decision, unchanged)
Per 2026-09-07_foundation-inspector-demo-test-gate-decision.md (Jason, 2026-09-07
14:47 UTC): scripts/test-task.sh and scripts/test-release.sh are deferred for this
offline inspector demo and are reported NOT RUN / DEFERRED, never passed or fully
covered; no live model calls, deployment actions, weaker inspector behaviour or
permanent removal of tests are authorized. Still required and not rocko's to grant:
filbert's independent code approval and Jason's separate synthetic demo acceptance.
Full deployment/integration testing remains a later gate. The r3 execution of the
live branches (r4 §3(g)) is neither authorized nor relabeled.
8. Freeze
Frozen at the r6 manifest (docs/plans/reviews/2026-09-07_foundation-inspector-rocko-build-manifest-r6.json,
sha256 a4a4493000aff5905337a643886ca36e7c5377d52deed77b8aeab7174ca73dcf; 382 files:
source 6, tests 5, suite 1, fixtures-meta 3, bundles 328, raw 19, demo 20; aggregate
scripts/foundation/ 380 files e9d406b3…3dff) for filbert's independent re-review.
Rocko changes nothing under the allowlist until darkwing returns reconciled findings.
C1 (Archify rev 3) remains HELD; no lane action taken.