Skip to content

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

Open
lzrscg wants to merge 174 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 174 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

claude added 30 commits July 31, 2026 19:20
… seed

Triage: improvement (new machine-consumable surfaces require SPEC.md
changes). Developer confirmed CLI-only connection, UI-owned text
editing, and saved-files-only analysis; audit candidates folded in on
their merits (parse-local availability, tag sub-ranges, multi-file
document view, comment ranges, invocation-anchored root, direct
position query). SEED.md consumed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…odel, exit mapping, refresh, inventory provenance, preview edits, interface versioning

Applied: I1 (identity/interpreted-data model for parseable-but-invalid files;
invalid imports listed with unavailable targets), I2 (unavailable-data list
corrected — occurrence targets never unavailable, source identities and import
targets can be; parse-local claim scoped to positions/spellings), I3 (exit
mapping stated: findings or unavailable data in the answer -> 1, clean complete
answer -> 0, usage/config errors keep 2; answer always emitted), I4 (new query
surfaces join read-time refresh on valid workspaces, modify nothing on
imperfect ones; inventory never refreshes or writes), I5 (inventory
availability restated as parse-independence; content provenance split into
invocation/config/discovery, recorded generation state, filesystem), I6
(preview edit classes enumerated: occurrence rewrites, id-attribute rewrites,
import specifier/addition/removal edits, section-move deletion/insertion/
self-closing rewrite, file relocation; derived-file removals added), I7
(machine-interface version value stated in SPEC.md, surface reports exactly
it — per-build observable; contract scope defined), O1 (per-unit ranges for
multi-unit declarations), O2 (identical-range tiebreak removed as unreachable),
O3 (byte-classification claim scoped; position-resolution totality and EOF/
beyond-EOF rules), O4 (policy rules reported at coverage-profile depth), O5
(cross-drive anchoring rule).

Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…t-2 JSON channel, expansion definedness, enumeration domain, identification preconditions

Applied: I1, I2, I3, I4, I5, O1, O2, O3, O4, O5. Rejected: none.

- I1: change 8 gains a workspace-independence bullet — consults no workspace or
  configuration, cannot fail for configuration reasons.
- I2: resolved via the channel arm (bullet 2 of change 6 already committed the IP
  to machine-consumable configuration errors): exit-2 errors emit a JSON error
  document as the entire standard output, amending the empty-stdout rule.
- I3: occurrence spans stated per kind; MDX embedding spans the full braced
  container, which change 3's byte-classification claim now cites.
- I4: dropped "hashes" from the unavailable-data list (no surface this proposal
  adds reports hashes; naming one would add an unrequested capability) and added
  the exact expansion-definedness rule (every transitively reached embedding
  records an occurrence, no cycle re-entered).
- I5: finding reporting defined over a consulted domain; a target-only
  enumeration's domain is the whole discovered set, so masked files always
  surface as findings with exit 1.
- O1: joint-location claim scoped to parseable files.
- O2: created-target-file previews report the creation as its own class with the
  insertion point at file start.
- O3: inventory's review-session listing is name-based and content-blind,
  corrupt sessions included.
- O4: structured-diagnostics contract extended to rename/move refusal reasons.
- O5: product version phrased as informational; testable contract carried by the
  machine-interface version.
- Compatibility note records the two convention amendments (exit-2 JSON form,
  change-8 precedence exception).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Applied all items; none rejected.

- C1: widened change 4's view domain — when expanded text is requested,
  the domain gains every file the expansions transitively consult, so the
  finding blocking an expansion is always in-domain and the never-silent
  guarantee holds.
- I1: change 1's target-node filter is now syntactic acceptance — a
  well-formed targetable identity selects (possibly zero) occurrences by
  resolved target; nonexistent, masked, identity-undefined, and unknown
  targets yield an empty answer with domain findings; only malformed
  spellings are usage errors; delta flagged in compatibility notes.
- O1: default-export unit ranges (named construct vs. export declaration).
- O2: graph-data area reported unconditionally as derived, xspec-owned.
- O3: session listing selects directory entries by name whatever occupies
  the path.
- O4: preview derived-file consequences defined as the identity-relevant
  delta, not the full regeneration set.
- O5: preview/real-operation equivalence scoped to workspace state, not
  scheduling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ion, corrupt-record outcome, file-filter semantics, availability scoping

Applied all items; rejected none.

- I1: graph-data area reported as owned with the durable paths carved out
  and taking precedence — never a blanket derived, deletable unit.
- I2: recorded state present but unreadable (corrupt graph data) gets a
  defined outcome: recorded entries explicitly unavailable, corruption a
  reported finding, exit 1, full inventory still emitted.
- I3: change 1 file filter pinned to the existing file-glob convention
  (set restriction, empty admission = empty exit-0 answer); the
  malformed-identity usage-error sentence scoped to the target filter.
- I4: change 4 closing sentence scoped to changes 1 and 3, naming where
  changes 5/7/8 state their own availability.
- O1: explicit TypeScript spans — text(...) occurrence = whole call
  expression; marker occurrence = bare chain, no statement terminator.
- O2: "the two" replaced — profiles and rules alike fully expanded.
- O3: multi-file view order pinned to byte order of workspace-relative path.
- O4: journal occupancy datum added (absence = empty journal).
- O5: origin-deletion class's single range covers the adjunct dropped-line
  bytes, contiguous by construction; no separate class.

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

Iteration 5 of patch refinement for 0001-external-ui-apis (IP). Applied:

- C1: replaced the graph-data area's contradictory per-occupant ownership
  composition with one rule stated once in the area entry: the area is a
  write reservation; reported durable and recorded derived paths are
  classified as reported; every other path under the area is unattributed —
  never listed, never claimed, never presented as rebuild-recoverable.
  The availability paragraph's review-session sentence now defers to that
  rule instead of asserting opposite ownership.
- I1: the empty-finding-free-answer guarantee of change 1 is now scoped to
  the consulted domain, absolute exactly when no file filter narrows it.
- O1: change 4's resolution-failure exemplars now include the
  unique-bearer-with-undefined-identity case change 1 cites.
- O2: change 6 defines the concerned path for missing configuration with
  no --config: the search-origin directory (invocation working directory),
  invocation input like change 5's anchoring; compatibility note updated
  so the invocation-anchored exception covers both changes.
- O3: change 5's configuration view names its shape: profiles and rules
  carried with complete definitions; group references stay names resolved
  against the view's own group list, never glob expansions.
- O4: split the change-1 file-filter sentence and the change-5
  provenance/availability sentences into separable statements, all
  clauses preserved.

Rejected: none.

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

Applied I1: change 2's second bullet now names the exact outputs that gain
code-location ranges — occurrence records present their source graph node as
one datum (identity plus that node's own construct range; changes 1 and 4
adjusted to match), review payloads generalize the present-node range rule
from requirement nodes to graph nodes, and query edge endpoints explicitly
remain bare identities.

Applied I2: the graph-data-area bullet no longer claims an unattributed
path is irrecoverable (false for the graph-data subcase per SPEC 12.1/13.3);
the undeletable rule now rests on the consumer's inability to tell
regenerable graph data from foreign content.

Applied O1: view's glob form states the empty-match outcome (empty set,
finding-free, exit 0), mirroring change 1.
Applied O2: anchoring bullet's "never as absolute paths" now carries the
different-Windows-drives carve-out stated at the change's end.
Applied O3: a root's tags/coverage attribute are defined structural absence,
not change 4 unavailability — no finding, no exit-1 consequence.
Applied O4: preview edits explicitly carry no replacement text; the preview
is a safety report, not an edit script whose external application would
bypass the journaled mapping.
Applied O5: the exit-2 JSON error document's trigger is delimited — --json
among the arguments, or a JSON-only surface with no flag needed; the
compatibility note now points at that delimitation.

Rejected: none.

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

Applied: I1, I2, O1, O2, O3, O4.

- I1: change 6 states the multi-construct location rule — one finding per
  condition instance carrying a location for every participating construct
  (duplicate-ID bearers, colliding import declarations, a cycle's full path),
  context entities as identity data; extended to refusal reasons (cycle a
  refused move would create).
- I2: change 3 assigns the wrong-kind usage error to a discovered code source
  named directly and fixes the view glob's restriction universe as the
  discovered spec sources.
- O1: change 2 scopes the absent-node clause to the range datum alone,
  leaving historical-text payload rules untouched.
- O2: change 1 states that file and target filters combine conjunctively in
  one invocation.
- O3: split the heaviest sentences in change 4's consulted-domain bullet and
  change 5's graph-data-area bullet.
- O4: change 6 states the missing-configuration concerned path's reported
  form (change 5's anchoring; degenerate self-reference).

Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…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
…imitation (iter 9)

Applied:
- I1: change 3's attribute parenthetical now reads "attribute inclusion is by
  form" — it governs which attributes appear in the view (every spelled one,
  validity notwithstanding), not per-attribute ranges. Git history confirms the
  intent: the parenthetical entered in iteration 8 as an inclusion statement
  ("spread attributes appear among the view's raw attribute spellings by form");
  "position" was a wording slip. Attributes are carried as raw spellings; ranges
  are granted explicitly where intended (tag decomposition, change 6 findings,
  change 7 id-rewrite edits).
- O1: the stable-code delimitation now covers review-operation refusals
  explicitly — findings under the existing exit-code partition, neither numbered
  conditions nor rename/move refusal reasons, uncoded because review flows lie
  outside this proposal's UI scope (relied on unchanged).
- O2: change 2's disambiguated-unit sentence now says "each carry the range of
  their own construct", ending the collision with change 1's coined "reference
  occurrence" (SPEC.md 4.6 uses "occurrence" for the Nth same-named unit).

Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Applied: I1, O1, O2, O3.
- I1: change 4 now defines when a section spells an identity (id prop
  exactly once, quoted attribute form); missing and invalid-form id
  props (repeated — spellings agreeing or not — braced or valueless
  values) spell no identity: own identity undefined, descendants'
  chain broken, and no participation in uniqueness — an invalid-form
  claimant never poisons a well-formed bearer. Resolution grounded in
  the document's own principles (no fabrication from invalid syntax,
  tags/coverage analog, mid-edit containment).
- O1: review-refusal aside in change 6 scoped past change 2's range
  generalization (removes the one self-contradiction reading).
- O2: change 5's corrupt-recorded-state finding explicitly joins the
  numbered validation-error conditions with a stable code.
- O3: an occurrence-less MDX-embedding spelling's finding range pinned
  to the full braced container, keeping change 3's byte classification
  exact on imperfect files.
Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…p exclusivity claim (iter 11)

Applied: C1 — replaced change 5's false "alone among readers" claim with an
accurate shared-reader statement (inventory + change 7's delta; existing check
noted as covered by its staleness condition) and gave change 7's delta a defined
outcome on recorded state that exists but cannot be read: the delta, both
directions one datum, reported explicitly unavailable, same numbered condition
and stable code as change 5's, exit 1, rest of the preview report emitted in
full; stated as the succeed/refuse equivalence's one success-side exception
(the real operation is not refused — corruption fails no build validation and
finishing regeneration replaces it). Aligned change 4's summary pointer and
change 6's refusal appositive with the new outcome.
Applied: O1 — absent tags/coverage props define the existing defaults (no tags;
coverage-required), closing the misreading that presence is required.
Applied: O2 — the test seam tied to acquiring workspace exclusivity never
engages on a preview, stated at behavior level (no flag prescription).
Applied: O3 — reported edit ranges may nest: section-move re-identification
rewrites locate inside the origin-deletion range in pre-operation coordinates.
Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Iteration 12 review: no Critical or Important items — refinement converged.

Applied O2: change 6 now states the invocation-anchored reporting form for
every configuration-error concerned path (the found or --config-named
configuration file, and the missing-configuration working-directory case),
instead of leaving the non-missing cases to the compatibility note's plural.

Applied O3: change 3's import entry now states the binding-name datum for a
bindingless declaration is structural absence — reported as absent, never as
unavailable — per the document's root tags/coverage taxonomy and change 4's
closed unavailable-data list.

Rejected O1: naming whether the unreadable-record finding becomes a new
numbered condition or folds into the existing staleness condition is
validation-section organization, which the patch's methodology preamble
delegates to spec refinement; the information contract (reported finding,
stable code, exit 1, full answer emitted, identical reporter set) is the same
on both branches, as the review itself notes.

Stage: Proposed -> Accepted.

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

Integrates all eight accepted surfaces as timeless end-state requirements
(review items C1-C9), with concrete invocations (I1):

- 5.7 reference occurrences (concept, spans per kind, no-occurrence rule,
  total order); 11.3 `xspec occurrences [--file <glob>] [--to <node>]`
  with syntactic --to acceptance and malformed-only usage errors.
- 1.7 rewritten: code-location ranges defined; presented in exactly two
  outputs (occurrence records, review payloads); edge endpoints stay bare
  identities; 10.7 payload generalized to present graph nodes.
- 11.4 `xspec view` (tree, tag decompositions, raw attributes, imports,
  occurrences, comments, byte-classification guarantee, domain forms) and
  11.5 `xspec at <file> <offset>` position resolution.
- 11.2 availability contract: parse-local structure, spelled/defined
  identity, tags/coverage and expanded-text definedness, explicit
  unavailability, consulted domains, exit mapping, stale-data rule;
  13.3 scoped so occurrences/view/at answer mid-edit.
- 11.6 `xspec inventory` (anchoring, configuration view, sources, derived
  map with provenances, graph-data area write reservation and
  unattributed-path rule, durable files, deterministic ordering).
- 14: stable codes for all 23 conditions, location cardinality, concerned
  paths, refusal-reason codes; new condition 23 (unreadable recorded
  state); 12.0 JSON error-document delivery whenever JSON output is in
  effect.
- 6.6 previews (`--preview` on rename/move): full plan report, edit
  classes with pinned ranges, derived delta with condition-23 outcome,
  refusal equivalence with 13.5 scheduling exception; --test-hold with
  --preview pinned as a usage error (I2).
- 12.6 `xspec version`: machine-interface version 1, workspace-independent,
  outside configuration-error precedence (14.14 scoped).
- 12.0/12.5/13.3/13.5 conventions absorbed the new outcomes (C9).

I3: no IP/delta framing survives; internal cross-references only.
I4 modularity assessment: no module split - every added portion is
consumer-facing interface/contract that PROCESS.md requires in SPEC.md
itself, and it is densely interlocked with 1.7/12.0/13.3/14; no clean
seam exists in the pre-existing content either. Single file retained
under the SHOULD.
O1 placement suggestion followed.
Rejected items: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…esh, import-edit, and view gaps (iter 2)

Applied:
- C1: node identities exist only over valid source paths — every node of a
  14.19-invalid file (roots, sections, code units) has an undefined identity
  under 11.2; such files keep parse-local structure and their condition-19
  finding accompanies every answer whose domain includes them; 1.5's
  #-unambiguity re-grounded on this rule; occurrences --to gains the
  invalid-path non-resolve case; 12.0 gains a marked byte-form
  representation rule for non-UTF-8 workspace-relative paths in outputs.
- I1: read-time refresh leaves an unreadable record (14.23) unread,
  unrepaired, unreplaced; refreshing reads consult no record and report no
  finding for it; the state persists, reported by 11.6/6.6/14.10, until
  build or rename/move regeneration replaces the record (13.3, 14.23).
- I2: import-removal extent pinned (declaration plus line-drop adjunct, as
  in 3); import addition inserted as a line of its own at a
  grammar-permitting, deterministic implementation-latitude offset equal to
  the previewed offset (6.5, 6.6).
- I3: view --text consulted domain defined: exactly the files of resolved
  targets reachable through occurrence-recording embeddings; a
  non-resolving spelling is the expansion's boundary; a masked file is
  never consulted by expansion, its finding surfacing only when requested.
- I4: argument checks of 11.3-11.5 precede answering — usage errors exit 2
  whatever findings the workspace or named files carry (11.2).
- I5: raw attribute spelling defined per attribute, in tag order: name as
  spelled (absent for spread), source range, and source text (name through
  value; a spread attribute's entire braced construct) (11.4).
- I6: verified against pre-IP baseline (a724662): query was already
  JSON-only ("a single JSON document is its only output form"), so section
  11's JSON-only statement alters nothing pre-existing — no change needed.
- O2: 11.4 code-source operand rephrased "wrong-kind operand, a usage
  error" to avoid conflation with stable code invalid-argument.
- O3: review export synopsis aligned to [--json] per its JSON-only text.
- O4: confirmed intended, no edit — multiple view <file> operands are
  deliberate refinement latitude (IP: exact surface shapes settled during
  spec refinement), consistent with the mandated per-file multi-view
  response in one document; removing the form would lose harmless
  capability an editor plausibly wants (view several dirty files at once).

Rejected:
- O1 (modularization): declined. The extraction candidates (10.4-10.6,
  7.4-7.5, 8) are load-bearing contract surface: strategy derivation
  determines export/next payloads, item identity, and invalidation, and
  coverage/policy evaluation is itself the command contract; PROCESS
  requires the full interface/contract in SPEC.md and forbids referencing
  module internals, so extraction would duplicate contracts rather than
  shrink the document. The SHOULD yields to those MUSTs here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ncerns and file-operand parsing (iter 3)

Applied: C1 (new 12.7 — value forms for ranges, paths and the marked
byte form, the value/absent/unavailable three-state, finding and error
documents, and document forms for occurrences/view/at/inventory/
previews/version, with pinned orderings; 11.6 derived-map bullet aligned
with the record-supplied datum; pointers from 6.6, 11, 12.0, 12.6, 14).
I1 (condition 22 concerns the offending symlink component, one finding
per component; condition 23 concerns the graph-data area; record
conditions added to 14's concerned-path rule). I2 (12.0: # splits only
identity-form arguments, including <file>#<id> operands; bare <file>
operands and --file globs are whole paths with no delimiter role for #).
O1 (10.1 "directory entry" replaces "file"). O2 (5.7 occurrence
existence anchored to target resolution). O3 (13.4 orphan rule extended
to a missing or unreadable record). O4 (12.0 intra-exit-2 precedence:
syntax-only errors before configuration loading, configuration errors
before workspace-consulting argument checks). O5 (finding order and
preview-edit order pinned in 12.7).

Partially applied: O6 — removed the one redundant clause in 11.6's
unattributed-path rule ("the one whose deletion is undone by nothing");
the remaining statements carry distinct load (the foreign case's
definition, the inventory's stance, the consumer rule), so further
compression risks dropping content.

Rejected: O7 — no modularization: nearly all of sections 8-10 is
consumer-facing interface contract that PROCESS.md requires to remain in
SPEC.md itself, which the review itself concedes makes single-file
defensible; extracting mechanism prose mid-IP would churn cross-
references for no requirement.

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

Applied: C1 (refused previews leave the findings-alone list; they keep the
four-member preview form with null mapping/files/delta), C2 (one gate phrase —
"the validations of \`xspec build\`" — in 6.4, 11.2, 12.0, 13.3; the refusal
branch of the all-or-nothing reads covers journal errors (14.13) and refused
writes (14.22); refresh runs only where build would succeed and cannot fail;
conditions 13/22 accompany no 11.3-11.5 answer — findings are the domain
files' alone, finding-free answers stay exit 0), I1 (11 intro corrected: only
occurrences/view/at/inventory have 12.7 document forms; query — JSON-only
already before the IP — carries its defining section's information), I2
(finding order made total: concerned path with null-first, identities,
message; identical findings collapse to one), I3 (list members are [] when
empty; null only where a form states the datum absent), O1 (companion
attribution via 13.1 naming stated in 11.6), O2 (duplicate
unresolved-spelling clauses trimmed from 5.7 and 11.3), O4 (offset spelling
pinned to ASCII decimal digits), O5 (recorded paths excluded from the
staleness comparison), O6 (marked-byte-form list extended with inventory
derived paths and view import targets).

Rejected: O3 — no modules extracted: the candidates (§10 review mechanism,
§14 condition catalog) are consumer-facing interface/contract, which
PROCESS.md requires defined in SPEC.md itself, so no loosely coupled
non-contract component exists to extract at the current size.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…ing spelling, unreadable-record staleness (iter 5)

Applied: C1 (derived-file map and emit destinations structurally absent for
.mdx-less discovered spec sources — 13.1, 13.2 via 7.3, 11.6, 12.7), C2
(view import name = default binding only, absent otherwise — 11.4, 12.7),
I1 (canonical anchoring spelling incl. "." self-reference and separator —
11.6, 14), I2 (check reports an unreadable record as a condition-10
finding concerning the graph-data area — 14.10, 12.2), O1 (5.7 definition
by resolution), O2 (prefix-first finding order — 12.7), O3 (occurrences in
13.3 content list), O4 (.xspec spelling pinned — 11.6), O5 (exit-2
document holds one finding — 12.7), O6 (positional tree parents to
innermost enclosing section — 11.4).

Rejected: none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…comparators, JSON contract details

Iteration 6 of applying IP 0001. Applied: C1, I1, O1, O2, O3, O4, O5, O6.

- C1: 6.6/6.5 — a created target file's entry reports its creation as its
  only edit, subsuming the insertion and the import additions composed into
  the file's initial content (per the IP's "one reported location without
  pre-operation coordinates"); the moved text's own rewrites stay reported
  in the origin file; 6.5's preview-offset promise scoped to files existing
  before the operation.
- I1: 12.7 — between-findings `locations` ordering given its element
  comparator (file path bytes, range start, range end); identities' element
  rule spelled out alongside.
- O1: 14/12.7 — a stable code's value pinned as the listed token string;
  numerals are ordinals for ordering, no part of the value.
- O2: 12.7 — preview edit tiebreak pinned to class-name bytes.
- O3: 11.2 — membership rule for a domain file's findings (a location in
  the file, or the file as concerned path); joint multi-file findings
  accompany whole when any participant is in the domain.
- O4: 6.6 — a refused preview consults no record; no condition-23 finding
  accompanies a refusal.
- O5: 11.5 — a non-UTF-8-path source is nameable by no argument value;
  its positions are reachable only through the view by glob.
- O6: 12.7 — exit-2 error document moved under Document forms, lead
  exception amended.

Rejected: O7 — modularization is a PROCESS SHOULD, not violated at the
current size; the reviewer's own framing conditions extraction on future
growth, and restructuring at convergence risks breakage with no
requirement gain.

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

Applied:
- I1: condition 12 carries no in-source locations and no concerned path
  (no file's finding per 11.2, so it accompanies no 11.3-11.5 answer,
  closing 7.5's check-only routing structurally); identities pinned as
  rule name, edge source, kind token, target; 14's cardinality paragraph
  and 12.7's identities description widened to match.
- I2: the invalid-workspace refusal precedes the operation-specific
  validation, which is defined and evaluated only over a workspace
  passing build's validations - the refusal reports the workspace's
  findings alone, never mixed with refusal reasons (6.4, 14).
- O2: 12.2 restated build validations under the build-validations clause
  so the "additionally" list holds only check-only verifications.
- O3: preview `files` entries keyed by current pre-operation path, the
  relocated file's entry included; created target file by its new path.
- O4: 13.3's recorded derived-file paths scoped to generated modules,
  companions, and emitted Markdown - graph data records no paths, its
  layout staying unenumerated.

Rejected:
- O1 (modularization): deferred deliberately - candidate components are
  bound to the core by dense numbered cross-references (5.4-5.6, 12.0,
  12.7, 14) whose contracts could not move to modules without the
  restatement module rules forbid; the SHOULD is weighed, not dropped.

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

Applied:
- I1: rename/move old-ID existence judged over spelled identities (11.2), parse-local —
  undefined-identity bearers still establish existence, no-identity spellings establish
  none, unparseable origin stays masked (6.4, 6.5).
- I2: refused-invalid-id scoped to intrinsic ID form (dot-path of 1.4-valid segments);
  positional conformance (1.3) is refused-structural-parent's alone, evaluated only over
  intrinsically valid IDs — no identity reports under both (14).
- I3: refused-destination-exists triggers on any occupant of the file-form destination
  path, whatever kind of filesystem object, symbolic links included (6.5, 14).
- O2: a successful non-preview rename/move reports the applied mapping — the preview's
  mapping information (6.4, 6.5).
- O3: finding-form identities content contractual exactly where 14 states it for the
  condition or reason, otherwise informational — deterministic, composition unpinned (12.7).

Not applied:
- O1 (modularization): standing deferral upheld. Extracting Review (10) or the
  query/JSON complex (11, 12.7) requires full interface restatement in SPEC.md per
  PROCESS module rules; the restructuring risk mid-refinement outweighs the SHOULD at
  current size. The deferral stays a recorded decision, not an omission.

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

Applied:
- C1: section-form move target path occupied by anything other than a
  discovered spec source is refused under refused-destination-exists
  (6.5 body and refusal list, 14).
- C2: rename/move origin operands pinned to discovered spec sources; a
  code-source origin is a wrong-kind usage error per 11.4's pattern
  (6.4, 6.5, 12.0 precedence bullet and exit partition).
- I1: rename's collision check pinned post-mapping - vacated IDs are no
  collision, produced IDs checked too, identity-unchanged reports
  refused-identity-unchanged alone (6.4, 6.5, 14 refused-id-collision).
- O2: 11.2 unavailability parenthetical no longer implies a structural
  view exists for code sources; occurrence's own range (11.3) named.
- O3: unreadable-record outcome consolidated into 14.23 as its one
  normative home; 6.6 and 11.6 defer to it.
- O4: explicit sentence in 14 that a refusal reports every applicable
  reason together, never only the first found.

Rejected:
- O1: modularization deferred again - the named candidates (Review,
  Coverage, validation catalogue) are consumer-facing contract that
  PROCESS.md requires to stay in SPEC.md itself and forbids modules to
  restate; extracting them mid-IP refinement would churn every section
  reference while yielding little movable non-contract content.

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

Applied:
- C1: 14.10 restructured into four forms — per-file staleness (generated
  modules/companions per 13.1, emitted Markdown per 13.2) and orphaned
  recorded files name the file; graph-data staleness (missing or
  mismatching under 13.3's comparison, recorded paths excluded) and the
  unreadable record are each one finding whose concerned path is the
  graph-data area, no path inside named, mirroring 14.23's shape. 12.2
  now enumerates the verifications, graph data included, removing the
  'generated files' ambiguity. Follows 13.3's existing commitment that
  check reports graph-data staleness while keeping 11.6's unattributed-
  path regime intact.
- O1: 6.5 classifies move operands by spelling — a mixed-form invocation
  matches neither synopsis and is a usage error; the file form's
  inability to spell '#'-containing paths noted as harmless (14.19).
- O2: 6.4 drops the '(12.7)' citation on the successful-rename report;
  12.7 pins no form for it, so the report stays information-only per
  12.0 — consistent with O4's recorded-gap stance.
- O3: 7 qualifies 'Every command locates the configuration' to except
  version, matching 12.6 and 14.14.

Rejected:
- O5 (modularization): SHOULD, not MUST. The named components are not
  loosely coupled — 14 is cross-referenced from nearly every section,
  10 and 11 interlock with 5.4-5.7, 12.0, 12.7, 13.3-13.5 — so
  extraction would duplicate contract text into SPEC.md or violate the
  no-reference-into-module rule; restructuring at convergence adds
  contradiction risk with no behavioral content. Consistent with prior
  rounds' deferrals.

No-op:
- O4: reviewer records the unpinned query/impact/coverage/review member
  names as a deliberate, IP-faithful gap for a future proposal; no
  change requested.

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

Applied:
- C1: 14.10/12.2 — the per-file content comparison judges the path's
  occupant itself, never traversing a symbolic link (13.4): it matches
  only a plain file holding exactly the generated content, so a symlink
  (whatever its target holds), a directory, or any other non-plain-file
  occupant is stale per se. Two conforming implementations can no longer
  diverge on a symlinked byte-identical occupant.
- I1: 14.10 — per-file form now reads "missing or does not match",
  covering check on a deleted generated module/companion/Markdown file,
  parallel to the unit form, 13.3, and 13.4's deleted-file promise;
  12.2 aligned ("present as plain files content-identical").
- O2: 11.6 — stated that the condition-23 finding is the only finding an
  inventory answer ever carries; findings a listed file or path may bear
  (14.19, 14.13, 14.21) report where their conditions assign them.
- O3: 12.7 — concerned-path ordering key pinned to byte-wise comparison
  across presentation forms: marked byte-form and plain-string paths
  sort in one byte order.

Rejected:
- O1: modularization deferred again — standing SHOULD acknowledged, but
  the consumer-facing contract must stay in SPEC.md (PROCESS), limiting
  the extractable interior, and restructuring mid-IP-refinement is not
  clearly right this round.

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

Applied: C1, I1, O2, O3
- C1: one precedence statement for the 13.3-gated reads (12.0) — their
  argument checks precede the invalid-workspace gate, judged per 6.4's
  parse-local pattern with unparseable-named-file masking, so unknown
  names exit 2 whatever the workspace's findings; the gate precedes
  session reading, so a corrupt session (14.21) reports only on a
  passing workspace and item-ID checks are masked by the corruption
  (13.3, 10.1, 10.7, 14.21 aligned).
- I1: a non-directory-occupied (symbolic link included) workspace-relative
  directory component of a move destination or of a derived path the
  destination would generate is one refusal cause under
  refused-invalid-destination (6.5, 14), disclaimed in 14.22 so refusal
  reports stay refusal-reasons-only and the finishing-regeneration
  infallibility claim holds; writes create nonexistent intermediate
  directories (13.4).
- O2: 11.2 closing label no longer overstates — "Never stale; writing
  nothing on a failing workspace."
- O3: duplicate profile/rule names named explicitly in 14.14.

Rejected: O1 — modularization stays deferred, consistent with prior
rounds; the Reviewer records it for completeness and states nothing
reopens that decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
…y findings, multi-# split (iter 13)

Applied:
- C1: 13.4/14.22 generalized from symlink-only to any non-directory occupant
  of a workspace-relative write-path directory component; condition 22 retitled
  obstructed-write-path, own-path and 6.5 destination-side exclusivities kept.
  Closes the plain-file-at-.xspec/outDir gap; 12.1's taxonomy, 13.3's gate
  enumeration, and 6.5's cannot-fail regeneration argument now cover the state.
- C2: condition 1 pinned to id-attribute absence; repeated/invalid-form id is
  condition 17 alone; condition 2's mask extended to every spells-no-identity
  parent (11.2), so finding sets like <S id="a" id="a"> + child are derivable.
- I1: 12.0 pins at most one '#' in <node>/<graph-node>/<file>#<id> spellings
  (mirroring 11.3); more is a malformed value, a usage error — split never
  ambiguous.
- O1: 5.3 cycle detection attributed to validation (build and check alike).
- O2: 7.5 pins captures as exactly $1-$9; every other $ is a literal byte.
- O3: 12.0 wrong-kind illustration now cites the 11.1/12.4 node-kind checks.
- O4: 6.6 delta rationale marked rationale-not-filter; degenerates toward the
  full set on an empty or lagging record.

Rejected/deferred:
- O5 (modularization): re-deferred — SHOULD-level; near-total contract
  locality keeps the single file; residual delegated to the downstream
  problems-file net per the standing closure ruling.

Closing iteration per Liaison valve ruling: REVIEW.md deleted; patch 0001
Stage: Accepted -> Applied.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
claude added 30 commits August 29, 2026 21:00
…table code tokens

Replace the condition-number finding model with SPEC 12.7's observable form
{"code", "message", "locations", "path", "identities"}: the 23 SPEC 14
condition tokens plus the nine refusal-reason tokens (with per-code ordinal
and exit class), located conditions carrying byte-range locations (condition
20's line/column converted to byte ranges and dropped from the model),
concerned-path conditions (10, 13, 14, 19, 21, 22) carrying `path`,
condition 12's contractual identities [rule, source, kind, target],
condition 11's foreign module as identity data, and cycle paths as identity
context (cycle-as-locations stays task A3). Every construction site across
core and workspace is ported; the JSON serializer emits exactly the five
members and the human renderer presents the same information. The 12.7
findings ordering and duplicate collapse land as one choke point
(core/findings.ts orderFindings) applied by every emitter; FIX_PLAN's A2 is
rewritten to its remainder (marked byte-form path values).

Suite: 98 failed / 539 passed vs the 142/495 baseline - 44 fixed, no new
failures; every residual is owned by a later plan task (A2-A5, B*, C*).
Self-tests and certification: 330/330.

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

FIX_PLAN A2. New src/core/path-text.ts is the one internal path
representation and shared path-value renderer (SPEC 12.0, 12.7, 14.19):
PathText = string | PathBytes, constructed from raw bytes only through
pathTextOf so a valid-UTF-8 path can never take the marked form;
pathTextJson renders the JSON value form ({"bytes": lowercase hex} for a
path with no plain string form), renderPathText the deterministic human
spelling <bytes HEX>, comparePathTexts one byte order over both forms.

Finding locations[].file and path are PathText; compareFindings and
compareLocations compare paths by exact bytes whatever the presentation
form; discovery's 14.19/14.14 findings carry the offending path's exact
bytes instead of the lossy U+FFFD decode; the human report, JSON report,
configuration-error diagnostic, and baseline diagnostic all render through
the shared helpers.

Verified: T12.7-2's build/query arms now emit
{"bytes":"73706563732f41ff2e6d6478"} sorted before the plain "specs/ha#…"
paths (remaining deltas in section-12.7 are A3 cardinality / A4 error
document / Stage B surfaces); section-14 (5 failed / 3 passed) and
section-11.2 / 12.1-12.2 / 13.3 (12 failed / 4 passed) byte-identical to
the pre-change baseline — no regressions; P-7 and sections 1.1-1.2 and 15
pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
SPEC 14 location cardinality (FIX_PLAN A3):

- Duplicate IDs (14.3): one finding per duplicated identity locating
  every bearer, the first included, instead of one finding per repeated
  occurrence (mdx.ts validateStructure).
- Import-binding collisions (14.15): one finding per collided identifier
  locating every colliding declaration, in xspec sources
  (spec-references.ts) and TypeScript files (code-analysis.ts) alike;
  the collision needs two distinct declarations.
- Cycles (14.9): a dependency cycle locates its full path through every
  reference spelling recording a participating dependency edge (graph.ts
  records an edge-to-spellings map beside edge assembly; d = the entry's
  own expression, MDX embedding = the full braced container, 5.7); a
  spec import cycle locates every participating import declaration. The
  cycle path no longer travels as identities - it stays in the message.
- A no-occurrence spelling of the MDX embedding form (14.6/14.8) is
  located by the full braced container, opening through closing brace -
  the span its occurrence would occupy (5.7).

Also normalizes the raw NUL separator bytes in graph.ts edge keys to the
escaped spelling (same value; keeps the file text for tooling).

Verified: T14-8 passes; T7.5-2..6, T1.3-*, T2.1-*, T2.2-2.3, T2.4-*,
T4-*, T5.1-5.3, T5.4-5.6, T3, T15, P1-P6 all pass. Remaining failures in
sections 5.7/6.3/7.4-7.5/12-14 predate this change and belong to later
FIX_PLAN tasks (A4 error document, Stage B surfaces, C-stage fixes).

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

SPEC 12.0/12.7/14: with JSON output in effect — --json among the arguments
(even when the arguments are themselves the error) or a JSON-only surface
(query, review export; CommandSpec.jsonOnly carries the marking for the
Stage B registrations) — an exit-2 usage or configuration error emits
{"error": <finding form>} as its entire stdout. Plain usage errors carry
code/path null; configuration errors carry code configuration-error and
the concerned path in the 11.6 anchoring form relative to the invocation
cwd (the found or --config-named file, or "." for a failed upward search),
one merged finding however many defects. The anchoring spelling is the
shared helper src/workspace/anchor.ts (inventory reuses it in B7); stderr
diagnostics and exit codes are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
A refused review operation (split on a wrong-kind or childless item,
resolve on a blocked item, create with an existing or case-colliding
name) now reports the findings-only document {"findings": [...]} with
one finding — code null (SPEC 14: review-operation refusals carry no
stable code), locations empty, path null, identities the session name
(+ item id / colliding name, informational) — exit 1, nothing modified,
human form through the shared findings renderer (SPEC 10.7, 12.0, 12.7).

Plan: A5 removed (verified: section-10.2-10.3, 10.7-i all green; the
10.7-ii and 10.1 refusal arms green — remaining reds there are C6's
T10.7-7/12 and the newly-diagnosed T10.1-5); C2 extended with the
corrupt-session-behind-the-gate ordering (T10.1-5, observed 14.21
reported in the gate's place); new task B2a added for parse-local
validation inside invalid-path (14.19) sources (T12.7-1 arm E, observed
the located 14.1 dropped with the file).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
SPEC 12.6/12.7: `xspec version` is a JSON-only surface emitting the
{"product", "interface"} document — interface exactly the string "1",
product read from the package's own metadata, fixed per build. It loads
no configuration and consults no workspace: main dispatches it before
workspace location, so configuration-error precedence (14.14) never
reaches it and the answer is byte-identical in any working directory.
Usage errors keep exit 2 and emit the 12.7 error document.

Verified: T12.6-1/2 pass; T12.0-9 advances past its version row (now
red at the unimplemented occurrences surface, task B4). Removes task B1
from specs/tmp/FIX_PLAN.md.

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

FIX_PLAN B2a (SPEC 11.2, 14.19, 12.0/12.7, 14): a discovered file whose
path is invalid stays visible to analysis. Discovery carries such files as
classification.invalidSources; the pipeline parses them into
invalidPathSpecs/invalidPathCode (document.file/analysis.file the real
PathText, path a never-rendered lossy stand-in), reporting their
parse-local findings beside the 14.19 while defining no identity: no graph
nodes, no hashes, no recorded inputs, no derived-file interaction. Import
designation consults the whole discovered set through SpecSourceDomain
(string- and byte-space designators; WorkspaceContent.readInvalidSource
reads content by exact path bytes): a valid import of a 14.19 member is no
finding, targetFile carries every valid import's member as PathText, and
references rooted at such bindings report 14.5/14.6/14.7 at analysis.
References from invalid-path files resolve in buildWorkspaceGraph
(findings only; the local form never resolves), and spec import cycles run
over exact path bytes with invalid-path files participating.

Verified: T12.7-1 arm E's build --json leg passes (14.1 x1 located in the
non-UTF-8-named file, marked byte forms; 14.19 x2); the arm's
occurrences/view/inventory legs still need B2/B4/B5/B7. Full suite 63
failed / 574 passed, every failure in a pending B2-C7 task's scope; no
regression in sections 1-5, 7, or certification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
FIX_PLAN B3 (SPEC 1.7, 4.6): every code location now carries its source
range. CodeUnit.range (core/code-analysis.ts) is the construct binding
the unit's name: a variable declaration's own node (name through
initializer, never the multi-declaration statement); dotted-namespace
units share the chain's outermost declaration — the one construct
binding them all; a named default export takes the construct's own range
with the `export default ` prefix excluded (later modifiers like `async`
kept, per the construct), an anonymous one's `default` unit the whole
export declaration; `@N` units their own occurrence's construct.
CodeLocationNode.range (core/graph.ts) carries it into the graph — a
whole-file location spans 0..the file's byte length — and
StoredCodeLocation.range persists it (core/graph-data.ts, stored format
version 4; an old store reads as malformed, hence a mismatch, SPEC 13.3).
Nothing presents the range yet: occurrence records (B4) and review
payloads (C6) are the two presentation points (SPEC 1.7), so query
edges/reachable stay bare identities.

Verified: typecheck, build, format clean; every T1.7-2 fixture shape
(plus async-default, braced-nested-namespace, and parenthesized named
function expression exports) checked byte-exact against the built
analyzer and graph at the core level — T1.7-2 itself goes green with
B4/C6. Full suite 63 failed / 574 passed, the failing set member-for-
member identical to the pre-change baseline (CI run 124): no regression,
every failure in a pending B4-C7 task's scope.

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

Register `occurrences [--file <glob>] [--to <node>]` (SPEC 11.3, JSON-only)
emitting the 12.7 {"findings","occurrences"} document, with argument checks
preceding answering: an outside-root --file pattern and a malformed --to
spelling each exit 2 with the error document; --to acceptance is syntactic,
unknown or unresolving identities selecting nothing; the filters combine
conjunctively.

The shared SPEC 11.2 machinery lands in core/availability.ts (consulted
domain over the entire discovered set, invalid-path members by exact bytes;
accompanying-findings selection; node-spelling well-formedness; occurrence
selection joining each source datum's range through its graph node; the
any-finding-or-unavailable exit rule), with the pre-answer step in
workspace/availability.ts: configuration errors keep exit-2 precedence, a
failing workspace answers from current sources consulting and writing
nothing, and a passing one participates in the 13.3 read-time refresh.

Identity definedness (SPEC 11.2) is now definedIdentitySections in
core/mdx.ts — spelled + well-formed + structural with inherited chain
conditions, uniqueness own-only — and graph node construction builds nodes
for exactly those sections: the duplicate-ID winner-picking is removed, so
ambiguous references report 14.5-14.7 and record no occurrence, no winner
resolved through.

Verified: T11.3-1..4 and T5.7-1..4 green; T11.2-*, T13.3-1/2, P-11
occurrences arms pass, each failing only at its first `view`/`at`
invocation (tasks B5/B6). Full suite 54 failed / 583 passed, every failure
mapping to an open FIX_PLAN task.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
The whole-document structural view (SPEC 11.4) lands on the shared 11.2
availability layer: view is JSON-only with variadic <file> operands that
assert membership in the discovered spec-source domain (unknown and
wrong-kind operands exit 2 before any answer or refresh side effect;
combining operands with --file is rejected at parse time), while --file
restricts the domain under the glob rules of 7. Per parseable requested
file the answer serves the positional section tree with construct ranges,
tag-range decompositions, raw attribute spellings (SpecSection.attributes
- repeated, unknown, and spread forms included), the three-state
interpreted datums of 11.2 (identity via definedIdentitySections;
tags/coverage via the new tagsDefined/coverageDefined), every import
declaration with the specifier-form-and-discovery target datum
(SpecImport.designatedFile), the file's occurrence records, and comment
ranges. With --text each node carries own and subtree text, defined
all-or-nothing over transitive expansion (TextAvailability) with the
consulted domain extended by expansionConsultedFiles; the graph's
embedding index now covers invalid-path files' embeddings so defined
text values stay exact there. The workspace pre-answer step is split
(analyzeWorkspaceForAvailability / finishAvailabilityRefresh) so
discovery-consulting argument checks precede the 13.3 refresh.

Verified: T11.4-1..6, T11.2-2, T11.2-4 pass; T11.2-1/3/5, T13.3-1/2 fail
only on the unimplemented at (B6); P-12 stays red until B6 lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
SPEC 11.5: register the JSON-only at command — offset spelling and bound
checks and view-equivalent operand membership precede the refresh, the
innermost containing section resolves with its 11.2 identity datum, the
containing occurrence reports its full 5.7 record, and an unparseable
named file answers the explicit unavailability marker beside its 14.20.
On a verified store (workspace/fast-read.ts) at answers store-backed and
byte-identical to the full path without loading the TypeScript compiler,
which holds P-12's exhaustive sweep inside its budget.

Verified: T11.5-1..3 pass; P-12 passes (545s/600s); fast/full byte
parity swept over 203 offsets; section-11.2 and section-13.3 at arms
pass (their remaining failures are B7/C3/C4 territory).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Register xspec inventory (SPEC 11.6) JSON-only and answer the ten-member
12.7 document without parsing sources, refreshing, or writing: anchoring
via the shared 11.6 spelling, the resolved configuration view with every
default and inferred kind explicit, every discovered source (invalid-path
files included) with its memberships, the derived map by the NAME.mdx byte
shape alone (specSourceDerivedPaths), the record-supplied datum through the
new shared three-way record read (readDerivedFileRecord: absent = empty,
unreadable = condition 23 with concerned path GRAPH_DATA_AREA, exit 1,
everything else in full), journal occupancy by presence alone, and session
files by name alone in byte order of file name. Discovery-level 14.14 keeps
its exit-2 precedence; 14.19/14.13/14.21 are never the inventory's.

T11.6-1..4 pass; T12.2-2/3, T13.3-2/3, T14-4 arms touching inventory stay
red on the C4/C5/C2 defects the plan already names.

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

B8: replace the ad-hoc first-failure {"refused": ...} refusals with the
12.7 findings report. src/core/refusal.ts evaluates every applicable
reason together over the valid workspace — intrinsic-form new IDs,
identity change, collisions locating every bearer, structural parent,
target parent, destination occupancy and validity (obstructed
destination-side directory components included, never 14.22), and the
would-be reasons evaluated in identity space over the current graph with
the mapping applied: refused-cycle (dependency and spec-import, located
at pre-operation coordinates) and refused-unresolvable-reference — one
finding per reason, exit 1. The invalid-workspace refusal still reports
the analysis findings alone; reanalysis remains only as an unreachable
guard. workspace/writes.ts gains probeOccupant and
nonDirectoryComponents; graph.ts exports findCycles; the preview (B9)
shares this evaluation.

Verified green: T6.4-1..7, T6.5-1/2/3/4/6/7, T14-7 (T6.5-5 stays red on
C1, T14-4's 14.21 arm on C2, T13.4-6 on C3, T6.6-* on B9/B10, as
planned).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
--preview on rename/move (SPEC 6.6, 12.7, 14.23; FIX_PLAN B9+B10, landed
together as the plan anticipated): full validation and planning, performed
on nothing. The planners collect classed preview edits (core/preview.ts)
in the same pass as the applied edits — reference rewrites at 5.7
occurrence spans, id-rewrites at the attribute's own characters, removals
extended over line drops, import additions at one deterministic offset now
shared by the real edit and the preview (6.5) — and the CLI emits the
four-member preview document: refusals keep the form with null plan
members through the shared refusal path; success reads the derived-file
record once (B7's reader), reports the record-based delta against the
post-operation generation set (generatedDerivedPaths), and reports an
unreadable record as the unavailable delta beside the shared condition-23
finding, exit 1, everything else in full. A preview takes no workspace
exclusivity and --test-hold with --preview is a usage error before any
lock. T6.6-2/4/5/6 and T12.7-3 green; T6.6-3 red only on its C1-shared
usage arms (mixed-synopsis / non-UTF-8 operands), noted under C1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
SPEC 6.5/12.0: a move operand containing more than one `#` is a malformed
value and an invocation mixing the two synopses' forms matches neither —
both are usage errors the invocation's syntax alone determines, now
rejected in `parseArgv` (reported without loading configuration, before
any lock or hold), and the non-UTF-8 positional exemption is removed so
every argument value is UTF-8-checked (exit 2, never a destination or
invalid-ID refusal). The handler's one-direction mixed check and its
non-UTF-8 `<new-id>` refusal become unreachable and are removed, guarded
by internal errors. Verified: section-6.5 (7/7) and section-6.6 (5/5)
pass, T6.5-5 and T6.6-3 included; T12.0-13's move arms behave (smoke),
its `show a#b#c` arms stay red for C2, noted in the plan.

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

SPEC 12.0/13.3 (FIX_PLAN C2): identity operands of show/query are judged
parse-local against the named file (discovery kind, spelled identities,
named units; an unparseable named file masks the id/unit half) before the
gate report, via the split read pre-answer step (analyzeWorkspaceForRead +
assessWorkspaceRead with a deferred commit); review subcommands judge
session existence against the directory alone and report a session's
corruption only past the gate, on passing workspaces (T10.1-5); multi-#
<node>/<graph-node> values are parse-level malformed values reported
without loading configuration (T12.0-10, T12.0-13). Adds a plan task for
the newly-diagnosed resolvable-baseline-vs-gate defect (T13.3-3's impact
arm) and sharpens C3/C4 with observed failure modes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
SPEC 6.3/12.0/13.3 (FIX_PLAN C2b): split baseline resolution into
readBaseline (ref + journal prefix/replay, exit 2 before source
validation) and validateBaselineContent (exit 2, only past the gate and
before the refresh commit). impact --base and review create --base now
report the gate's findings (exit 1) when the current workspace fails
build's validations and the baseline shares them; replay judges only
suffix lines, so a garbage journal line inside the shared prefix is the
gate's 14.13, never a replay failure. T6.3-1..4 and T13.3-3's
garbage-journal arm green.

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

SPEC 13.4/14.22: an obstructed write path is any workspace-relative
directory component occupied by a non-directory — plain file, symlink, or
other — one condition-22 finding per distinct offending component,
concerned path the component. classifyOccupant maps ENOTDIR/ELOOP to
absent so per-file staleness and removals never crash below an obstructed
component. The 13.3 gate (assessWorkspaceRead) now evaluates build's full
write set before any store read, and the query/at store fast path verifies
the write set unobstructed, falling back to the full path otherwise.

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

SPEC 13.3/14.23/14.10 (FIX_PLAN C4): recorded generation state that exists
but cannot be read as a record is neither read, repaired, nor replaced by
the refreshing reads — they answer from the current analysis, report no
finding for it, and leave the store byte-for-byte — and `check` reports
the state as staleness under the exclusive unreadable-record unit form,
one condition-10 finding concerning the graph-data area, the recorded-file
per-file form undetectable while it holds.

- workspace/graph-data.ts: `LoadedGraphData.state` three-way
  ("absent" | "readable" | "unreadable"), one classification rule shared
  with `readDerivedFileRecord` (now derived from the same load).
- workspace/refresh.ts, workspace/availability.ts: both refresh points
  skip predicate and write on the unreadable state.
- workspace/check.ts: unreadable → `unreadableRecordStaleFinding()`
  (path `.xspec`, locations empty), exclusive with the mismatch arm.
- core/graph-data.ts: comments brought in line with the new discipline.

T13.3-2 green in full (the corrupt-record sweep: every refreshing read
exit 0, store untouched, `inventory` still 14.23-unavailable, `build`
replacing the state); section-6.6/11.6/14 files green. T12.2-2/3 still
red at their family-3/missing arms on C5's concerned-path defect (the
mismatch unit form names `.xspec/graph.json`), as the plan records.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
SPEC 10.7/1.7: the self-contained payload of next --json, show, and export
presents every present scope, context, and origin node — requirement node
and code location alike — with its source range read from the current
graph; an absent node carries none. A present code-impact scope now enters
as identity + presence + sourceRange (CodeLocationNode.range, no text), and
a currently-present origin node's entry carries its current range (the
after side is the current graph's). The human origin rendering gains the
matching range line.

Verified: section-10.7-i/-ii, section-1.6-1.7, section-10.2-10.3 all green
(T10.7-7 and T10.7-12 included); typecheck and format clean.

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

Three product fixes from the C7 sweep's two residual reds (P-11, P-12):

- src/core/canonical-json.ts: one iterative single-buffer emitter behind
  canonicalJson and compactJson — linear time in the rendered text (the old
  per-level join re-copied every subtree, cubic on nesting depth), no native
  recursion, and pretty indentation bounded at 32 levels. Byte-identical
  output for every document nested within the bound (verified over view,
  query, check --json, and .xspec/graph.json on a staged workspace); a
  depth-4096 fuzz tower's view answer is ~35 MB in ~4 s instead of
  quadratic-indentation gigabytes past the harness's 64 MB guard.

- src/cli/commands/view.ts: the node tree renders iteratively (children
  before parents over an explicit stack), so a depth-4096 balanced section
  tower no longer overflows the call stack (SPEC 11.4 answers any parseable
  nesting).

- src/core/ts-module.ts: the TypeScript compiler API loads once through
  createRequire; the four former `import ts from "typescript"` sites route
  through it (type positions via `import type * as tst`). Importing the
  ~8.5 MB CJS file through the ESM loader cost ~0.2 s per invocation in
  format sniffing and named-export lexing; every configuration-parsing
  invocation drops ~0.5 s -> ~0.26 s.

Verified: typecheck, format:check, build clean; full suite 636/637 — P-12
green at 321 s (was a 600 s timeout, locally and in CI run 33296625151), all
previously-green files still green. The one red is P-11, now failing inside
the harness: its recursive decodeViewNodeForm overflows on the depth-2048
view tree its own generator draws, after the product answers conformingly —
see the FIX_PLAN C7 note; logged separately to TEST-SPEC-PROBLEMS.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
No product change can clear P-11: the harness's recursive view decoder
overflows its call stack on the conforming depth-2048 answer its own
generator provokes (CI seed 271828183, trial 1), a harness-implementation
defect by the property machinery's own H-8 classification. Details, exact
reproduction, and evidence in the entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Run 33298889697 (e239f0c): harness-self green, suite-linux 636/637 (P-11's
harness error alone), Windows E-6 8/9 — its byte-identity arm starved
because the suite-linux upload step skips on any test failure (no
`if: always()`), which self-heals once suite-linux is green.

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

Applied REVIEW.md items:
- C1 (Critical): added H-11 to section 0 — the harness must decode and
  evaluate every conforming answer at the scale its own staged inputs
  provoke (decoding and all per-datum traversals alike), with harness-side
  failures reported as harness defects, never product diagnoses or passes;
  added S-8 to section 17 gating that capacity against synthetic
  conforming-form documents at maximum staged scale before any product
  exists. No section 16 test content or SPEC-facing assertion touched.
- I1 (Important): pinned a test-strength floor on P-8's giant-nesting
  mutation class (staged draws include nesting at least 2048 levels deep),
  inherited by P-11 through P-8's generators.

Rejected: none.

Resolved specs/tmp/TEST-SPEC-PROBLEMS.md (2026-08-30 P-11 entry): the
document now states the obligation whose absence admitted the harness
decoder defect and gates it red-green; the P-11/P-8 test text stands
unweakened. Problems file deleted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
Applied I1 (Important): H-11's operative clause now covers the capture of
H-2's observed output streams — capacity limits dimensioned to staged
scales, exhausted capture limits surfacing loudly (silent truncation is
indistinguishable from the partial-document violation P-8/P-11 assert),
classification extended to failures while capturing — and S-8 gains a
capture arm at maximum staged scale via S-3's stand-in mechanism, making
obligation and pre-product gate coextensive with the whole pipeline.

Applied O1 (Optional): S-8's scale dimension rephrased as H-11's ("the
maximum scale the suite itself stages"), keeping the gate coextensive
with the obligation if a large deterministic fixture is ever added.

Rejected: none.

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

- C1 (Critical, applied): new T6.5-8 asserts 6.5's added-import line
  discipline (trailing U+000A; preceding U+000A at a mid-line offset) in
  TS and MDX arms, value-blind on identifier and insertion offset;
  T6.5-2/T6.5-7 cross-references updated.
- I1 (Important, applied): S-2 gains round-trip scale vectors at P-8's
  giant-nesting floor and the largest staged document size.
- O1 (Optional, applied): S-8 dimensioned to the answer scale H-11
  obliges (expansion blowup included), not staged-input size.
- O2 (Optional, applied): new T1.3-7 deterministically anchors P-8's
  2048-depth floor outside the generator machinery; P-8 points to it.

No items rejected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TyZ5zUv2UCkvTkM1tkYUp2
….0-1 and P-1 precision

Applied C1: SPEC.md 12.7 fixes "the value forms every JSON output uses"
universally, pinning document forms only for the enumerated surfaces
(12.6 versions the whole contract; 1.7 lists 10.7/11/12.4 among the
range-carrying outputs). Rewrote H-3 as a two-tier contract — pinned
document forms plus universal value forms that adapters may never
re-map (latitude confined to the surrounding unpinned shape); updated
the §11 preamble's query routing; extended T12.7-1 with literal
{"start","end"} arms on query node/row ranges, show --json, and review
payload nodes, and widened the unavailable-member exclusivity walk to
every JSON document the suite captures.

Applied O1: reworded T12.0-1's flag-less/--json clause to
information-strength — byte-identity is not asserted (the two
invocations differ in argv; 12.0 determinism binds per identical
input), aligning with the §11 preamble.

Applied O2: P-1's segment property now judges the staged spelling's
resulting split (a .-containing draw stages as multiple segments,
nested beneath the chain its prefixes spell), mirroring the tag half;
structural-rule outcomes stay with T1.3-2..4.

Rejected: none.

Co-Authored-By: Claude Fable 5 <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.

2 participants