Files
stack/scripts/foundation/fixtures/README.md
T
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

6.1 KiB
Raw Blame History

Foundation inspector fixtures

Synthetic, deterministic inputs for scripts/foundation-inspect.mjs and its tests. Nothing here is live: identities, digests, times and paths are invented by build-fixtures.mjs (SHA-256 of synthetic:<label> for every fake digest).

Path Content
build-fixtures.mjs Generator. node scripts/foundation/fixtures/build-fixtures.mjs <out-dir>
bundles/<case>.json One complete bundle per evaluation case (pretty JSON, trailing newline)
raw/<case>.json Byte-exact lexical cases (duplicate keys, BOM, invalid UTF-8, oversize, ...)
index.json Expected exit/result/reason/rule/proposalRule[/byteOffset] per case, sorted by name
demo/<case>.json Owner-demo copies of five bundles, byte-identical to bundles/
demo/<case>.expected.{txt,json,exit} Goldens: text output, --json output and exit code

Regeneration

node scripts/foundation/fixtures/build-fixtures.mjs /tmp/fx
diff -r /tmp/fx/bundles scripts/foundation/fixtures/bundles
diff -r /tmp/fx/raw     scripts/foundation/fixtures/raw
diff    /tmp/fx/index.json scripts/foundation/fixtures/index.json

scripts/test-foundation.sh performs exactly this comparison; a checked-in fixture that differs from a fresh generation fails the suite. Goldens are produced by running the inspector on the demo copies:

cd scripts/foundation/fixtures/demo
for f in *.json; do case "$f" in *.expected.*) continue;; esac
  b="${f%.json}"
  node ../../../foundation-inspect.mjs "$f" > "$b.expected.txt"; echo $? > "$b.expected.exit"
  node ../../../foundation-inspect.mjs --json "$f" > "$b.expected.json"
done

Case groups (see index.json)

positive, shape, profile, identity, structure, cycle, continuity, ownership, operation, admission, registration-delegation, proposal, lexical (raw). Every rule in the closed vocabulary except the CLI/I-O rules (covered by ../cli.test.mjs with a disposable sandbox) is exercised by at least one case; ../resolve.test.mjs enforces that.

The profile-* cases (addendum FI-C2-1) cover the strict typed-string profile: one final LF on an id/runtimeId/digest value is schema-valid under the pinned checker's $ semantics and refused by the inspector as profile-pattern-mismatch before any identity lookup (group profile); two final LFs, CRLF, CR, interior LF, U+2028 and U+2029 fail the schema pattern itself (group shape); free-form text with escaped newlines stays allowed (group positive).

The FI-FILBERT-6 correction cases (verdict findings F1F5) are the review's witness recipes rebuilt from the frozen demo bundles, each with positive controls: adm-registry-declaration-* and adm-*-authorization-undeclared (F1: every consulted registry reference resolves by exact registry/id/revision/digest, rule registry-declaration-missing; consulted dependency/mission/subject-task authorizations must be declared), adm-assigned-task-without-work-read* and prop-task-only-* (F2: a bound task is consulted work), prop-issuer-* (F3: the issuer ceiling narrows both requester calculations and work access is rechecked), cycle-*versioned* / cycle-*-cross-revision / cycle-mission-parent-*revision* (F4: revision-exact cycle graphs), shape-order-* and prop-message-* / prop-delegation-missing-after-requester-admission (F5: first failure independent of record input order; message-is-not-authority after structural validation, before requester admission). ../resolve.test.mjs asserts each recipe's first failure and permutation independence directly.

The FI-ROCKO-7 ordering cases extend F5 to the declared inventories (charter §10.4 applies beyond records): shape-order-registries-*, shape-order-artifacts-*, shape-order-authorizations-*, shape-order-delegation-inputs-* (two different shape errors per pair, forward and reversed, plus a "swapped" pair where the errors change places and a malformed entry without a readable typed key, which sorts last), shape-order-family-precedence-* (records, registries, artifacts, authorizations, delegationInputs stay in that stage order), profile-order-* (strict-profile violations follow the same key; any shape failure precedes them), shape-order-registry-digest-* / shape-order-profile-precedes-digest-registries / shape-order-two-digest-mismatches-reversed (content-digest traversal in registry/id/revision/digest order after the profile stage), dup-order-* (identity stage) and struct-order-delegation-inputs-* (structural stage). Typed keys: registries registry/id/revision/digest, artifacts runId/artifactId/digest, authorizations the runtime id, delegationInputs decisionRef kind/id/scope/revision; equal keys tie-break on the entry's total ordering form (below). Semantic sequence arrays (instruction, skill, endpoint, dependency, subject and evidence lists, paths, canonical content) are never reordered. ../resolve.test.mjs asserts the located first failure over every permutation (all permutations for inventories of up to four entries, a fixed deterministic family beyond that).

The FI-ROCKO-8 cases (FI-FILBERT-7 finding R5-1) fix the tie-break itself: r5 broke ties on the ASCII-only mock-digest canonicalizer and mapped every non-ASCII entry to one empty form, so two distinct Unicode entries with equal (or no) typed keys fell back to input order. The inspector now orders ties by a total ordering form defined over the whole strict-JSON input domain (sorted keys, array order kept, every string as a JSON literal, no normalization), which is injective on distinct values and never a digest or a validity judgement. shape-order-unkeyed-unicode-<family>-{forward,reversed} (two unreadable non-ASCII entries per family: a string and an object, shape-type-mismatch in both orders), shape-order-equal-key-unicode-{records,registries}-{forward,reversed} (two copies with identical typed keys, a legitimate non-ASCII value and one different shape error each: shape-unknown-field in both orders) and positive-unicode-display-name-allowed (control). ../resolve.test.mjs asserts the form's totality and injectivity against canonicalize() refusals and the permutation stability of every pair.