Skip to content

sdg: IP 0001 — foundational machine surfaces for an external spec UI - #7

Open
lzrscg wants to merge 290 commits into
mainfrom
claude/xspec-ui-apis-4df8fa
Open

sdg: IP 0001 — foundational machine surfaces for an external spec UI#7
lzrscg wants to merge 290 commits into
mainfrom
claude/xspec-ui-apis-4df8fa

Conversation

@lzrscg

@lzrscg lzrscg commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Improvement Proposal specs/patches/0001-external-ui-apis.md (Stage: Proposed), drafted from the seed "Foundational APIs for an external spec UI" and finalized against the Developer-confirmed scope: CLI-only connection (no service/watch surface), UI-owned text editing (no content-mutation commands), saved-files-only analysis.

Proposed SPEC.md change areas: reference occurrences with source ranges; source ranges for code locations; a whole-document structural view (tag-range decomposition, imports, comments, occurrences, direct position resolution, multi-file form); a per-file parse-local availability contract for the new surfaces; a workspace inventory with invocation-anchored root; structured diagnostics with stable codes and ranges; rename/move previews; machine-interface identification.

Also carries the preceding Liaison commits on this branch (PHILOSOPHY.md updates, seed intake) and consumes specs/tmp/SEED.md.

Process notes: branch claude/xspec-ui-apis-4df8fa is this session's harness-designated push branch and stands in for patch/external-ui-apis (recorded in the patch header). Merge happens only at Phase 11 per specs/DEVOPS.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2


Generated by Claude Code

lzrscg pushed a commit that referenced this pull request Aug 3, 2026
…rfect files (iter 8)

Applied:
- I1: change 4 now states the text-value principle for files with findings —
  Markdown compilation's removal rules classify constructs by syntactic form,
  never by validity or resolution (imports removed by form, tags removed with
  every spelled attribute, non-inventoried constructs preserved as content);
  resolution enters only via text(...) replacement, already the unavailable case.
- I2: identity definedness disambiguated — chain conditions (presence,
  well-formedness, structural validity) are inherited; uniqueness constrains the
  section's own spelled identity alone, so a uniquely spelled descendant of
  duplicate-id ancestors keeps its defined identity; defined identity does not
  imply defined prefixes, and occurrence resolution / the target filter turn on
  the referenced identity's own definedness.
- O1: spread attributes appear among the view's raw attribute spellings by form;
  invalidity is a located finding, never a view omission.
- O2: position-resolution offset domain closed — a non-non-negative-integer
  offset value is the same usage error as a greater offset.
- O3: stable-code scoping stated as deliberate — codes cover exactly the
  numbered conditions plus refusal reasons; plain usage errors carry no code but
  still get the JSON error document when JSON output is in effect.

Rejected:
- O4: the Branch header's mapping is deliberate harness bookkeeping — pushes go
  to the designated branch and the mapping is recorded in the patch header and
  PR #7; stripping it mid-process would name a branch nothing pushes to.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
claude added 29 commits August 6, 2026 20:02
…/CONF-MD scopes and exclusions for the 0001 surfaces

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…icted arm; name CONF-DISC's 14.19 path (iter 1)

Applied: I1 (VIOL-CORE-CHATTYREADS deviation states the appended line's
inertness — no 5.4 mapping, no 14.13, derived bytes independent of line
count — and the passing side now covers T10.4-5's ungated reads and
T13.5-4's derived-file comparison), I2 (new VIOL-AVAIL-NOFILE certifies
T11.3-4's restricted arm; Justification recast to claim the staging
hazard it now checks and to scope the decode claim to the datum-form
violators, with the four Exclusions references tightened to match),
I3 (CONF-DISC command surface names the 14.19 reporting path, dormant
on the conformer), O1+O4 (CONF-AVAIL restated in the shared "Contracts
under certification" pattern with graph-data/refresh out of scope and
"as staged" flag wording), O2 (VIOL-DISC-DIALECT's bracket-free
patterns labeled a staging constraint), O3 (VIOL-CORE-EARLYWRITE
scoped to --test-hold invocations), O5 (Exclusions entry for the
review-operation refusal negatives).

Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ns; name bare 11.2 forms and --tag in surfaces (iter 2)

Applied all review items; none rejected.
- I1: VIOL-DISC-DERIVED — T7-4/T7-5 staging constraint extended: discovery
  observations run before any generated file exists, closing the leak from the
  conformer's own next-to-source .xspec. output under T7-4's bare * pattern.
- I2: CONF-CORE — read surface enumerated exactly, the 11.2 surfaces declared
  outside it, and T13.4-5's/T13.5-4's read sweeps pinned to it by constraint.
- I3: CONF-VALID — query nodes --tag (T2.6-1's staged selection) named in the
  command surface.
- I4: CONF-AVAIL — bare view (T11.4-1) and bare occurrences (T11.2-4,
  T11.3-4's unrestricted arm) named in the command surface.
- O1: VIOL-DISC-DERIVED destination arm stated as deterministic 14.19
  (destinations end .md, 13.2).
- O2: VIOL-CORE-PARTIALWRITE deviation pins the write on every build of
  T13.5-5's loop (byte-identical content rewritten, never skipped).
- O3: T13.5-2 bracketing constraint hoisted to CONF-CORE's scope; EARLYWRITE
  and CHATTYREADS now reference it.
- O4: T11.4-1 constraint aligned with 11.2's chain conditions (1.4 form, 1.3
  structure under 11.4's positional enclosure, unduplicated, valid paths).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…xact CHATTYREADS and CONF-VALID rationales; account T3-6 negative half (iter 3)

Applied: I1 (CONF-AVAIL scope now binds every in-scope test's commands to the
enumerated view/occurrences surface — no in-scope staging drives at, and
T11.2-4's record observations ride occurrences and view — mirroring CONF-CORE,
so the conformer can pass C-1 under any conforming harness staging), O1
(VIOL-CORE-CHATTYREADS passing side now credits T13.5-1's seam-neutrality
journal compare to identical command sequences on both twins instead of denying
the compare), O2 (CONF-MD justification accounts T3-6's uncertified negative
half via its positively anchored destination computation), O3 (CONF-VALID
justification restated to the exact corruption-catching mechanism: 14.20 or
clean build fails against the conformer; class-shifted corruption leaves the
violator's expected failure unmaterialized).

Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…Tests Specified (iter 4)

Iteration-4 review returned no Critical and no Important items; refinement
halts with the document unchanged. Optional items not applied:

- O1 rejected: T6.1-2's in-scope membership is already functionally justified
  (anchors EARLYWRITE's and CHATTYREADS's passing sides); per-test
  justification prose is a completeness motive, not a selection criterion.
- O2 rejected: T13.5-4's final compare is scoped by TEST-SPEC's own wording
  ("derived-file inconsistency is resolved... byte-equal to a clean build"),
  so the derived-files reading is assertion semantics from the test's text,
  not an open fixture-content choice needing a staging constraint.
- O3 rejected: reviewer's own finding is that nothing in the expected-failure
  set turns on the refresh-write question; residual clarity polish only.

specs/tmp/REVIEW.md deleted; no CERTIFICATIONS-PROBLEMS.md existed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…R gets no pull_request runs

Scaffolding audit for IP 0001 (Tests Specified): the existing layout,
vitest projects, npm scripts, network-denial wrapper, and E-6 exchange
wiring already cover every TEST-SPEC/CERTIFICATIONS addition; new tests
and fixtures are Phase 9/10 content under existing globs. The one gap:
PR #7 is unmergeable against main (specs/PHILOSOPHY.md conflict), and
GitHub creates no pull_request-event workflow runs for a conflicted PR
(zero runs across 45 commits). Add the working branch to ci.yml's push
trigger so the TEST-SPEC-required tests run on every push to the branch
head — the channel sdg/initial-build already used — with checks
attaching to the PR's head commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Convert the three compliance reviews (TEST-SPEC 1-9, TEST-SPEC 10-18 +
cross-cutting, CERTIFICATIONS) and the red verify run at 8294929 into a
flat, ordered task list: foundations (literal 12.7 findings decode, exit-2
stream protocol, H-7 universe re-pin), contradicting-assertion fixes,
stable-code sweeps, missing arms, missing tests (5.7, 6.5-6.7, 10-14,
11.2-11.6, 12.6-12.7), property layer + S-6 oracles, the CONF-AVAIL
certification family, and the E-6 legs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…de and S-5 guards (FP-001)

Rebuild the findings assertion layer as a literal, form-exact SPEC 12.7
decode (TEST-SPEC H-3 amended): the finding form
{code, message, locations, path, identities} with exact members,
null-vs-omission and []-vs-null rules, stable code tokens validated
against the pinned SPEC 14 vocabularies, the marked byte-form path,
the pinned findings-order comparator (numeric condition order, refusals
in 14's order, code-less last; byte-wise location/path/identity/message
tie-breaks with the prefix rule), and duplicate collapse — new
test/helpers/adapters/forms.ts, never adjustable to a product's shape,
with its own form-exact failure trailer.

Model: Finding carries the token code; the 14.N condition identity is
derived through the harness-pinned token table (model.ts) so existing
condition-identity assertions are expressed against tokens. Add the
three-state datum decode (plain / null / {"unavailable": true}) and the
unavailability-marker structural walk T12.7-1 relies on; S-5 guards for
all of it (58 S-5 tests green).

Sweep every compile-affected call site: located conditions assert via
locations, path-level conditions (14.10/13/19/21/23) via the concerned
path, policy findings via the contractual 14.12 identities quadruple,
cycles via participating-file locations (byte-precise full-path staging
stays T14-8/FP-081). Certification fixtures emit the 12.7 form (minimal
mechanical conversion; CONF-VALID behavioral rework stays FP-009).

Gate: npm run test:self — 5 failed / 228 passed, exactly the
pre-existing baseline (certification-document x3 until FP-091,
s1-traceability x2 until FP-003); S-5 and certification green; affected
suite files red-as-diagnosed HarnessAssertionError against the current
product's pre-12.7 shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ffect (FP-002)

SPEC 12.0/12.7 and amended H-5: with JSON output in effect (--json among
the arguments, even erroneous ones, or a JSON-only surface), an exit-2
invocation emits the single 12.7 error document {"error": ...} as its
entire stdout; stdout is byte-empty on exit 2 only when JSON is NOT in
effect; the output form never changes exit codes or stderr content.

- assertions.ts: invert assertJsonOutputConvention's exit-2 branch to the
  error-document contract (protocol grain; P-8 inherits it).
- forms.ts/model.ts: add the form-exact decodeErrorDocument ({"error": ...}
  holding one literal finding form) with S-5 good/bad decoder guards.
- support.ts: expectErrorDocument sugar; expectConfigurationError now
  asserts the error document with stable code configuration-error and a
  non-null concerned path, stderr /config/i duty unchanged.
- Sweep every exit-2-with-JSON stdout-empty assertion to the error
  document: sections 6.3/6.4/6.5 usage-error helpers, 7-basics and
  7.1-7.3 T7-3/T7.3-1 query arms (JSON-only surface), 7.4-7.5 T7.4-1,
  10.1, 10.2-10.3, 10.7-i/ii, 11, 12.0-i (T12.0-2/-4/-5/-6), 12.3-12.5;
  human exit-2 arms keep byte-empty stdout.
- T12.0-2: add the stderr-invariance arms — a failing build (exit 1) and
  the unknown-flag usage error (exit 2), each run with and without
  --json, stderr byte-identical across forms (H-4 product-to-itself).
- assertion-protocol self-test reworked to guard the inverted convention.
- conf-disc fixture: emit the error document under --json (UsageError
  carries code/path; configuration errors decorated centrally with
  configuration-error and the anchoring-form concerned path) so T7-4
  stays certified; violators unchanged.

Verified: npm run test:self at 5 failed / 230 passed - exactly the
pre-existing s1-traceability x2 (awaits FP-003/stages E-G) and
certification-document x3 (awaits FP-091); certification fully green.
Affected suite files fail red-as-diagnosed only (HarnessAssertionError)
against the current product, e.g. 12.0-i 5/6, 6.3 2/4, 7.4-7.5 7/8, P-8
falsified with seed+shrink via the shared helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…T6.7-1; remap T11-* to 11.1 (FP-003)

- s1-traceability: EXPECTED_KEY_COUNT 71 -> 81 (SPEC.md now carries 70
  subsections: 5.7, 6.7, 11.1-11.6, 12.6, 12.7 added); universe-count
  assertion green again.
- Manual restructuring moved SPEC 6.6 -> 6.7 (new 6.6 is Previews):
  re-register the test as T6.7-1, rename registry module and wrapper to
  section-6.7.*, update all SPEC citations; red-as-diagnosed under the
  new ID.
- Traceability: T6.7-1 -> [6.7]; T11-1..T11-5 -> [11, 11.1] (their
  both-forms arms assert the section-11 body's JSON-only contract),
  T11-6/T11-7 -> [11.1]; fix the body-key comment (11 now has
  subsections); note T12.0-10's aliasing ends once its own arms are
  implemented; SPEC_BODY_TEXT_KEY_SECTIONS unchanged per amended H-7.
- S-1 unmapped-key red narrows to {5.7, 6.6, 11.2-11.6, 12.6, 12.7} --
  6.6 joins deliberately (the retired T6.6-1 no longer falsely covers
  Previews); stays red until stages E/G land.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…age the deleted-location side (FP-004)

T10.7-12 asserted a present code-impact scope must carry no source range;
current SPEC 10.7/1.7 fixes the opposite: every present node, requirement
node and code location alike, enters the payload with its range, and only
a deleted location's entry carries none. The scope is now the named unit
src/ref.ts#refUnit, its construct range byte-asserted against precomputed
offsets behind a multi-byte prefix; src/del.ts (added v1, deleted v2)
stages the deleted side. assertPresentState requires the range;
T10.7-12 maps 1.7 beside 10.7 per TEST-SPEC's stated delegation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…s as T6.5-5 exit-2 usage errors (FP-005)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…oken-exact and 12.7-literal via FP-001's layer

Research disposition, no code change: every §§1–9 numbered-condition
assertion site routes through the shared helpers FP-001 rebuilt
(buildFindings/assertConditionCounts/assertFindingLocated/
finding.condition/expectConfigurationError) on the form-exact 12.7
decode; the 14.N identity is the pinned-table image of the
decode-validated token, so each assertion holds exactly for the one
SPEC 14 code string, and expectConfigurationError asserts
configuration-error directly. No stderr/human/ad-hoc-JSON condition
assertions exist in §§1–9 (conditionMention is S-5-only).

Verified: npm run typecheck clean; npm run test:self 4 failed / 231
passed — exactly the planned mid-loop reds (certification-document x3
until FP-091, s1-traceability until stages E/G), S-5 and certification
green; FP-001-untouched section-2.4 probe red-as-diagnosed at the
form-exact decode against the pre-12.7 product.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…oss the §6 refusal arms (FP-007)

Extend both expectRefusalModifiesNothing helpers to run refusals under
--json, decode the form-exact 12.7 findings-only report, and assert exactly
one finding per arm carrying the exact stable refusal code plus its
concerned identity, path, or located participant (SPEC 14, T14-7 staging
record: T6.4-3, T6.5-4, T6.5-6). New support helpers
assertFindingMentionsLocation / assertFindingNamesIdentity /
assertFindingConcernsPath; invalid-workspace precondition arms assert the
one located 14.5 finding alone; traceability adds "14" to the three
staged-at tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…7 path (FP-008+FP-009)

T1.3-6 gains the two invalid-form arms (repeated `id`, braced `id={"x"}`):
each bearer reports 14.17 and never 14.1, masks 14.2 for its immediate
child, and the grandchild's structural check still reports — exact counts
{14.17: 1, 14.2: 1} with byte-window location assertions behind a valid
sibling. The CONF-VALID fixture's lexer now parses attribute occurrences
and braced values (well-formed MDX, never 14.20): repeated props and
non-quoted-static id/tags values report 14.17 (`invalid-prop`), an
afflicted `id` spells no identity and masks like a missing one.

Verified: CONF-VALID conformer 12/12 in-scope tests; both violators fail
exactly their certified tests and pass T1.3-6; suite T1.3-* stay
red-as-diagnosed against the stub; test:self keeps only the 4 planned
mid-loop reds (certification-document x3 -> FP-091; S-1 unmapped keys ->
stages E/G).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…e/span literalness with check and query nodes/edges (FP-010+FP-011)

T3-1 now stages construct-like bytes inside two fenced code blocks and an
inline code span and asserts they create no node (exact query-nodes identity
set via a new scoped identity-only decoder, S-5-guarded), no edge (exact
contains+depends set), no finding (build and check exit 0), and byte-exact
preservation. The CONF-MD conformer gains a Markdown literal-region pre-scan
feeding its lexer, a check command, and honest whole-report query
nodes/edges; a probe shows the pre-rework conformer failing the staging with
the diagnosed spurious 14.20. Conformer 8/8 in scope; violators certify
exactly T3-3+P-2 and T3-4+P-2; test:self keeps only the 4 planned mid-loop
reds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…reachable paths, and query-node edge lists (FP-012)

T1.7-1 gains SPEC 1.7's second half: everywhere a graph node appears as an
edge endpoint it is a bare identity, requirement node and code location
alike. A new workspace stages references/depends/embeds edges entering the
graph at code locations; the arms pin exact edge sets and the witness path
through the H-3 decoders, and a new adapter-layer walk (S-5-guarded)
rejects any range datum accompanying an endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…s (FP-013)

Two arms appended to T4_3_2_ARMS: text(); and text(SPEC.a, SPEC.a.b); —
the two-argument arm passes two static resolvable node chains per
T2.4-3's MDX precedent so arity is each arm's sole defect, asserting
exactly one 14.8 at the call. Probe-verified against the built product
(valid one-argument control exits 0; each arm one 14.8 in-window); suite
test stays red-as-diagnosed at the FP-001-class form-exact decode gap.
test:self unchanged: 4 planned mid-loop reds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
The root-marker test gains its second workspace: MAIN.mdx bears a
root-sourced {text(...)} embeds edge into OTHER.mdx (top-level, outside
any section — the T8-5 shape), plus an untouched local section as
control. An edit to the embedded target's text changes only the root's
effectiveHash, so the marker's location is transitively — never
directly — impacted, with the forced witness path root -> upstream, and
the complete category table pins that no node of the marker's document
is changed (MAIN root exactly upstream-changed). Reuses section-5.6's
impactAgainst/assertRequirementCategories and section-9's
assertImpactedCode. Genuine pass against this repo's product
(probe-validated); suite and self-test states unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…3 adapter (FP-015)

T6.4-1 now runs the rename with --json and decodes the command's own
report: a successful rename's report is the applied mapping — every
identity pair the operation journaled, the information of the preview's
mapping (SPEC 6.4, 6.6), carried in JSON per 12.0. The report shape is
unpinned, so the decode lives in a new adjustable H-3 adapter
(test/helpers/adapters/operations.ts, assumed shape mirroring the
preview's pinned 12.7 mapping member), fail-loud on a mapping-less
report; the pairs are asserted as a complete set (support.ts
assertAppliedMapping) against the fixture's pinned mapping. S-5 gains
the adapter's positive control and wrong-shape rejections.

T6.4-1 turns falsely-green -> red-as-diagnosed at the mapping decode
(the product reports {"findings":[]} on successful rename); the other
section-6.4 failures are the unchanged pre-existing exit-2/refusal-form
gaps. test:self keeps exactly the 4 planned mid-loop reds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…e arms (FP-016)

Base and ordering arms gain the discovered-code-source <file> operand (exit
2, judged like existence before source validation) on a spec+code config;
three new arms pin parse-local old-ID existence over spelled identities
(SPEC 6.4, 11.2): duplicate spellings and an id-less ancestor's sole bearer
refuse via the workspace's one numbered finding (14.3 / 14.1, T6.4-6
protocol, nothing modified), while a repeated-id sole would-be bearer spells
no identity and exits 2 beside that file's premise-pinned 14.17 findings.
Probed sound against the built product; suite red-as-diagnosed at the
FP-002-class error-document gap; test:self unchanged (4 planned reds).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…017)

T6.5-1 decodes the file-form move's own report through the H-3
applied-mapping adapter and asserts every journaled identity pair — the
moved file's four nodes, implicit root included; T6.5-3 does the same for
the section form: exactly the moved subtree's prefix-replaced pairs
(SPEC 6.5: both forms report as rename does; T6.4-1's protocol, FP-015's
adapter and helper). Both tests turn red-as-diagnosed at the decode
against the current product, which reports {"findings":[]} with no
mapping member.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…d-path refusal arms (FP-018)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…l arms (FP-019)

Wrong-kind (code-source) origins in each form ride the base and ordering
arms on a spec+code config, exit 2 inside modifies-nothing compares; the
two missing mixed-synopsis invocations land beside the dead-letter third
(classification by spelling alone, exit 2, nothing modified); parse-local
origin-ID existence mirrors T6.4-4: dup/anc refuse exit 1 with exactly
the one 14.3/14.1 finding, solo (repeated id, 14.17 premise) exits 2
beside its file's findings. Probed sound against the built product;
suite red-point and self-test reds unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Six arms: $0, trailing $, and $ before a non-digit, staged once in from
and once in to. Build exit 0 is the load-without-14.14 assertion; exact
14.12 finding sets over capture/dropped-$/one-byte-wildcard/regex-anchor
bait paths assert literal-bytes-only matching. The trailing-$ to arm pins
its anchor-bait edge via query edges, then asserts check exit 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…records (FP-022)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…023)

New registry module test/suite/registry/section-5.7.ts (+ thin wrapper,
manifest spread, traceability "T5.7-1": ["5.7"]): one workspace staging
every occurrence kind — a three-entry mixed d array, a single-reference
d, an MDX {text(...)}, a TS text(...) call, a TS marker — plus the
duplicate d={[BASE.a.b, BASE.a.b]} and a twice-spelled marker. Asserts
the complete 11-record occurrence multiset (one per d array entry, never
the array or the prop; one per embedding/call/marker with its edge kind;
two per duplicate pair at distinct ranges) through the form-exact 12.7
occurrences decode, and the collapse side via the complete 17-edge query
edges set. Red-as-diagnosed at the occurrences invocation (exit 2,
unknown command — the 11.3 surface is patch-new); staging proven by
direct edge-set probe and by shim runs (conforming answer green,
per-array deviation red at the multiset). test:self unchanged: 4 planned
mid-loop reds, S-1 unmapped keys 9 -> 8 ("5.7" now mapped).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…nd (FP-024)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
claude and others added 30 commits September 10, 2026 17:10
… section move, T6.5-7) as out of phase and superseded by the rewritten SPEC 6.5

Research: src/ is unchanged since the plan's commit 72ad038 and the
code-file loop of src/core/move.ts ("Code files: chain retargets plus
added imports") still emits additions only, so the task is not
implemented; this loop runs under Phase 9, whose scope guard forbids
modifying src/; and the SPEC 6.5 sentence the task quotes ("removed
exactly when its binding had references and the rewrite leaves it with
none") no longer exists — the rewritten 6.5 removes a declaration
exactly when an occurrence used a binding of its before the rewrite and
none uses any binding of its after it (a type-level spelling is no
occurrence), which pins the text-binding case the task left
"conservative". TEST-SPEC's T6.5-7 entry is unchanged by the revisit.

No replacement task: a product task cannot be worked in any Phase 9
iteration, and the Phase 10 compliance determination re-derives product
gaps against the revised SPEC once no plan file exists (PROCESS.md,
Ralph Loop, step 3). The task's diagnosis and code pointers stay in git
history at 72ad038. A dated re-descent note in the plan's header records
these facts for the following iterations. No code changed; no tests run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…er, T6.5-9) as out of phase, recording that its requirement, T6.5-9, and the harness's added-import assertions are unchanged by the revisit

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…re the in-memory re-validation, SPEC 6.6) as out of phase, recording its reproduction against 54b53a4 and that its 6.6 basis, T6.6-3, and the refused-preview encoding are unchanged by the revisit

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…a hand-staged scratch workspace lives

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
… colliding import bindings masked, SPEC 11.2/14) as out of phase, recording its reproduction against 0c5a2b7 and the revisit's pinning of its collision arm, and add Task 6 registering TEST-SPEC's unregistered T4.5-8 in the harness

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ore the 13.3 gate, SPEC 6.3/12.0) as out of phase, recording its reproduction against d4aabcb, the revised 12.0's configuration-before-baseline ordering, and TEST-SPEC's unasserted invalid-baseline-beside-failing-workspace case, and add Task 7 registering the unregistered T6.3-5

Task 5 is a product task (src/), which Phase 9's scope guard forbids. Research
recorded in the plan's re-descent note: not implemented (impact.ts 147/156/161/171,
review.ts 145/165/170/181, baseline.ts header unchanged since 72ad038); both
reviewer observations reproduce against the build of d4aabcb (exit 1 with the
current workspace's duplicate-id / journal-error findings for impact --base and
review create --base, text and --json; the valid-current control exits 2 with the
6.3 error, nothing written); the quoted 6.3/12.0/13.3 clauses persist verbatim;
T6.3-1..4 and T13.3-3 are byte-identical to 72ad038; no registered test reaches
the post-gate divergence. Pointers: the rewritten 12.0 orders configuration
errors ahead of baseline errors while the product validates the configuration
after readBaseline; T12.0-10 was re-worded while section-12.0-i/ii.ts did not
move; T6.3-5 (added by 3031926) is registered nowhere under test/ — Task 7.
AGENTS.md: how to hand-stage a git-backed scratch workspace for baseline-taking
commands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…— FIX_PLAN Task 6 — red against the product at every colliding arm and the spec-source case, its type-level controls green

TEST-SPEC T4.5-8 is now `T4_5_8` in test/suite/registry/section-4.5.ts
(SUITE-15: T4.5-1 … T4.5-8) with its H-7 entry in traceability.ts, and
FIX_PLAN Task 6 is removed with a dated completion note.

The test stages, per colliding form at module scope — `const SPEC = 1`,
`function SPEC() {}`, `class SPEC {}`, `enum SPEC {}`, `namespace SPEC {
export const v = 1 }` — a code source importing `SPEC` and `text` from
`../specs/A.xspec` with the marker `SPEC.a` and the call `text(SPEC.b)`,
both targets existing, and asserts: `build --json` and `check --json`
report exactly [14.7, 14.7, 14.15] in 12.7 order, exit 1 — each 14.7
byte-exact at the span its occurrence would occupy (the bare chain; the
call, callee through closing parenthesis; terminators excluded), the 14.15
locating the import by its own characters and the non-import by the
construct binding the name (the declarator `SPEC = 1`, the `const`
statement excluded) and nothing else; the gated `query edges --from
src/app.ts` reports those findings without answering (13.3; the
findings-only document, no edge); and `occurrences --file src/app.ts`
carries them and lists no record (5.7, 11.2). The type-level controls
(`interface SPEC {}`, `type SPEC = number`, `namespace SPEC { export type T
= number }`) assert `build` and `check` exit 0 and the file's outgoing edge
set exactly the `references` and `embeds` edges. The spec-source case
(`export const BASE = 1` beside `import BASE from "./BASE.xspec"`, a
section with `d={BASE.a}` and `{text(BASE.b)}`) asserts [14.5, 14.6, 14.15,
14.16] in 12.7 order — the `d` expression braces-excluded, the embedding
brace through brace, the 14.15 locating the import and the declarator
`BASE = 1`, the 14.16 the export statement whole — on `build`, `check`, the
gated `query edges --from specs/COL.mdx#c`, and `occurrences --file
specs/COL.mdx` with no record. Conservative operationalizations are noted
in the module header (H-4).

Verdict against the build of b4c4661 (T4.5-1 … T4.5-7 stay green): T4.5-8
fails as a diagnosed product failure at its first colliding arm — `build
--json` beside `const SPEC = 1` exits 0 with no finding. Red-checked by
hand-staging every arm's exact bytes (AGENTS.md): each of the five
colliding forms parses and yields exit 0, no finding, both edges and both
occurrences recorded — the product's collision rule
(src/core/code-analysis.ts 606–645) pairs import-bound names only, so
non-import declarations raise no 14.15 and the chains resolve through the
import, a broader failure than Task 4's note predicted (no condition-15
finding at all, not a masked condition 7); the spec-source case reports
the 14.16 alone (range exactly the export statement) and resolves the
`d` and `text(...)` spellings at exactly the ranges the harness expects
for its 14.5/14.6 — the harness's byte offsets confirmed against the
product's own occurrence ranges; and the three type-level controls pass
(exit 0, both edges). No staging error: every arm's failure is the
product's.

Self-tests: `npm run test:self` 343/346 — S-1 green with the map entry;
the three remaining failures are the pre-existing certification-document
lag the harness carries since 035b088/cbb0a35 (the fixture manifest lacks
VIOL-CORE-LATELOCK: 18 violators in CERTIFICATIONS.md vs 17 pinned, and
T13.5-8 named in scope for CONF-CORE but unregistered), untouched here.
`npm run typecheck` and `npm run format` clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…n the harness — FIX_PLAN Task 7, the plan's last task, so the plan file is deleted — green against the product on every arm

T6.3-5 is registered in test/suite/registry/section-6.3.ts (SUITE-23 now
T6.3-1 … T6.3-5) and in the H-7 traceability map ("6.3", "10.7", "12.0").
Verdict per arm against the build of 24c9487 (src/ untouched): (a) the
repository-subdirectory arm green — `impact --base c1` from R/sub and from R
with `--config sub/xspec.config.ts` both report exactly `specs/A.mdx#a`
changed and `specs/A.mdx` descendant-changed attributed to it (T5.6-1's
leaf-edit table), identically; (b) both nested-repository stagings green —
the nested repository initialized after the outer committed its files with
the extra section, and the in-place submodule (the outer's v1 a gitlink and
no files): `impact --base v1 --config inner/xspec.config.ts` from R resolves
v1 in the inner repository (the extra section on neither side) and `review
create --base v1` records the inner v1 hash among the exported creation
parameters and not the outer's, no item naming the extra section; (c) the
no-repository arm green — exit 2, the error document, stderr echoing HEAD or
the repository, nothing modified; (d) the configuration-absent-at-ref arms
green — a commit predating sub/xspec.config.ts and one holding the file under
another name, from R/sub and from R with --config, plus `review create --base`
on the predating commit: each exit 2 with stderr naming xspec.config.ts,
nothing modified. No red-check was needed (no arm fails); the discriminating
assertions are positive-form (an exact identity set, the inner hash's
presence).

Operationalizations recorded in the module header: the leaf-edit report
shape; the recorded commit as a string leaf of the product-shaped creation
parameters (the §10.2/§10.6 technique; the full hash or an abbreviation of at
least 7 hex digits) beside the outer hash's absence; the no-repository
error's wording (HEAD, or the repository/git) and its staging premise —
checked through git under the product's isolation, a harness condition if it
fails; the absent-configuration error naming xspec.config.ts. Helpers
expectExitAt/impactAt/expectBaselineUsageErrorAt take an explicit working
directory; the existing helpers delegate to them, T6.3-1 … T6.3-4 unchanged
and green. Certification: T6.3-5 lies in CERTIFICATIONS.md's Exclusions —
no fixture or manifest work.

Verification: `npm run build`; the section-6.3 suite file 5/5 green (T6.3-5
in 8.3 s); `npm run test:self` 343/346 — the same three pre-existing
certification-document failures as before this task (the fixture manifest
lacking VIOL-CORE-LATELOCK — 18 violators in CERTIFICATIONS.md against 17
wired — and T13.5-8 unregistered), a matter for the Phase 9 compliance
determination, not this task; `npm run typecheck` and `npm run format:check`
clean.

AGENTS.md records how a nested repository or an in-place submodule is
scripted through the builder's `git([...])` (`-C`, an inline identity,
`protocol.file.allow=always`).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…IX_PLAN.md

Convert the second re-descent's first compliance determination (reviewers A/B/C
and the red VERIFY report at 8342cdc) into a dependency-ordered task list:
Part A wires T13.5-8 and VIOL-CORE-LATELOCK so the three red self-tests turn
green first; Part B lands the shared helpers (permission-removal staging with
E-1 self-verification, the form-exact performed-operation decoder, the exact
refusal-identities expectation, the CONF-VALID alphabet); Parts C–E carry the
per-section arms and the unregistered tests, overlapping findings merged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
… in the harness — FIX_PLAN Task 1

Adds T13.5-8 to test/suite/registry/section-13.5.ts, spread through the
section array and mapped in traceability.ts to 13.5, 13.3, 6.3, 6.4, 6.6,
12.0, and 14. Its arms, per TEST-SPEC §13.5 and CERTIFICATIONS.md
§CONF-CORE's staging constraints: exclusion first on a workspace failed
by a second BOM-led spec source (14.20; added after the valid build and
the audit session, masked, never an operand; its premise `build --json`
run outside every bracket) — while `review resolve --test-hold` is held,
`review create --strategy audit --name n`, `review resolve … --status
skipped`, and `rename specs/A.mdx a b`, none carrying `--test-hold`, exit
2 promptly modifying nothing, command 1 exiting 1 at the gate only after
the hold's deletion; seam ordering under `--test-hold` with no other
holder — `rename specs/A.mdx nope x` (exit 2), `review create --base
no-such-ref --name n` on a workspace verified to lie in no repository
(exit 2), and the gate arm `review create --strategy audit --name n
--json` (exit 1 with the condition-20 finding) — each creating the hold
first, byte-identical while held, exiting only after the hold's deletion,
nothing modified; and the non-mutating boundary — the refused preview
exits 2 at once, `--test-hold` beside `--preview` exits 2 creating no
hold file. The wait for a refused invocation's hold reuses the driver
whose rejection on the command's exit or on a timeout becomes a
diagnosed failure. section-6.3.ts exports its no-repository premise
helper for the baseline arm.

The gate arm asserts the finding's identity and file (condition 14.20 in
specs/B.mdx), not the zero-length range at offset 0 SPEC 14 pins for a
BOM — that range is 14.20's own subject (T1.6-5, T14); the built product
today reports [0, 3) there, a nonconformance outside this test's charter.

Verified: typecheck and format:check clean; test:self 344/346 — the
certification-document tests 1–2 remain red for Tasks 2–3, test 3
(every in-scope test implemented) now green; S-1 traceability green;
T13.5-8 passes against the built product (every arm driven, ~5 s) and,
driven through a scratch stand-in that drops `--test-hold` from one arm's
invocation at a time (nonexistent old ID, unresolvable baseline, the
gate arm, the held `review resolve`), fails each time as a diagnosed
failure naming that arm's missing hold file — never passing on exit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…_PLAN Task 2

test/fixtures/conf-core/product.mjs, the one implementation every
VIOL-CORE-* shim threads a switch through:

- BOM detection: the source decoder now keeps a leading byte-order mark
  (`ignoreBOM: true` — the default stripped it, so `build` exited 0 on
  the failing workspace T13.5-8 stages) and reports condition 14.20 with
  the zero-length range at offset 0 SPEC 14 pins, exit 1, nothing
  written — `build`, `check`, the gate of 13.3, and rename/move's
  precondition alike.
- Acquisition before every later check: `runMutating` gains a `check`
  hook run after exclusivity and the hold and before the gate and
  refresh of 13.3; `review create`'s git-less `--base` refusal (6.3) and
  its `--coverage` profile check move into it, so the baseline arm
  creates the hold first and exits 2 after its deletion. Rename's
  argument checks already followed acquisition; exclusion already
  preceded the gate. The hook is the seam VIOL-CORE-LATELOCK (Task 3)
  can position ahead of acquisition.
- `rename --preview` as the non-mutating boundary: `--preview` is a flag
  of rename; `--test-hold` beside it is the syntax-class usage error of
  12.0, judged before configuration; the refused form (nonexistent
  origin file or old ID) exits 2 acquiring nothing and creating no hold
  file; a preview of a performable rename lies outside the surface and
  exits 70 as a fixture scope error (`xspec: fixture scope error: …`,
  mirroring CONF-DISC), as does the section-form `move` (previously a
  misreported usage error).
- Every existing violator's stated passing side on T13.5-8:
  VIOL-CORE-EARLYWRITE's deferred-exit clause — a refused invocation
  (usage error, findings, or refusal) creates the hold having written
  nothing, waits for its deletion, then exits with its error;
  VIOL-CORE-EARLYREFRESH's early refresh writes nothing on a failing
  workspace, its gate findings set aside so the gate reports only after
  acquisition and the hold. Nothing the document pins moved.

Verified: typecheck and format:check clean; test:self 344/346, the two
certification-document reds left for Task 3 (T13.5-8 not yet in the
manifest), certification.test.ts unchanged — CONF-CORE 8/8, each
violator failing exactly its certified tests. T13.5-8 driven through a
temporary self-test (the AGENTS.md pattern, deleted) against every
conf-core binding: passes against the conformer, EARLYWRITE,
EARLYREFRESH, STALELOCK, PARTIALWRITE, CHATTYREADS, and PERSISTREADS;
fails against NOLOCK on exactly its exclusion-first arm (the excluded
`review create` exits 1 with the condition-20 finding where the arm
asserts 2). Hand-checked in a scratch workspace: the BOM finding's
`{"start":0,"end":0}` range, the preview and section-move exits 70,
and `--base`/`--coverage` exit 2 with no journal or session written.

AGENTS.md: the fixture-scope-error sentence now covers CONF-CORE.
FIX_PLAN.md: Task 2 removed (47 tasks remain).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
… and pin 18 violators — FIX_PLAN Task 3

The CONF-CORE conformer's mutating scaffold takes a per-command `judge` hook —
the checks CERTIFICATIONS.md's LATELOCK entry names as judged ahead of the
refresh: review create's baseline/coverage usage checks, then the 13.3 gate or
rename/move's 6.4/6.5 valid-workspace precondition (loadGraph), then
rename/move's unknown-file/id usage checks — whose loaded graph feeds the
refresh and the operation. The conformer runs it after the hold; the
`lateAcquisition` switch (bin-latelock.mjs) runs it before acquisition, so a
refused invocation exits at once with no hold file and a mutating command
started while another is held on a failing workspace exits 1 at the gate.
The manifest lists T13.5-8 in CONF-CORE's scope and NOLOCK's certifies and
appends LATELOCK last; EXPECTED_VIOLATORS is 18. AGENTS.md records the
`-t CORE` family filter for certifying one fixture family alone.

npm run test:self: 18 files, 347/347 green — certification-document 5/5,
CONF-CORE passing nine tests, LATELOCK failing exactly T13.5-8 (command 1's
hold file never appears), NOLOCK failing exactly T13.5-2 and T13.5-8.
typecheck and format:check clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…FIX_PLAN Task 4

test/helpers/permissions.ts stages environment refusals by permission
removal alone (T14-9, T14-10, T13.5-7): stageWriteRefusal(path) makes the
holding directory read-only and a file occupant unwritable;
stageWriteRefusalUnder(dir) applies that discipline to every path beneath
an area whose write paths the harness cannot name (.xspec, specs/b),
leaving the area's parent writable so a product's exclusivity state never
meets the staging; stageReadRefusalOfFile sets exactly 0o200 and
stageReadRefusalOfDirectory exactly 0o100. Each records the prior modes,
returns an idempotent restore(), and verifies itself on the harness's own
process before returning (E-1): creation, mkdir, write-open, append-open,
rename-over, and unlink must be refused (EACCES/EPERM) for a write
staging, the read refused and the kept permission granted for a read
staging; any unrefused attempt is undone and reported as
HarnessStagingError — an Error that is deliberately not a
HarnessAssertionError (H-8, H-11), never a pass or a skip (H-9).
Non-Linux platforms, absent objects for a read refusal, symbolic links,
and wrong kinds throw the same error at once. The verification functions
are exported so the self-test proves the ineffective-staging report fires
in an unprivileged process too.

test/self/permission-staging.test.ts asserts each mode against this
process's own attempts, restore()'s reinstatement, the unstageable cases,
and the E-1 report. AGENTS.md records that the self project must run
unprivileged (as root: unshare --map-user=1000 --map-group=1000 -- npm run
test:self, the inner stage of .github/scripts/run-without-network.sh).
FIX_PLAN.md's references to Task 4 now name the helper.

Verified: under the unprivileged namespace, npm run test:self is 19
files, 355 passed, 1 skipped (the non-Linux arm), certification included;
as root the six staging tests fail with HarnessStagingError naming the
privileged runner, by design. typecheck and format:check clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…X_PLAN Task 5 (harness side)

SPEC 12.7 pins the performed `rename`/`move` document: on success exactly
{"findings", "mapping"}, `findings` [], `mapping` in the preview's form —
one {"from", "to"} per mapped identity ordered by `from` bytes — and H-3
lists it among the form-exact documents. The harness decoded it through an
adjustable adapter that ignored members beside `mapping`, never demanded
`findings`, and compared pairs as a sorted set.

- forms.ts: new `decodePerformedOperationReport` beside the preview decoder
  — exact member set, `findings` the empty array, `mapping` through the
  shared `decodeMappingArray` (factored out of `decodePreviewReport`,
  behaviour unchanged there): a duplicated identity, an out-of-order pair,
  or a pair with members beside from/to rejects.
- model.ts: `PerformedOperationReport`; the "shape is unpinned" statement on
  `AppliedMappingPair` replaced by the pinned-order contract.
- operations.ts: `decodeAppliedMappingReport` is a thin alias of the
  form-exact decoder returning its `mapping` (no member ignored).
- support.ts: `assertAppliedMapping` compares the ordered arrays.
- Consumers: T6.4-1/T6.4-5, T6.5-1/T6.5-3 (every expected array already in
  from-byte order, the root's bare-path pair first), T6.6-2 compares the
  performed `mapping` to the preview's raw decoded `mapping` pair for pair
  in order, T6.6-6's real move likewise; T12.7-2's document-forms arm ends
  with a performed `rename --json` asserted as the exact two-member document.
- S-5: the performed decoder's acceptance and 15 rejections (extra member,
  findings absent/null/non-array/non-empty, mapping absent/null/non-array/
  unordered/duplicated, pair extra member/missing/empty/non-object) and the
  alias's form-exactness; the applied-mapping entry leaves the
  unpinned-adapter walk list (it is a pinned form now).

Verified: typecheck and format clean; S-5 98/98; sections 6.4 (7/7), 6.6
(5/5), 12.7 (3/3) green against the built product; 6.5 8/10 with T6.5-7 and
T6.5-9 the known diagnosed product failures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…er and close FIX_PLAN Task 5

CERTIFICATIONS.md §CONF-CORE scopes `rename` and file-form `move` as
"reporting the applied mapping in the performed-operation form of 12.7",
yet the conformer emitted {"ok": true} on success. It now emits exactly
{"findings": [], "mapping": [...]}: rename maps the renamed node and its
descendants by prefix replacement in full identity form; the file-form move
maps the root's bare-path pair (old path to new) and every section of the
moved file with its ID kept and its file part changed — each mapping ordered
by `from` bytes (the bare path a proper prefix, so it sorts first). The
human-readable lines are unchanged. No in-scope test decodes the document
yet; the fixture now honours its documented scope for the ones that will.

Task 5 removed from specs/tmp/FIX_PLAN.md (44 tasks remain).

Verified: `unshare --map-user=1000 --map-group=1000 -- npm run test:self`
19 files, 357 passed, 1 platform-gated skip (certification included, CORE
family green); Prettier clean; a hand-staged in-scope workspace shows the
two documents byte-for-byte in 12.7 form.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Replace the SOME-quantified "full 1.5 identity or bare ID" expectation
(support.ts assertFindingNamesIdentity / ConcernedIdentity) with an exact
ordered-array assertion (assertFindingIdentities) and a refusal-aware
wrapper (assertRefusalIdentities) that requires the array for every reason
SPEC 14 pins — refused-invalid-id, refused-identity-unchanged,
refused-structural-parent, refused-missing-target-parent (the concerned
identity as the sole element, in 1.5's form over the destination file) and
refused-id-collision (the located bearers' identities in location order) —
and rejects one stated for a reason 12.7 leaves unpinned (refused-cycle,
refused-destination-exists, refused-invalid-destination); either slip is a
plain harness error, never a diagnosed failure.

The three RefusalExpectation types (section-6.4.ts, section-6.5.ts, and
their consumer in section-14.ts assertRefusalReport) carry
`identities?: readonly string[]`; every identity-pinned case in
RENAME_REFUSAL_CASES, MOVE_REFUSAL_CASES, T6.5-6, and T14-7's own stagings
states its exact array (`["specs/B.mdx#"]` for the empty-ID arm; `b` then
`b.c` for the two-bearer collision). T14-7 gains the exact self-move of
either form: section form `["specs/R.mdx#a.mid"]`, file form the bare
`["specs/R.mdx"]`, each refused-identity-unchanged alone.

Results against the built product: T6.5-4 and T6.5-6 pass; T6.4-3 and
T14-7 fail as diagnosed product failures — `rename … a.mid a.then` emits
`["specs/A.mdx#a.then", "specs/A.mdx#a.then.kid"]` (SPEC 14: the new
identity alone, no produced identity beside it), and `move specs/R.mdx
specs/R.mdx` reports refused-destination-exists beside
refused-identity-unchanged (SPEC 14: alone). With the rename deviation
masked through a stand-in, T14-7 runs every other arm green up to the
file-form self-move. Self project 357 passed under the unprivileged
namespace; typecheck and format clean. Task 6 removed from FIX_PLAN.md;
Task 13's dependency note repointed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…FD in the CONF-VALID conformer — FIX_PLAN Task 7

The CONF-VALID conformer (test/fixtures/conf-valid/product.mjs) now implements the rewritten SPEC 1.4 alphabet: a segment or tag containing `"`, `'`, `\`, `&`, or U+FFFD is condition 4 (14.4). Attribute values stay read verbatim (2.4), so a backslash-u-hex escape spelling or a `&#46;` character reference inside an `id` is a one-segment ID containing `\` or `&` — never the two-segment `a.b` — and a tag spelled that way a tag containing `\`. A 14.4 finding is now one per offending `id`/`tags` attribute, however many of its segments or tokens violate, located at the attribute's own characters (name through closing quote; SPEC 14, T14-11) instead of one per segment at the whole construct; 14.1–14.3 and 14.17 keep their construct ranges. Tag sets are emitted in UTF-8 byte order (12.7's set form) rather than UTF-16 code-unit order. The two violators keep exactly their one deviation each.

Inseparably, P-1's oracle (`valueVerdict` in test/suite/registry/section-16-p1.ts) judges the same five characters invalid: its alphabet already staged both quote characters as predicted-valid, so the conformer change alone would have turned P-1's certification against CONF-VALID red. Drawing `\`, `&`, and U+FFFD remains Task 19's, whose plan text now records what landed here; Task 18's text notes the conformer's per-attribute 14.4 location.

Verified: typecheck and format:check clean; the CONF-VALID family certifies exactly as CERTIFICATIONS.md states (all 12 in-scope tests pass against the conformer; VIOL-VALID-CTRL fails exactly T1.4-1, T1.4-4, P-1; VIOL-VALID-WIDE exactly T1.4-2, T1.4-4, P-1); `npm run test:self` under the unprivileged namespace: 357 passed, 1 skipped; P-1 against the built product fails as a diagnosed product failure (the product accepts the segment `"`).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ed-unresolvable-reference from the harness vocabulary — FIX_PLAN Task 8 (vocabulary)

CONDITION_CODE_TOKENS now holds SPEC 14's 25 tokens (index N-1 is 14.N's),
with USAGE_ERROR_CONDITION_CODE_TOKENS naming 14.24 write-failure and 14.25
read-failure: the findings-array decode rejects either as a form failure
(usage errors are carried only as the exit-2 error document's code, in no
findings array), while the error-document decode admits them. The retired
refusal code refused-unresolvable-reference no longer exists in SPEC 14 and
is rejected as unknown. S-5 gains probes for each case.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…rror-document arms — FIX_PLAN Task 8

T14-6 now stages 14.24 (T14-9 (f): `.xspec` unwritable on a stale
workspace, `build --json`) and 14.25 (T14-10 (g): `specs/sub` unlistable
under `specs/**/*.mdx`, `build --json`) through the E-1 permission-staging
helper on the Linux leg, asserting exit 2 and the exact `write-failure` /
`read-failure` token as the exit-2 error document's code. The plan's
"source with read permission removed" staging is condition 20, not 14.25
(SPEC 14.25, T14-10 (a)), so the unlistable directory of T14-10 (g) is
staged instead. The stale `refused-unresolvable-reference` mentions in the
section's comments and T14-7's title are gone. Against the built product
both arms fail as diagnosed product failures: it exits 70 (internal error)
at the refused graph-data write and at the refused directory listing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…space note

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
… writes — FIX_PLAN Task 9

T13.5-7 becomes "interrupted or write-refused mutation: the pinned write
order": the refusal arms (a)–(f) of TEST-SPEC T13.5-7 — each staged by
permission removal while the mutating command is held at the 13.5 seam,
every rewritten-byte expectation read from a twin on which the same
operation ran unrefused, the state asserted entry by entry against 13.5's
per-command write order, exit 2 with the `write-failure` error document
and its concerned path — plus the kill arm constrained to the states 13.5
admits. Fixtures, stagings, twins, the pinned-state laws, and the arms live
in test/suite/registry/write-refusal-staging.ts (exported for Task 10's
T14-9); section-13.5.ts composes them and re-exports the hold helpers that
moved there. Traceability maps the new passages. AGENTS.md records the
stand-in red-check technique; FIX_PLAN.md drops Task 9 and records what
landed. Against the built product the test fails diagnosed at arm (a)'s
exit-code assertion (exit 70 at the refused write); the self project is
green under the unprivileged namespace (357 passed, 1 skipped).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
… — FIX_PLAN Task 10

Register T14-9 in the new split module test/suite/registry/section-14-ii.ts
(array section14iiTests, spread in index.ts, declared by the wrapper
test/suite/section-14-ii.test.ts, mapped in traceability.ts): contract and
recovery arms over Task 9's stagings — one per concerned path ((a) the
child rename b.k -> b.k2 so the refused rewrite is the first write, (b)–(f)
as T13.5-7 stages them, plus specs/sub unwritable for the destination's
production), the reporter sweep on a stale session-bearing workspace with
.xspec unwritable (nine refreshing reads and review create concern .xspec;
check, inventory, version, and a --preview never report), and the
precedence arms (invalid --group value and unknown node with code null, the
failing twin's ids exit 1, the identity-unchanged rename under (a)'s
staging, a --test-hold path in a read-only directory). Red-checked through
the exit-70 stand-in (all arms pass; wrong-path and silent-stderr
perturbations caught); against the built product it fails diagnosed at arm
(a) (exit 70). Self project 357 passed / 1 skipped under the unprivileged
namespace. Remove Task 10 from FIX_PLAN.md; record the stand-in's two new
mappings in AGENTS.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
… — FIX_PLAN Task 11

Append T14-10 to `section14iiTests` beside T14-9: one arm per row of
SPEC 14.25, each refusal staged by permission removal alone through the
E-1 helpers (`stageReadRefusalOfFile`, mode 0o200; `stageReadRefusalOfDirectory`,
mode 0o100), Linux-gated via `WRITE_REFUSALS_STAGED`. (a) a discovered
source's content — a spec source and a code source, each condition 20 at
offset 0, masked, the 11.2 surfaces answering per file; (b) the journal's
content — condition 13 from build, check, the gated `ids`, a refused
rename, the inventory finding-free; (c) a session file's content —
condition 21 from check, `review status`, `review list`; (d) the
configuration's content — condition 14 from every loader, `version` exit 0;
(e) a derived file's content — one per-file condition-10 finding, build
exit 0; (f) graph data — the state of condition 23 to inventory and a
move preview, the unit-form staleness to check, `ids` regenerating; (g) a
directory discovery lists — the read-failure usage error from every
loader with the 12.0 precedence arms; (h) the session directory's
listing. The two unstageable clauses are recorded in the module header.
Traceability maps T14-10 to "14", "10.7", "11.2", "11.5", "11.6", "12.0",
"12.7", "13.3". Against the built product arms (a), (c), (d), (e) pass and
T14-10 fails diagnosed at arm (b) (exit 70 at the journal `open`); the
plan preamble records each arm's outcome and AGENTS.md the arm-by-arm
red-check pattern.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…nked working directory, and the 14.24/14.25 error documents — FIX_PLAN Task 12

runErrorConfigPathsArm gains the unoccupied-`--config` arms (the non-canonical
`./../cfg//xspec.config.ts` and an absolute path, each echoed byte-for-byte as
given, SPEC 14) and their existing-file counterparts (the same spellings naming
the malformed file report the canonical `../cfg/xspec.config.ts`, 11.6). Two
Linux-leg arms, gated by LINUX_LEG_STAGED, run last: the working directory
`R/L` -> `R/a/b` with `--config ./../xspec.config.ts` reported as the physical
`../xspec.config.ts`, and the environment-refusal documents staged through
test/helpers/permissions.ts (`.xspec` unwritable on a stale workspace ->
`{"code": "write-failure", "path": ".xspec"}`; `specs/sub` unlistable ->
`{"code": "read-failure", "path": "specs/sub"}`), decoded form-exact by
assertEnvironmentRefusalDocument. Against the built product T12.7-3 now fails
diagnosed at the first unoccupied-`--config` arm (the product canonicalizes the
value); through the AGENTS.md stand-in every arm passes. Self project 357
passed / 1 skipped unprivileged; typecheck and format clean. Task 12 removed
from the plan with its landing recorded; AGENTS.md records the red-check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…arms — FIX_PLAN Task 13

T14-7 (test/suite/registry/section-14.ts) now drives `./a.mdx`, `specs//b.mdx`,
and `specs/../specs/b.mdx` as the file form's destination and as a section
form's target path over a root-level origin, each refused
refused-invalid-destination alone with `path` the spelling as given (SPEC 14,
6.5, 12.0), and a section move carrying `x` from A into B where B imports A and
`user` references `x` locally, refused refused-cycle locating exactly the local
reference spelling and B's existing import declaration, never a range for the
import that does not yet exist (SPEC 14, 5.7). The no-unlisted-code clause is
recorded at assertRefusalReport and in the module header: the form-exact decode
admits only 14's codes, and the exact multiset excludes every other.

Against the built product the six spelling arms answer as pinned; the
import-cycle arm fails diagnosed (the product locates the import declaration
alone), and the test still fails diagnosed first at its rename
refused-invalid-id arm. Red-checked through the AGENTS.md stand-in: the whole
test passes with base fixes for the product's earlier deviations, and five
perturbations are each caught as a HarnessAssertionError. Self project 357
passed / 1 skipped under the unprivileged namespace; typecheck and format:check
clean. Task 13 removed from FIX_PLAN.md; AGENTS.md records the stand-in base
fixes and the run-one-at-a-time note.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ection-14 — FIX_PLAN Task 14

T14-11 stages one byte-precise fixture per range rule of SPEC 14 beyond
T14-8's — `d` value expressions (an array entry, `d={foo}`, `d={}`), a
non-static bare reference exclusive of its `;`, the attribute conditions
14.2/14.3/14.4/14.17 at the attribute's own characters, 14.1's opening
tag, 14.15's declaration forms and colliding declarator (14.7 beside),
14.16's construct forms, 14.18's chain-extended binding, 14.20's
zero-length offsets (BOM, encoding, syntax, and the Linux-leg refused
read), and a repeated `d`'s per-spelling resolution — every offset the
UTF-8 byte length of the staged text before the pinned part, every
range asserted `{start, end}` exact. Traceability "14", "1.7", "5.7",
"11.2", "11.4". Against the built product ten arms pass and five fail
diagnosed, the registered test at arm (c) (`d={}` reported 14.20).

`d={}` is not well-formed MDX under the reference grammar, which SPEC 14
nonetheless locates as condition 8: recorded in
specs/tmp/SPEC-PROBLEMS.md (2026-09-11); the arm follows TEST-SPEC.

AGENTS.md records the per-arm driver for T14-11. Self project 357
passed / 1 skipped under the unprivileged namespace.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…n; d={} is condition 20

Resolves specs/tmp/SPEC-PROBLEMS.md (2026-09-11, d={} versus an undefined
"well-formed MDX"), Reviewer round 1 of the jump-back refinement.

Applied:
- C1: 14.20 now fixes well-formedness as a contract about the input
  languages: MDX syntax at major version 3, expression-container and
  attribute-value content exactly one ECMAScript 2024 expression (JSX
  permitted), ESM blocks import/export-only modules, the empty expression
  admitted only in flow/text position. The 14 range rule's "enclose no
  expression" clause is deleted; 2.7 and 14.20 state that d={} is not
  well-formed MDX, its syntax failure at the closing brace's offset
  (resolution (a) of the problems file: GOALS.md fixes the input language
  as MDX, so the reference grammar, not a dialect, is the inferable
  intent). The problems file is deleted as resolved.
- I1: editions named — MDX 3 / ECMAScript 2024; TypeScript 5.0 as a floor
  (a later 5.x release's syntax left unfixed, since a pin would oblige the
  product to reject newer syntax); well-formedness stated as parse-level,
  post-parse grammar checks excluded; 7 and 14.14 cross-reference 14.20.
- I2: 2.7 defines an MDX comment exactly as the grammar's empty expression
  (whitespace and JavaScript comments only, line comments ended by a line
  terminator), every other container shape classified under 14.16 or 14.20.
- I3: 14 locates a dynamic d value by its own characters, first token
  through last, enclosing parentheses included, surrounding trivia excluded.
- O1: spread entries by own characters (`...` included); an elision locates
  the whole array literal.
- O2: 4.6 makes .d.ts declarations ambient by file kind.

Rejected:
- O3: splitting long pinned sentences is stylistic, risks semantic drift in
  text the harness pins byte-exactly, and the reviewer concedes no
  redundancy; not clearly right.
- O4: no loosely coupled component is identified and the reviewer concedes
  nothing would move; nothing to apply.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…c} is a comment; declaration files by TypeScript's file-name rule

Reviewer round 2 of the jump-back refinement (SPEC-PROBLEMS.md on d={}
versus "well-formed MDX", resolved in round 1).

Applied:
- C1, resolution (b): 14.20 decides well-formedness by derivability
  under the language's syntactic grammar (its productions plus the
  supplemental grammars refining what a covering production matches).
  ECMAScript's static-semantic early errors (duplicate lexically declared
  names, an export naming no declaration, a non-simple assignment target,
  strict-mode restrictions), TypeScript's post-parse grammar checks, name
  binding, and type checking take no part. The 2.1/2.4 collisions are
  findings (14.15) in a well-formed file, within one ESM block or across
  blocks; an export statement is 14.16 whatever it names. Rationale for
  (b) over (a): the settled design in 2.1, 2.4, 14.15, and the range rule
  ("an import-binding collision locates every colliding declaration")
  treats collisions as per-construct findings in a file that proceeds,
  which serves the IP's inline-diagnostics purpose; round 1 already listed
  "a duplicate declaration" as taking no part and only its "reported after
  parsing" rationale was false for ECMAScript. (a) would reclassify that
  design and cascade into TEST-SPEC.
- I1: 2.7 states the {// c} outcome outright: a comment, a line comment
  ending at the closing brace as at a line terminator; content is the
  characters between the braces, the closing brace never among them; the
  "each ended by a line terminator" dialect qualification is dropped.
- I2: 4.6 names declaration files by TypeScript's file-name rule
  (.d.mts, .d.cts, or a .ts name with .d. earlier in its last segment).
- O1: 2.7 covers whitespace- and comment-only d braces beside d={}.
- O2: the range rule pins one finding per array literal for its
  elisions, however many.

Not applied:
- O3: downstream awareness only (TEST-SPEC T14-11 arm (c), T2.1-2/3,
  T14-3); no SPEC edit, cascades through Phases 6-7.

Stage line of 0001-external-ui-apis.md unchanged (Tested; not rewound on
the backward jump).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…terminator ends them; TypeScript-only syntax is a parse failure in a spec source

Round 3 of the Phase 4 revisit of specs/SPEC.md.

Applied:
- C1: 2.7 no longer pins `{// c}` as a comment or a line comment as ending at the closing brace; an MDX comment's line comments count only when a line terminator ends them before the closing brace, a brace on a commented-out line closing nothing. 14.20 states the same rule for every expression container's content (a container reaching such a brace runs on to a later brace at which its content derives, or leaves the file unparseable at end of file) and applies it to the empty-expression exception.
- I1: 2.4 now states that a form the file's grammar does not derive is a parse failure (14.20), never a dynamic reference: a non-null assertion, a type assertion, or other TypeScript-only syntax is condition 8 in a TypeScript source and unparseable in a spec source.
- O1: 4.6 cites 14.20 for the TypeScript release it fixes, not for the declaration-file rule.

Rejected:
- C2: wrong on the facts. Under MDX 3 an unterminated string at an early `}` swallows the brace exactly as an unterminated comment does, and a `{` inside a string opens no nesting level; `d={"a}b"}`, `d={"a{b"}`, `d={BASE["a{b"]}`, `d={BASE["a}b"]}`, and `{text("a}b")}` in flow and text position all parse (checked against the installed remark-mdx 3.1.1 / micromark-extension-mdxjs 3.0.0 as a black box). Braces in a segment are spelled verbatim in every form, so 6.4's guarantee holds and 1.4 stays as it is.
- O2: not a SPEC.md defect, and IMPLEMENTATION.md is outside this mission's permitted edits. Noted for that document's next refinement: its claim that remark-mdx's grammar defines well-formed MDX (SPEC 14.20) no longer holds where the toolchain enforces ECMAScript early errors that 14.20 excludes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…mment count made exact; run-on failure located by the offset rule

Applied: C1 (1.4, 2.7, 14.20: inside braces and ESM blocks, whitespace and
line terminators are ECMAScript 2024's, the one exception to 1.4 and 3; the
whitespace-and-comments count is stated as MDX 3 judges it: block comments
deleted first, then line comments through the first U+000A/U+000D, U+2028 and
U+2029 notwithstanding, counting only when one ends them before the brace,
and a whole content so judged must also lex to no token. Established by
running the installed remark-mdx 3.1.1 as a black box, which contradicts the
review's proposed rule for `{// c}` with U+2028 before its brace: MDX 3 runs
on there rather than admitting a comment, while `{// c}` plus a line holding
`}` is one empty expression and the U+2028 variant of that is unparseable),
I1 (14.20: the run-on gloss no longer asserts end of file; the offset rule of
14 locates the failure, since a text-position container cannot cross a blank
line while a flow-position one can), O1 (2.3: an embedding defined by its one
expression, whitespace and comments beside it notwithstanding; 2.7 points to
2.3), O2 (14.20: spread attribute braces hold `...` plus exactly one
expression beside whitespace and comments), O3 (2.4: "index or access form
applied to the chain"), O4 (1.7: a named unit's range excludes an `export` or
`export default` prefix save where the export declaration is the construct),
O5 (4.6: the file-name rule cited as TypeScript's, no release named).
Rejected: none. O6 is cascade awareness for Phase 6; no SPEC change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants