sdg: initial build — xspec#1
Open
lzrscg wants to merge 166 commits into
Open
Conversation
…; record seed-style principle in PHILOSOPHY.md
Triage classification: initial build (no prior specs/SPEC.md). Seed adopted verbatim as the SPEC.md draft with Markdown structure restored; single-file (no modules) — components share a dense core and the Developer authored the seed as one coherent document. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
GOALS.md approved verbatim by Developer via Liaison. SEED.md deleted (consumed by triage). Phase 2 complete; next: Phase 4 refinement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applied: C1-C6, I1-I17, O1-O4, O6-O8. - C1: layer diagram removed (prescribed internal architecture, untestable). - C2/I8a: config example disambiguated (boundaryKind, selector kind); group selectors gain a kind disambiguator mirroring boundaryKind. - C3: canonical identity defined as journal-origin identity, so stored hashes are rename/move-invariant; forced by 6.2 + 10.4 + the GOALS durable-identity bullet. Reintroduced identities stay hash-distinct; baseline hashing uses the baseline journal; non-prefix journals fail the command. - C4: code-location identity syntax, named-code-unit rule, nesting, and document-order collision suffix defined in 4.6. - C5: upstream-changed propagates through subtrees (matches §15); parent-consistency items exclude the root; dependency-consistency items only for nodes with a directly changed dependency target; §15 made exact. - C6: split now emits a parent-consistency item for the scope root's own text, with defined blocking, removal of the original, and refusal cases. - I1 also covered the identical dangling ref in 1.4 ((3.8) -> (2.6)). - I2-I17: '#' banned in segments/paths with '/' as canonical separator; error conditions 15-19 added (imports, constructs, props, node usage, source paths); TS reference forms pinned; content-based staleness; ignored-node definition; session-name syntax; review command edge cases; re-derivation mechanics; read-command graph refresh; move edge cases; derived-path ownership and source exclusion; lookup exit codes; baseline edge cases. Rejected: O5 (extract §10 into a module) - reviewer itself deems a single file defensible at current size, and PROCESS module rules keep the full review interface (commands, statuses, item kinds) in SPEC.md regardless, leaving little to extract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applied: C1, C2, I1-I15, O1-O6, O8, O9. - C1: partitioned exit codes — configuration errors are load-time usage errors (exit 2) for every command per GOALS; nonexistent rename/move origins and unknown review item IDs are usage errors; refusals stay exit 1; 14.14 recast, 12.2 config clause relocated. - C2/I1/I2: hash property sentences corrected; metadataHash pinned to d-declared targets; upstream-changed covers dependency-set changes; attribution redefined to originating (changed or metadata-changed) nodes with a metadata-edit worked example. - I3/I4: resolved/blocked defined, invalidated items re-enter via next and re-block dependents; total item order specified for path-blocks and coverage sessions. - I5/I6/I7: import specifier resolution and permitted forms defined (MDX and TS); MDX comments carved out and stripped; spec-group files must be .mdx (14.19). - I8: byte-exact Markdown emission (in-place deletion, emptied lines dropped with terminators). - I9: derived-file paths recorded in graph data; build removes orphans, check reports them (14.10), refresh preserves the record. - I10: mutating commands mutually exclusive per workspace; second fails with usage error; interrupted mutations detected by check. - I11: identity syntaxes per command (root bare path, code locations for query edges/reachable, show). - I12: arrow-function initializers are named code units. - I13: config key optionality and defaults pinned (specs required; markdown absent = no emission; emit and mode required). - I14: new 14.20 unparseable source; read commands fail with build validation errors on invalid sources. - I15: 13.1 restated behaviorally (module + companion files satisfying 4.1-4.5); declaration-map mechanism dropped from 4.2; source exclusion by .xspec. filename rule. - O1-O6, O8, O9: clarifications as suggested. Rejected: - O7: pinning a specific hover-truncation number is arbitrary pseudo-precision bordering on an implementation detail; the existing deterministic-limit requirement plus staleness checking (14.10) already fully pins generated content. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applied all items: C1-C4, I1-I9, O1-O8. - C1: subtree/own text defined positionally via Markdown-compilation contribution (interleaved, byte-exact); ownHash made run-aware so the subtreeHash iff-property holds under interleaving. - C2: cross-module text call (14.11) now reported by build/check per the preamble default; 4.5/14.18 carved to keep conditions 11 and 18 disjoint. - C3: 14.10 marked check-only. - C4: invalidation anchored to state recorded at resolution, with explicit absent markers, so deletion review stays resolvable. - I1: rename/move regenerate derived files as build does. - I2: journal added to derived-file reproducibility inputs. - I3: doc-comment limit pinned (1000 code points, ellipsis) and */ escaping. - I4: audit strategy pinned (roots included, 10.5 scope, child-item blockedBy). - I5: resolve-time re-derivation generalized to all strategies. - I6: review next with nothing to review defined (exit 0, both cases named). - I7: --test-hold seam for deterministic mutual-exclusion testing. - I8: duplicate import bindings under 14.15; TS string-form text() under 14.8. - I9: deleted nodes reported under journal-mapped-forward baseline identity. - O1-O8: placement explicit, example labels moved outside fences, self-rename refused, root metadata/coverage reporting pinned, dynamic .xspec import invalid, review create modes exclusive, list/status/show content lists, read-time invalidation never persisted. Rejected: none.
Applied: C1, C2, I1-I18, O1-O6, O8. - C1: made hash constructions satisfy the stated iff properties by folding canonical identities into the inputs — child identities enter ownHash at their excision points (so structural edits are the parent's edit, keeping GOALS attribution sound), dependency targets enter effectiveHash as (identity, hash) pairs. Rename/move invariance preserved via canonical identities. 5.4/5.5/5.6/6.2 aligned. - C2: split decompositions are recorded session state; defined the (kind, scope-node) uniqueness invariant, match/reuse at split and re-derivation, recursive decomposition replacement, and blockedBy recomputation (retained items keep theirs). - I1: policy violations are check-only findings; build regenerates regardless (7.5, 12.1, 14.12). - I2: reads evaluate context sets by running generators unpersisted. - I3: id/coverage/tags must be static string literals (2.7, 14.17). - I4: explicit N+1 own-text runs incl. empties (1.6). - I5: absent journal = empty journal, current and at baseline. - I6: rename and file-form move are pure; section-form move restructures both parents (changed + cascades). - I7: impacted code evaluated over union of baseline+current references/embeds edges; added/deleted count as changed. - I8: empty targetTags and empty selector tags are config errors. - I9: whole-pattern leftmost-shortest disambiguation for wildcards and captures. - I10: context/origin/blockedBy defined for all item kinds, incl. coverage and split-created items; blockedBy empty by default. - I11: audit order = file path bytes, then document order; blocking enforces bottom-up. - I12: node/file/glob args are workspace-relative; --config and --test-hold resolve against cwd. - I13: rename/move refuse up front on a workspace failing build validation. - I14: create refuses names matching an existing session case-insensitively. - I15: corrupt review session defined (14.21); review subcommands exit 1 on it. - I16: query subtree/ancestors membership+rows defined; reachable --kinds default stated. - I17: markdown.outDir must resolve within the workspace root. - I18: parent-consistency blockedBy defined per changed branch; only subtree-coherence/parent-consistency block it. - O1 global byte-wise comparison; O2 length-one cycles; O3 exclusivity ends with holder process; O4 orphan-removal claim qualified; O5 --test-hold creation failure; O6 flag syntax; O8 UTF-8/no-BOM. Rejected: O7 (extract §10 into a module only if the file grows — condition not met; Reviewer itself deems current size acceptable, and §10 is tightly coupled to the hash and CLI contracts).
Applied: - C1: separated expanded text values from pre-expansion "own content" (1.6); ownHash and the subtreeHash iff now defined over own content (5.5); all own/subtree text outputs (4.2, 10, 11, 12.4) pinned to the expanded value. - C2: whitespace and control characters defined by exact code points in 1.4; referenced from 2.6 tag splitting and 3 line dropping. - C3: review create records fully resolved creation parameters (baseline commit; coverage profile snapshot with group globs/kinds); generator runs use recorded parameters (10.1, 10.4, 10.5, 10.7); unreadable recorded baseline fails per 6.3 as usage error. - I1: imports in xspec source files may not bind S, Spec, or text (2.1, 14.15). - I2: id/coverage/tags values must be quoted-form string literals; braced expressions invalid (2.7, 14.17). - I3: non-conforming files under .xspec/reviews/ are not sessions and are ignored; review list reports corrupt sessions and exits 1 (10.1, 10.7, 12.0, 14.21). - I4: failed build/refresh modifies nothing - derived files and graph data unchanged (12.1, 13.3). - I5: review export payload defined - JSON-only full session dump with invalidation applied (10.7). - I6: code-group imports designating derived-file paths outside the .xspec specifier are invalid (4, 14.15). - O2: worked change-category example for pure structural add/remove (5.6). - O3: next on a zero-item session reports the every-item-resolved case (10.7). - O4: session corruption invariants enumerated (10.1). - O5: build/check report all detectable errors; parse-failure masking defined (14 preamble). - O6: "collapsed" ancestor chains defined for impact output (9.3). Rejected: - O1 (modularize section 10): review commands, invalidation, and strategy re-derivation are tightly interwoven; a split at the current file size risks restating the interface in the module or referencing module internals from SPEC.md. Reviewer itself deemed deferral reasonable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…d reference-chain grammar in SPEC.md Applied: C1, I1, I2, I3, O1, O3, O4, O5, O6 - C1: repeated props on <S>/<Spec> are invalid (2.7, 14.17) - I1: line terminator set (CRLF as one, lone LF, lone CR) and unterminated final line defined for the line-drop rule (3) - I2: d value pinned to braced expression holding a single static reference or array literal; quoted/valueless d is 14.17, non-reference braced value is 14.8 (2.2, 2.7, 14.17) - I3: static-chain grammar pinned (.name / ["literal"] segments only; optional chaining, non-null assertions, parentheses, other indices dynamic), text(...) arity pinned to one argument, non-chain expression statements in TS classified 14.18 (1.4, 2.4, 4.5, 14.8) - O1: 13.5 atomicity restated as the observable contract (readers never see partial content) - O3: repeated flags are a usage error; list-valued flags take one comma-separated value (12.0) - O4: ids --tree/--file semantics defined; --file is a glob as in 11 (12.3) - O5: companion files named NAME.xspec.<suffix>, keeping them under the derived-file exclusion (13.1) - O6: missing parent id masks structural-ID checks for immediate children only (14.2) Rejected: O2 — pinning MDX/TypeScript grammar editions is a product-scoping choice not derivable from the bundle; the spec's own construct grammar (2.1-2.7, 2.4) is pinned independently of edition and 14.20 remains the residual parse-failure class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applied all items; none rejected. - C1: 6.2 section-form move claim made conditional on own-content change; coinciding-parent degenerate case acknowledged as pure in effect. - C2: 15 example graph gains the two root contains edges. - I1: 5.4 canonical identity redefined as a journal walk whose termination (an entry vacating the tracked identity) plus end position distinguishes reintroduced identities by construction. - I2: 9.3 propagation path defined (contains/dependency steps to the explaining edit; subtreeHash chain for direct, effectiveHash for transitive). - I3: 7 + 14.14 unknown configuration keys are a configuration error. - I4: 10.7 guarantee scoped to recorded parameters; discovery follows current configuration, de-grouped files leave the session's view like deletions. - I5: coverage named as the third built-in strategy (10, 10.5, 10.7). - I6: 6.5 section-form text semantics pinned (exact deletion + line drop at origin; insertion before the target parent's closing tag with terminator rules; no other byte changes). - O1: 12.0 missing required flags/arguments classified as usage errors. - O2: query edges takes --kinds (comma list) aligning with reachable. - O3: 7 empty groups and group-less specs/code maps are valid. - O4: 7.4/14.14 wrong-kind group references are configuration errors. - O5: 12.0 shortest-path tie-break (element-wise byte-least identity sequence); 8.2 reports one shortest covering path. - O6: 6.4 rewritten references preserve quote/access form; fresh forms pinned. Also absorbs the prior interrupted round's uncommitted 4.5/6.5 edits, which this review upholds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applied: - C1: section-form move now refuses (exit 1) when the target parent section is missing or lies within the moved subtree (6.5). - I1: discovery never follows symbolic links (7); the only rule coherent with baseline reconstruction from git content (6.3). - I2: impact output pins edge+path selection — minimized over all qualifying impact edges, 12.0 tie-break, byte-least kind (9.3). - I3: code-impact context pinned to impact-edge targets whose subtreeHash or effectiveHash changed (10.5 item 3). - O1: reference rooting is scope-aware; shadowed bindings are not spec references (4.5). - O2: type-level TypeScript references are not rewritten by rename/move (6.4). - O3: each changed branch enters parent-consistency context as one node, A's child on the branch (10.5); 10.4 aligned to context node. - O4: graph-data content declared opaque with its observable contract (13.3). Rejected: none. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applied: - C1: total item order for absent scope nodes — present-first at the document-order key, absent ordered by forward-mapped identity then item id; covers 10.5, 10.6, and 10.7 orders. - C2: item/decomposition/invariant matching and invalidation compare requirement nodes as canonical identities (5.4), never spellings; reads present recorded nodes under forward-mapped current identity. - I1: 12.0 pins output streams — reports (findings included) on stdout, exit-2 errors and diagnostics on stderr; --json document is the entire stdout. - I2: xspec.config.ts pinned as declarative static data (exact form defined in 7); non-conforming config is a configuration error (14.14). - I3: blockedBy acyclicity added to session invariants (10.1); 10.7 next's dead "every item needing review blocked" case removed. - I4: symlink write semantics (13.4): derived-path writes replace the link itself; non-plain-file durable paths are journal error / corrupt session (14.13, 10.1, 14.21); symlinked workspace-relative directory components refuse the write (new 14.22). - O1: --test-hold creation fails if anything exists at the path. - O2: --file glob outside-root classified as invalid flag value (12.0), exit 2 like 14.14. - O3: 14.20 grammar follows the file name (.tsx parses as TSX). Rejected: - O4 (modularize): strategy derivations and the condition list are contract-level content referenced by number throughout SPEC.md; extraction would force forbidden references into module internals or duplication — no loosely coupled component exists. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…ation, split child context, empty policy kinds; tighten root-marker gloss and mixed-failure exit precedence Applied: I1 (root precedes its file's sections in document order, 1.2), I2 (non-static bare TS reference in expression-statement position is condition 14.8 — 4.5 clarified, 14.8 enumeration extended, 14.18 carve-out added), I3 (split's per-child subtree-coherence context is the child's ancestor chain, 10.7), I4 (empty policy kinds list is a configuration error, 7.5 + 14.14), O1 (root-marker impact gloss qualified to subtreeHash/effectiveHash changes, 4.5), O2 (rename/move argument existence and baseline resolution precede source validation, with unparseable-file masking — 12.0 bullet + 6.4 anchor). Rejected: none. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
lzrscg
force-pushed
the
sdg/initial-build
branch
from
July 10, 2026 00:08
817c9bf to
81df91b
Compare
…it-destination scope, hash sort keys, move-import determinism Applied: I1, I2, O1, O2. Rejected: none. - I1: 10.2 defines baseline (fixed at item entry: recorded-baseline graph in baseline sessions, entry-time graph in audit/coverage) and current (= the 10.4 recorded state, written at creation, rewritten at each resolve, reported as recorded); 10.4 homes the recording in the current field; 10.7 next --json hashes glossed as baseline/current. - I2: 7.3 states when configured Markdown emit destinations exist — only with markdown present and emit true; none when markdown is absent or emit is false. - O1: 5.5 sort key for dependency-target pairs and metadataHash identities is the full canonical identity (identity string, then journal position, earliest first). - O2: 6.5 move-added spec module imports bind fresh identifiers with deterministic choice and placement; rewritten file content is byte-deterministic for a given operation and workspace state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Record Developer's delegation of undirected implementation/tooling choices (mainstream, minimal-dependency, deterministic defaults; seed-implied stack facts are settled).
… and test harness Developer confirmed all eight proposed choices via the Asking Developer process: TypeScript strict/ESM/tsc on Node active LTS; remark-mdx + TypeScript compiler API (config statically parsed, never executed); in-repo arg parsing/glob/walking with minimal runtime deps; SHA-256 via node:crypto with injective framing; system git read-only plumbing; Vitest with blackbox CLI-driven E2E; Prettier only; single npm package xspec with src/ + test/ + specs/ layout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…PEC.md section by section Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…ion contract, blackbox staging Applied: C1 (new T12.0-11/12: git read-only around baseline reads, git-less non-baseline surface; preamble added to H-7 traceability keys), C2 (duplicate profile/rule names and repeated capture wildcard in T7.4-1/T7.5-1), C3 (TS duplicate-import-binding matrix in T4-2 with non-spec negative control), C4a-f (1.4 class boundaries in T3-3 and P-2; own-content line-drop suspension fixture pinned in T5.5-2; 4.6 function/class-expression units and string-literal member in T4.6-1/3; text() attribution to named units in T4.6-1; wildcard dot-segment cases in T7-4; retained context set in T10.5-5), I1 (H-2 sharpened: subprocess invocation of the executable is the only channel, stated in behavior terms — PROCESS.md blackbox MUST plus SPEC.md's declared complete interface; the conflicting in-process default in IMPLEMENTATION.md cannot stand against it and IMPLEMENTATION.md's own preamble yields to the specs — flagged upward for correction), I2 (H-3 and T10.1-4: shape-dependent session-corruption fixtures staged by adapter-layer transformation of product-written files, never from an assumed layout), I3 (T10.4-1 full per-kind invalidation matrix with controls), I4 (T13.3-2/ T13.4-3: spec-observable operational definition of graph data), O1-O9. Rejected: I5 — SPEC.md's silence on duplicate config-object keys is an ambiguity in a degenerate input, not blocking per PROCESS.md (no requirement exists there to contradict or test; product stays implementable and fully testable), so no SPEC-PROBLEMS entry and no TEST-SPEC change — TEST-SPEC must not invent a requirement for unspecified behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…ST-SPEC H-2 Developer-delegated conformance amendment (Liaison directive): the Test harness section's in-process-by-default invocation (with subprocess exceptions and bin smoke coverage) contradicted TEST-SPEC H-2, which the Phase 6 review sharpened to subprocess-only. Replaced with: tests invoke the xspec executable as a subprocess in all cases, fast paths included; the product's (argv, cwd, stdout, stderr) entry (Architecture section, unchanged) is noted as an implementation detail and not a permitted test channel. No other section or technical choice altered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
… move regeneration, baseline replay Applied review items (TEST-SPEC.md refinement, iteration 2): - C1: staged every untested 14.14 arm - config syntax error (T7-2); markdown without emit (T7.3-1); missing profile/rule required fields, invalid targets/mode/boundaryKind/type enum values, unknown boundary and selector group names, kind mismatches (T7.4-1, T7.5-1) - C2: new T14-5 positive grammar-selection test (.tsx parses as TSX, edges recorded and attributed per 4.6); 14.20 primary-test map updated - I1: T6.5-3 now asserts the section-form move's journal append and finishing regeneration as T6.4-7; T6.5-2 byte-change scope aligned with SPEC 6.5 wording so the regeneration is not read as forbidden - I2: T6.3-4 adds the unreplayable-mapping arm (garbage journal line, H-4 shape-independent) at impact --base and review create --base, error naming the entries, create modifying nothing (10.7) - O1: T4.5-2 root-marker impact qualified to text edits (subtreeHash/ effectiveHash scope of SPEC 4.5) - O2: query section intro states information-equality via H-3, not byte-identity, between invocations with and without --json - O3: T4-2 adds TS-side bare/absolute .xspec specifier form violations Rejected: none. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…ation, metadata-terminus paths, segment-exact chains
Applied:
- C2: T10.6-3 (audit re-derivation on updated resolve) and T10.7-11 (coverage
re-derivation with recorded profile) added; T10.7-9's split/re-derivation
persistence assertions pinned to run in both a path-blocks and an audit session.
- C3: T9.3-2 gains the metadata-terminus arm — pure d-list edit on D, code
location impacted via X depends-on D, witness path ends at the
metadata-changed node with no changed node anywhere.
- I1: T2.4-4 added — computed access is segment-exact: BASE["a.b"] is
unresolved (14.5/14.6/14.7) while local string "a.b" resolves.
- I2: T5.5-5 gains the order-insensitivity arm — reordering a d array and a
tags list changes no hash and no categories.
- I3: T7-4 gains the literal-metacharacter arm ([1], {a,c}, !, +(x) match
literally); P-7 and P-1 generators include these characters.
- I4: E-6 added — Windows CI leg for the platform-sensitive subset (1.5
separator quantifier is unobservable on Linux), with cross-leg
product-to-itself byte comparison per H-4.
- O1: T5.4-1 journaled-reintroduction variant (rename c->a after a->b).
- O2: T5.5-2 kind-distinction arm (child construct replaced by same-canonical-
identity embedding via journaled move; ownHash must differ).
- O3: T8.2-1 root trio pinning the root-node reason's position.
- O4: T1.5-2 covers spec-group and code-group # paths.
- O5: T5.5-4 reworded — requirement nodes bear only depends/embeds edges.
- O6: T10.1-1 qualified to a freshly built workspace (13.3 refresh otherwise).
Rejected:
- C1: the proposed check-side conflicting-journal arm asserts behavior SPEC.md
does not force — the staged journal (a->b, a->c concatenated from clones) is
byte-identical to one reachable by valid operations (rename a->b; reauthor a;
rename a->c; manual delete — 5.4 reintroduction, 6.6), so a conforming check
must accept it; no blackbox staging can force the conflicting/unreplayable
flavors of 14.13 at check beyond the malformed and non-plain-file arms
already tested (T6.1-3, T6.3-4, T12.2-2), and asserting either direction
would add a requirement SPEC.md does not contain.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…boundary, session-name gate, Windows review leg, class attribution Applied C1: T2.7-2 rewritten — the no-hash-change assertion now covers only the layouts SPEC.md 3/1.6 supports (edit any layout; delete inline comment with retained non-whitespace; delete own-line comment with its entire line), plus a boundary arm asserting that deleting only an own-line comment's construct characters changes the containing section's ownHash and yields `changed`. Applied I1: T10.1-3 gains the valid-name discriminators — invalid-stem .json files (.foo.json, "a b.json") with garbage content and wrong-case NAME.JSON are not sessions; list exits 0, check reports no 14.21. Applied I2: E-6 Windows fixture now includes an audit review session (create, next --json, resolve, export) with the session file and review outputs byte-compared across legs; audit records no creation parameters, keeping the comparison free of git commit identities. Applied I3: T4.6-1 gains class-as-innermost-unit arms — a marker in a class static block and a text(...) call in a plain non-function property initializer each attribute to bare path#C. Applied O1: T12.0-5 native-separator negative (specs\A.mdx → exit 2), Windows-discriminating via E-6. Applied O2: absent-scope ordering arms added to T10.6-2 (audit) and T10.7-4 (coverage). Applied O3: kind-mismatch mirrors added to T7.4-1 and T7.5-1 (code-kind naming a spec-only group). Applied O4: T3-3 multi-line-construct arms (residue merging, merged-empty-line drop); P-2 generator now emits multi-line comments. Rejected: none. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…undary-overlap coverage; log SPEC 4.5/§8 problem
Applied:
- I1: T12.4-1 show/query-node comparison scoped to SPEC 12.4's enumerated
fields; tags and coverage attribute (query-node-only per SPEC 11) are
explicitly outside the show assertion, so the test adds no requirement.
- I2: new T8-4 — boundary-and-target overlapping populations (file in both
spec groups, T7.1-1): a required node that is itself a boundary node with
no incoming dependency edge is uncovered in direct and transitive modes;
boundary membership is never a zero-length covering path.
- O2: T7-3 omitted-optional-key observations stated per key (code: no
discovery/edges and unknown --from; markdown: no .md, T3-6; coverage:
zero profiles exit 0; policy: no findings exit 0).
Logged as blocking SPEC problem (specs/tmp/SPEC-PROBLEMS.md):
- I3: SPEC 4.5's "a root marker grants no coverage" contradicts SPEC 8's
path reachability once a top-level {text(...)} (2.7/2.3/1.2) makes the
root a dependency-edge source; also unpinned for roots as spec-boundary
members. Root-as-source fixtures held back pending Phase 4 resolution.
Rejected:
- O1: a byte-copied journal line is not guaranteed conflicting/unreplayable —
entry bytes are opaque and a conforming product with position-independent
entries reaches an identical duplicate via a legitimate history (rename;
manual delete+re-author, 6.6; identical rename), after which check must
pass; requiring a 14.13 finding would add a requirement.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Applies the review round (critical:1 important:0 optional:2) per Developer
ANSWER (option 2): root nodes never participate in coverage paths, and the
fix is coverage-scoped only.
- C1 applied. SPEC 8: the reachability definition is qualified (dependency
edges between non-root participants); the root exclusion is stated
normatively alongside the contains exclusion - roots are never boundary
nodes, intermediates, or targets, in either mode; a spec-group boundary
contributes only its non-root requirement nodes; root-sourced embeds
edges and d/text(...)/marker references targeting a root never extend a
covering path. The exclusion is expressly coverage-scoped: roots remain
group nodes (8.2 ignored-node reporting unchanged) and root-touching
dependency edges remain ordinary edges for policy (7.5), impact (9.2),
effectiveHash (5.5), and query (11). Top-level {text(...)} remains
permitted exactly as 2.7/2.3/1.2 stand, with its root-sourced embeds
edge and 5.5/5.6/query-edges consequences as written. 4.5's sentence is
repaired: no coverage in any profile, because roots never participate in
coverage paths (8), not merely because they are never targets. 1.2's
bullet now cites both exclusions.
- O1 applied via the coverage-scoped wording above.
- O2 applied: 4.5's impact illustration now covers changes upstream of the
document that change the root's effectiveHash.
- Rejected: none.
Rationale (Developer ANSWER): coverage must be earned through
requirement-level links (code-to-section, section-to-section);
whole-document gestures - root markers, top-level embeddings - provide
impact tracking and document composition, never coverage. GOALS.md's
"root nodes ... are never coverage targets" is the same stance at target
granularity.
Resolves the 2026-07-10 entry in specs/tmp/SPEC-PROBLEMS.md (4.5 vs 8);
the four held-back TEST-SPEC surfaces are now determinate. Problems file
deleted; no logged problems remain.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…go-to-definition Applied review items (iteration 2, re-entered refinement): - I1: 6.5 — mirrored rename checks stated in identity terms: cross-file section move keeping its ID is valid; exact self-move refused, no journal entry; new-id collision checked against the target file after removal. - I2: 11 — reachable requires a path of one or more edges, so equal --from/--to report no path (cycles invalid, 5.3); reachable --kinds accepts only dependency edge kinds, contains is an invalid flag value. - I3: 4.2 — go-to-definition defined for root references: start of the source file; non-root resolves to its <S> section. - O1: 11 cites 5.5 (not 1.2) for the absent root coverage attribute; 12.4 show prints "identity" rather than "ID" (roots have no ID). - O2: 7 — empty top-level coverage/policy list is valid, equivalent to omitting the key. - O3: 10.2 — items are created with status unresolved at create, re-derivation, and split alike. Rejected: none. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…nge writer test/windows/e6-subset.test.ts declares the shared registry entries T1.5-1, T1.5-3, T12.0-5 against the built product and reruns the four single-casing probes of T7-4, T10.1-2, T10.1-3, T12.0-6 through probe functions extracted from (and still called by) their registered suite bodies — one code path per leg (TEST-SPEC E-6, C-2). test/helpers/e6.ts holds the representative byte-identity fixture (build, check, query, coverage, impact over a pinned-git baseline, journaled rename, journaled file-form move with clean post-move check, audit review create/next --json/resolve/export) capturing per-step transcripts and the final tree (.git excluded); test/suite/e6-exchange-writer.test.ts writes the captures into XSPEC_E6_EXCHANGE_DIR when set (the e6-linux-outputs CI artifact), and test/windows/e6-byte-identity.test.ts reruns the identical fixture and asserts byte identity, failing loudly on a missing or malformed exchange once its own fixture run succeeded. Verified: npm run test:self green (228/228; probe refactors re-certified); npm run test:windows collects 9 tests, all 8 product-facing failing as diagnosed assertion failures against the stub (H-8); exchange write/read/compare round-trip verified with a scratch test (removed). CI wiring checked statically against .github/workflows/ci.yml. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…(CLEAN-01) All three projects hold real tests, so the self-labeled scaffold smoke tests are removed (test/self/, test/suite/, test/windows/). This was the final FIX_PLAN task, so specs/tmp/FIX_PLAN.md is deleted per PROCESS.md Ralph rules. Phase-gate confirmations (local, Linux, network-disabled where stated): - typecheck + format:check green. - E-5: npm run test:self twice — 227/227 green both runs, per-test results identical (JSON-reporter compare). - E-3/H-1: files run in parallel within a run (aggregate test time ~130s vs ~86s wall); two concurrent test:self instances both green. - C-1: all 17 per-fixture certification reports (4 conformers, 13 violators) appear in test:self stdout; the harness-self CI job's exact command (run-without-network.sh npm run test:self) green locally, 227/227. - Pre-product red baseline (E-1 shape: suite+self, network disabled, XSPEC_E6_EXCHANGE_DIR set): self 227 passed; suite 258 tests all failed, every failure a diagnosed HarnessAssertionError — zero passes, skips, non-assertion errors, or timeouts. Windows project on Linux: 8/8 failed as diagnosed, same audit clean. - E-1 content: sections 1-16 in test/suite (257 registry entries + E-6 writer), section 17 incl. certification in test/self. Live CI is not observable from this environment (gh absent; GitHub API jobs endpoint 503): wiring verified statically; note the newest Actions run on this branch is 2026-07-11 (1453a98, PR #1) — pushes since then have not triggered pull_request runs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…proved) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Convert the iteration-1 findings (total non-implementation at 8a79d6e) into a dependency-ordered task list: kernel, glob engine, CLI entry, config/discovery, MDX and TS source models, text model, graph, journal/canonical identity, hashes, generated modules, build, read commands, coverage, baseline/impact, exclusion, rename/move, review, check/policy, then convention and green sweeps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
… hashing, canonical JSON, findings (T1) src/core/ gains the pure foundation every later task builds on: - text.ts: the exact SPEC 1.4 whitespace/control classes and the SPEC 3 line-terminator/line model (CRLF, lone LF, lone CR; final line may lack a terminator), with exact round-trip splitting. - bytes.ts: SPEC 12.0 byte-wise case-sensitive comparison (UTF-8 byte order, not UTF-16 order), stable byte-order sorting, and exact UTF-16 index <-> UTF-8 byte-offset conversion for SPEC 1.7 source ranges. - hash.ts: SHA-256 hex with length-prefixed injective component framing (SPEC 5.5; IMPLEMENTATION "Hashing"). - canonical-json.ts: the one canonical serializer — byte-wise sorted keys, stable ordering, trailing newline (IMPLEMENTATION cross-cutting). - findings.ts: the validation-finding data model carrying SPEC 14 condition numbers 1-22 with exit class per SPEC 12.0 (14 -> 2, rest -> 1) and file/location/correction fields, rendered later by the CLI. Verified: npm run build, npm run typecheck, prettier --check src all pass; behavior exercised by a manual probe over dist/ (character-class edges incl. U+00A0/U+0085/U+2028 exclusion, mixed-terminator round-trips, framing injectivity, byte-order vs code-unit-order divergence, canonical JSON determinism, condition table). Stub CLI untouched (still exits 86; T3 retires it). T1 removed from specs/tmp/FIX_PLAN.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
src/core/glob.ts implements the exact SPEC 7 dialect — `*`, `?`, `**` over workspace-relative UTF-8 path bytes, byte-wise and case-sensitive, every other character literal, the dot-segment rule read from the pattern as written, lexical `.`/`..` resolution with outside-root detection — and SPEC 7.5 files-selector captures: $1–$9 each at most once in from, one-plus bytes within a single segment, to-expansion agreement matching captured bytes as literals, and the whole-pattern left-to-right fewest-bytes disambiguation (both acceptance examples verified). Compile errors (outside-root, duplicate capture) come back as data for 14.14 / usage-error reporting. No glob library (IMPLEMENTATION "Key libraries"). Verified: typecheck + build clean; a scratchpad probe covering every T7-4 semantics row, the SPEC 7.5 examples, and capture corners passes; 124,697-case differential fuzz against the S-6-vetted harness oracle (plain, from-captures, to-agreement) shows zero mismatches. No test/ changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…ch (T3) Retire the Phase 8 exit-86 stub. src/cli/main.ts is the (argv, cwd, stdout, stderr) -> exit code entry (IMPLEMENTATION Architecture) with bin.ts a trivial wrapper; src/cli/args.ts implements the SPEC 12.0 conventions mechanically over the SPEC 12.5 command table (review/query subcommands, per-command flag and positional arity from SPEC 6.4, 6.5, 8.2, 9, 10.7, 11): unknown commands/flags, missing required flags/arguments, invalid flag values, flag repetition, and non-UTF-8 argument values are usage errors - exit 2, diagnostic on stderr, empty stdout; --json and --config <path> are accepted by every command; --kinds takes one comma-separated value with per-subcommand kind sets; review create enforces its exactly-one-of rule and --strategy/--status value sets (SPEC 10.7). Commands whose behavior is not yet built exit 2 with an explicit "not implemented" stderr diagnostic (temporary scaffolding). Verified: build + typecheck green; manual probes - `nonsense` exits 2 with stderr text and empty stdout, no invocation exits 86 anymore; section-12.0-i and -ii now fail only at unbuilt behavior (build "not implemented"), with T12.0-4's repeated-flag arms passing under the real harness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…port defineConfig (T4)
Configuration per SPEC 7: locate xspec.config.ts by upward search from the
working directory or via --config resolved against it; parse with the
TypeScript compiler API as an AST reduced to data, never executed; enforce
the exact declarative form (one defineConfig import from "xspec",
optionally aliased; a default export of one call with a statically literal
sole argument); validate the full 7.1-7.5 schema (unknown keys, group
references and kind inference/ambiguity, empty lists, capture violations,
outside-root globs and outDir). Every violation is a condition-14 finding
reported by every command at load as a usage error (exit 2, empty stdout)
before dispatch. src/index.ts exports the typed identity defineConfig so
'import { defineConfig } from "xspec"' resolves.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…exclusions (T5) SPEC 7/7.1-7.3/13.4: src/workspace/discovery.ts walks the workspace root without following symbolic links (byte-encoded names, lstat semantics, pattern-pruned via the new CompiledGlob.mayMatchWithin); the pure classification in src/core/discovery.ts applies group globs to byte paths, excludes derived files (.xspec. names, .xspec/, enabled Markdown emit destinations) silently, and reports the path conditions as data — spec/code overlap 14.14, `#`/non-UTF-8/non-.mdx 14.19. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
src/core/source-text.ts: shared source decoding (SPEC 1.6) — BOM and
invalid UTF-8 report 14.20 with the failure's byte offset; reused later
by the TypeScript analysis.
src/core/mdx.ts: parse discovered spec sources with remark-mdx (its
grammar defines well-formed MDX; a thrown parse failure is the file's
single 14.20 with location, masking the conditions inside). Build the
per-file model: <S>/<Spec> equivalence with self-closing empty leaves
(1.1), the implicit root (1.2), the section tree with structural-path
IDs validated as segment sequences with 14.2's masking rule for the
immediate children of a section without a usable id (1.3 -> 14.1-14.3),
the exact 1.4 segment/tag character classes (-> 14.4, with a raw-source
scan for U+0000 since MDX decodes it to U+FFFD), and byte-offset source
ranges — construct spans, opening/closing tag spans, root = whole file
(1.7). Props per 2.5-2.7: coverage required/none defaulting to
required, tags whitespace-split with duplicate collapse and empty ==
omitted, only id/d/coverage/tags with no repeats or spreads, quoted
string values, braced d recorded as an expression span for the T7
analyzer (-> 14.17), and construct classification — sections,
{text(...)} embeddings, MDX comments, spec imports; other JSX,
expressions, and exports -> 14.16. Self-closing is derived structurally
(opening tag == whole construct), so spaced forms like <S id="a" / >
model correctly.
Verified: npm run build, npm run typecheck, and a 200-check functional
probe of the built model against the harness's own section-1.3, 1.4,
2.5-2.6, and 2.7 fixtures (condition multisets, byte windows, masking,
ranges, determinism) — all passing; harness untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…ic analyzer (T7) - src/core/references.ts: the shared static-reference analyzer (SPEC 2.4; IMPLEMENTATION: one analyzer for MDX expression spans and TypeScript sources) over the TypeScript compiler API — static string literal (plain quotes only), static property chain (dot / string-literal computed access), everything else dynamic with a reasoned span. - src/core/spec-references.ts: spec-module import validation (SPEC 2.1 -> 14.15, one finding per invalid import, duplicate-binding findings, poisoned-root masking per SPEC 14), d and text(...) reference extraction (SPEC 2.2/2.3 -> 14.8, arity included) with target descriptors, spellings, and byte spans for SPEC 6.4/6.5 rewriting. - src/core/mdx.ts: widen the acorn expression grammar by exactly the two rules SPEC demands parse (postfix non-null assertion -> dynamic reference 14.8; duplicate module-scope import bindings -> 14.15), so those defects report as findings, not parse failures. - package.json: acorn + acorn-jsx as direct dependencies (already transitive via remark-mdx; needed for the grammar extension). Verified: npm run typecheck clean; npm run test:self green (227); sections 2.1/2.4 still fail only with the stub not-implemented signature (observable after T17); a 60-assertion probe over the TEST-SPEC 2.1-2.4 and 14 masking fixtures passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…odel (T8) src/core/text-model.ts: SPEC 3 removal/replacement/line-drop rules over the parsed document model, and the SPEC 1.6 per-node values derived from them — subtree text (children interleaved, text(...) fully expanded across files), own text (N+1 runs joined at child excision points), and the own content sequence (replacement suspended; runs alternating with child/embedding references, embeddings counting as remaining line content). Verified against the hand-derived byte expectations of the certified section-3 and section-1.6-1.7 suites. FIX_PLAN: T8 done and removed; T8a added (T6 parser gap — two certified fixture shapes stock remark-mdx rejects, per conf-md's documented scope). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Three surgical, documented widenings of remark-mdx's grammar in src/core/mdx.ts, preserving exact source offsets (SPEC 14.20: the grammar so extended defines well-formed MDX; the toolchain stays remark-mdx): - ESM block boundary: a clone of the stock mdxjsEsm tokenizer registered ahead of it ends the block at the first line boundary where the accumulated text is a complete valid program, so an import directly followed by a non-blank line parses (T3-3 DROP_SOURCE). The addResult estree is rebased to document positions; adjacent import lines become one block per line (all consumers are per-statement). - Flat section-tag pairing: a fromMarkdown override turns every JSX tag token into an xspecJsxTag leaf, and the document builder pairs tags on a stack across construct boundaries, so a section opened with trailing same-line content may close on a later line (T3-1 gamma, section-6.5 X2) and content may directly precede a closing tag. Unmatched or mismatched tags, and all tokenize-level failures, stay 14.20-unparseable. - Section ranges now come from the exact tag tokens (the openingTagEnd scan is gone); 14.16 for foreign elements reports once per paired element with the element's range, as before. Verified: typecheck green; probes compile T3-1 REMOVALS_SOURCE/BASE and T3-3 DROP_SOURCE through the T8 text model byte-identically to the tests' hand-derived expectations, T3-4/T3-5 fixtures unchanged, X2's post-move shape parses with exact nesting, and a 22-case regression probe (structural findings, owners, T6 acorn widenings, determinism, malformed sources) passes. Harness self-tests 227/227. section-3 still fails as diagnosed pending T17 (build wiring). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…xt calls, units (T9) src/core/code-analysis.ts: per-file analysis of discovered code-group sources (SPEC 4, 4.3-4.6). Parses under the file-name-selected grammar (.tsx as TSX, else plain TS; decode/parse failure -> 14.20 with location, masking the file's inner conditions). Validates module linking (SPEC 4 -> 14.15): spec module imports with the 2.1 specifier form designating a discovered spec source, default/text bindings only (aliased, optionally type-only = type-level names), forbidden .xspec forms (static dynamic import(), export declarations, import X = require), derived-path specifiers through every linking form (13.4), and pairwise binding collisions. Extracts references with scope-aware value-level rooting via the type checker of a single-file in-memory program (shadowed/type-only roots record nothing, no condition): markers -> references edges, text(node) -> embeds edges; non-static marker/text argument -> 14.8, string text argument in TS -> 14.8, unsanctioned value uses -> 14.18, cross-module text argument -> 14.11 (static half). Attributes each reference to the innermost enclosing named code unit per the exact 4.6 construct list, dot-joined chains, 1-based @n document-order disambiguation. Records spellings and spans for the rename/move rewrites. src/core/discovery.ts: string-level companions for the import rule — canonicalOutDirPrefix (refactored out of the byte matcher), markdownEmitDestinations (SPEC 7.3/13.2), derivedFilePathKind (SPEC 13.4). Verified: npm run typecheck and npm run build clean; a 66-case driver over the compiled module reproduces the section-4.5/4.6/4/14 suite scenarios (marker/embed edges and attribution matrix, shadowing, type-only freedom, all 24 invalid-import arms, collisions, cross-module 14.11, grammar selection, masking, byte-accurate finding locations, run-twice determinism). Suite files stay red until T17 wires build. FIX_PLAN.md: T9 removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…n, cycles (T10) src/core/graph.ts: the project-wide graph over the parsed spec and code analyses (SPEC 5.1-5.3) — requirement nodes and code locations with SPEC 1.5/4.6 identities; the four edge kinds as collapsed sets (5.2); reference resolution reporting unknown d/text/TS targets (14.5-14.7) with the SPEC 14 masking rule for unparseable targets; dependency cycles over the combined contains+depends+embeds graph and spec import cycles (2.1), each reported as a 14.9 finding with the full closed cycle path (iterative Tarjan SCC + shortest-cycle extraction, byte- deterministic throughout). Finding gains an optional cycle field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…T11) Core (src/core/journal.ts): the SPEC 6.1 journal model — one entry per line, each the compact canonical JSON of a self-contained operation record (rename / move-file / move-section) plus the full identity mapping it produced, byte-deterministic with the canonical bytes as the only accepted spelling. Parsing validates every line (malformed JSON, wrong shape, impossible operations, conflicting or inconsistent mappings, non-canonical bytes) into condition-13 findings naming the line (SPEC 14.13). Canonical identities (SPEC 5.4): backward walk from the newest entry — mapping-to extends the chain, mapping-away ends it — yielding (identity, journal position), position 0 at the journal's start, so reintroduced identities start new chains and distinct nodes never hash alike; plus the SPEC 5.5 (identity, position-earliest-first) comparator and the SPEC 6.3 forward mapping for baseline replay. Workspace (src/workspace/journal.ts): load — absent file = empty journal, non-plain-file occupant (symlink included, judged by lstat, never read through) = 14.13 finding (SPEC 13.4); append — canonical line via a single O_APPEND write, creating .xspec/ on first use, refusing symlinked components and non-plain occupants. Shared helpers: FORBIDDEN_SEGMENT_NAMES moved to core/text.ts (SPEC 1.4, now shared with mdx.ts); compactJson single-line canonical rendering added to core/canonical-json.ts. Verified: build + typecheck green; a 53-check probe over serialization determinism, parse/validation (including the T6.1-3 garbage-line, directory, and symlink arms), the 5.4 walk scenarios, forward mapping, and workspace I/O all passes. section-6.1 still fails as diagnosed (build/rename arrive with T17/T26), per the plan's verification note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Add src/core/hashes.ts (SPEC 5.5): ownHash over the own content sequence with canonical-identity references (SPEC 5.4), subtreeHash over children in document order, effectiveHash with per-edge (canonical identity, effectiveHash) dependency pairs, and metadataHash over the d target set, coverage attribute, and sorted tags — all under injective length-prefixed framing with domain tags, iteratively evaluated so deep contains chains cannot overflow, total and deterministic even over invalid workspaces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…, runtime text (T13) src/core/emission.ts renders, per spec source, the generated module and its companions (SPEC 4, 4.1, 4.3, 4.4, 13.1) as pure deterministic text: - NAME.xspec.ts — header + re-export shell, so consumers' CommonJS/NodeNext extension lookup resolves ./NAME.xspec at compile time (to the shell) and at runtime (to the consumer-emitted NAME.xspec.js), while every navigable declaration stays in the declaration companion for the SPEC 4.2 declaration-map navigation T14 adds. - NAME.xspec.impl.js — plain-CJS runtime: frozen opaque node tokens (child properties by ID segment only), subtree texts in a module-private WeakMap reachable only through the text export (SPEC 4.3), owning-module tagging via Symbol.for so a cross-module text() call throws naming both modules (SPEC 4.4 → 14.11). - NAME.xspec.impl.d.ts — unique-symbol-branded readonly node interfaces: missing paths and assignments are type errors (SPEC 4.1); another module's nodes are rejected at the text argument (SPEC 4.4). Verified by a scratch end-to-end probe mirroring the certified consumer arrangement (strict NodeNext-CJS compile, plain-Node run): chains, bracket access, missing-path/readonly/cross-module type errors at the consumer reference, byte-exact subtree texts with embedding expansion, the cross-module runtime throw naming both module stems, no text observable without importing text, sectionless and non-identifier-stem sources, and run-twice byte identity — all pass. Suite section-4* files stay red until T17 wires emission into build, as planned. FIX_PLAN: T13 removed; T14 annotated with the landed architecture so the documentation layer extends it instead of redesigning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…(T14) Extend generated-module emission (SPEC 4.2): every node's own text — truncated to its first 1000 Unicode code points with … appended, each */ written *\/ — is embedded raw as a documentation comment; the comments sit as JSDoc on the type companion's navigable declarations (child property signatures, the root constant) so hover shows them, and are duplicated textually in the NAME.xspec.ts shell. A new companion NAME.xspec.impl.d.ts.map (standard v3 source map, sources naming the .mdx, plus a trailing sourceMappingURL comment) maps each declaration name to its node's <S> construct start — the root to file start — so the language service's source mapper lands go-to-definition in the source .mdx. Verified end to end against the TS language-service API (quick info, definitions, internal source mapper) with the section-4.1-4.2 fixture shapes; suite observability still gated on T17 (xspec build). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
… rules (T15) All product file writes now go through src/workspace/writes.ts: - writeDerivedFile: temp file + rename in the target's directory (IMPLEMENTATION), so a written path holds prior state or complete new content at every moment (SPEC 13.5); replaces any occupant — a symbolic link as itself, never writing through it; a directory whole (SPEC 13.4). - writeDurableFile / appendDurableFile: refuse a path occupied by anything other than a plain file (SPEC 13.4; read side reports 14.13/14.21). - symlinkWritePathFindings / symlinkComponentOf: condition-22 findings for write paths traversing a symlinked workspace-relative directory component, for refuse-before-modify and check's report-without-writing (SPEC 14.22); components above the workspace root unrestricted. - removeDerivedFile: orphan removal via recorded paths, never through a link (SPEC 13.3/13.4). - journal.ts now routes its append through the layer and shares the occupant classifier. Verified: typecheck green; direct functional probe of all layer behaviors (29/29) against dist; section-13.4 stays 6/6 red as diagnosed until T17 lands `build` (per plan). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…match (T16) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
The full SPEC 12.1 pipeline: analyzeWorkspace (src/workspace/pipeline.ts) discovers, parses, and validates spec and code sources with SPEC 14 masking (14.20 masks file internals; discovery-level 14.14 precedes all source analysis, exit 2), loads the journal (14.13), assembles the graph, and computes the four hashes. On a valid workspace, computeBuildOutputs (src/core/build.ts) derives the generated TypeScript modules (13.1), Markdown emission per markdown.outDir (3, 7.3, 13.2), graph data with the recorded derived-file set (13.3), and orphan removal via recorded paths (13.4); executeBuildOutputs (src/workspace/build.ts) writes after the SPEC 14.22 write-path check. A failed build — findings exit 1 (report on stdout, human and --json via src/cli/report.ts) or configuration error exit 2 — modifies nothing. Also harden the exit-code partition (SPEC 12.0, found by P-8): a call-stack overflow while parsing a pathological configuration or source (deep nesting towers) now reports 14.14 / 14.20 instead of escaping as an internal-error exit 70. Suite movement: section-3 (6/6), section-13.1-13.2 (3/3), and section-16-p8 (parser-robustness fuzz) fully green; T12.1-3/T12.1-4 green; harness self + certification 227/227. Remaining failures all cite commands of later tasks (check, query, ids, show, coverage, impact, review, rename, move). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
…T18) The shared SPEC 13.3 pre-answer step: prepareWorkspaceForRead (src/workspace/refresh.ts) analyzes the workspace, fails with findings (exit-1 class) on invalid sources modifying nothing, and otherwise refreshes missing/mismatched graph data — writing exactly what build would write except no TypeScript or Markdown is generated or removed and the recorded derived-file paths are left unchanged. A refused write path (14.22) fails with the finding before modifying anything. The CLI face, prepareGraphForRead (src/cli/prepare.ts), renders both failure classes once for every future consumer (ids, show, coverage, impact, review, query); check never uses it (14.10). Core rework (src/core/graph-data.ts): refreshedGraphData and graphDataMatchesCurrent now take the would-be build graph data — with no recoverable record there are no recorded paths to preserve, so a refresh from a missing store writes build's data verbatim, would-be record included (byte-identical to a real build's store, per SPEC 13.3's "exactly what xspec build would write"). Verified: build, typecheck, format clean; 17-scenario manual probe of the step through dist/ (missing store byte-identity with build, record preservation enabling later orphan removal, failed refresh modifying nothing, no-op on matching data, 14.22 refusal) all pass; section-13.3 unchanged (T13.3-4 green, T13.3-1/2/3 await the T19+ commands); section-12.1-12.2/13.1-13.2/13.4 identical to pre-change HEAD. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
SPEC 11: JSON-only output with or without --json, including the failed- refresh findings report; node/nodes/edges/subtree/ancestors/reachable over the refreshed graph (13.3 via prepareGraphForRead); conjunctive nodes filters with --group spec-group validation (wrong-kind = invalid value, 14.14) and --file outside-root usage errors; graph-node identity resolution per 1.5/4.6 with unknown paths as usage errors (12.0); reachable over dependency kinds only with one shortest witness under the 12.0 byte tie rule (core/paths.ts, reusable for coverage and impact paths). Verified: section-11 7/7 green; section-5.1-5.3 T5.2-1 green; section-5.5 T5.5-1/3/4 green; residual failures there and in section-1.5 are blocked on show/check/impact/rename/move (T20, T24, T26-T28, T35). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
- src/cli/commands/ids.ts: SPEC 12.3 — IDs grouped by file (byte order), document order within a file; --tree nesting by section structure; --file <glob> (SPEC 7 rules, outside-root pattern = usage error exit 2, checked before source analysis); --unreferenced (no incoming depends/embeds/references edges; contains never counts); restricted trees re-nest under the nearest listed ancestor or the file top level, containing exactly the listed IDs; --json per 12.0, human form with the same information. - src/cli/commands/show.ts: SPEC 12.4 — identity, source range, own and subtree text (expanded, 1.6), all four hashes, tags, coverage attribute (absent for roots), edges by kind; show --json emits the query node document exactly. - src/cli/commands/common.ts: shared helpers extracted from query.ts (usageError, emitDocument, rangeJson, edgeJson, resolveRequirementNode, nodeReportDocument) so show and query node can never drift apart. - Both answer from the refreshed graph (SPEC 13.3, cli/prepare.ts). - FIX_PLAN.md: remove T20; carry the refresh-on-read building blocks forward into T21. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Add src/core/coverage.ts — pure evaluation of one profile (SPEC 8, 8.1, 8.2): boundary sets (spec groups contribute non-root nodes, code groups their code locations), reachability over the profile's edgeKinds with every root-adjacent edge excluded, the 8.1 required set, ignored nodes with all applicable reasons in the fixed 8.2 order, and one shortest covering path per covered node via shortestWitnessPath under the 12.0 byte tie rule (virtual multi-source; direct mode accepts only single-edge results). Add src/cli/commands/coverage.ts — all profiles or one named (unknown name: usage error, exit 2), refresh-on-read via prepareGraphForRead (13.3), human and --json forms with identical information, --check exiting 1 on any uncovered required node. Wire the handler into the dispatch table and drop T21 from the fix plan. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Add src/workspace/baseline.ts (SPEC 6.3): resolve a baseline git ref to the workspace content as it stood at the ref through read-only plumbing (rev-parse, ls-tree, cat-file — src/workspace/git.ts), classify sources with the configuration at the ref, validate the baseline as a workspace (usage error naming offending files otherwise), compute baseline hashes with the baseline journal, and compute the journal replay mapping — core computeJournalReplay enforces the entry-wise prefix invariant and composes the suffix entries into a baseline-to-current identity map. Refactor the analysis pipeline behind analyzeWorkspaceContent and extract parseConfigurationBytes/journalFromBytes so the filesystem and git-tree paths share one body. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
src/core/changes.ts: pure derivation over a baseline side and the current side (graph, hashes, journal each). Nodes matched by canonical identity per side (SPEC 5.4 — equivalent to 6.3's replay forward-mapping, with 9.3's reused-identity semantics); both-sides rule enforced (added/deleted nodes are `changed` only); `changed`/`metadata-changed` from ownHash/ metadataHash comparison; `descendant-changed` attributed to the changed records strictly below on either side; `upstream-changed` derived over the matched (both-sides) child and dependency-edge relations — a sub-relation of the acyclic baseline graph — attributing each cascade to its originating nodes exactly per the SPEC 5.6 worked cascades. Verified by a manual probe over all six cascade fixtures (leaf edit, child add/remove, d-target add/remove, coverage/tags-only, multiple flags, added/deleted convention, no-edit purity) through resolveBaseline + analyzeWorkspace; section-5.6 still fails only on `impact: not implemented` (T24). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SDG initial-build PR for xspec, a requirement-traceability tool for specifications written in MDX.
Phase 2 (triage & draft): seed classified as the initial build (no prior
specs/SPEC.md); the Developer-authored seed specification is adopted as the initialspecs/SPEC.mddraft.specs/GOALS.mdfollows after explicit Developer approval, andspecs/tmp/SEED.mdis deleted once consumed. Subsequent phases (SPEC refinement, TEST-SPEC, certifications, scaffolding, harness and product implementation) continue on this branch.🤖 Generated with Claude Code
https://claude.ai/code/session_015XRjC6q66ab9mDaqgFZnDZ
Generated by Claude Code