feat: HC-113 — hypercode diff (semantic IR diff)#25
Conversation
…nal)
New command: hypercode diff <old.ir.json> <new.ir.json> [--format text|json].
Computes the affected-node set between two hypercode.ir/v2 documents:
- hash-driven traversal — a subtree with an unchanged hash is skipped
wholesale, so cost is proportional to the change, not the tree; a
provenance-only change (different rule, same value) is invisible by design
- nodes matched by selector identity (type[.class][#id], source order
disambiguates duplicates); added/removed/reordered children reported
- property changes carry reasons: old/new value plus the old/new winning rule
("was: APIServer > Listen @ service.hcs:26 / now: … @ edited.hcs:26")
- --format json emits hypercode.diff/v1 — the machine-readable feed for
incremental regeneration; exit code is diff-like (0 identical, 1 changed)
- rejects IR v1 with a clear re-emit hint
Plumbing: hand-rolled Foundation-free JSON parser (house style; numbers kept
as raw lexemes so 2^53+1 comparisons stay exact — lesson from the #23 review),
IRDocument read-back model, IRDiffer + text/JSON renderers.
15 new tests (diff semantics incl. hash short-circuit and provenance
invisibility, parser round-trip/escapes/malformed, rendering) — 107 total.
Docs: Usage.md §6 with real output, README CLI block, workplan HC-113 done,
codegen-demo cross-link.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cc436644b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Schema/hypercode-diff-v1.schema.json — the diff output format is a cross-implementation contract like the IR schemas; CI now diffs the example IR against an edited spec and ajv-validates the result - DocC catalog: pipeline updated to v2 + explain/diff, CLI list current, Topics sections for Contracts, Explain and Semantic diff symbols - RFC §9.7: hypercode diff named as the shipped affected-node command; 0.2 changelog entry gains HC-113 - Usage.md: header pipeline shows diff; §6 links the schema - README: diff schema linked alongside the IR schemas Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…chain The old text was built on the deprecated "executable architecture language" framing (explicitly deprecated in DOCS/Positioning.md): a runtime that drives execution, @profile/@tenant/@feature directives that don't exist, and enabling/disabling of paths that was never implemented. Now aligned with RFC 0.2 and reality: - the one-sentence formula (context-resolved specification layer) and the "CSS for application structure" mental model - real .hcs syntax: selectors, @Dimension[value] contexts, @contract blocks - the asymmetric-cascade safety lock (values cascade, contracts narrow) - the resolved IR v2 as the consumer contract (typed values, provenance, contracts, Merkle node hashes) - the actual toolchain table (resolve/validate/explain/emit/diff/lsp) - review compression + the runnable codegen demo; explicit binding time, runtime resolver out of scope per RFC §9.8 - "what it is not" distilled from Positioning.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Review follow-up on #25: - JSONParser numbers now follow RFC 8259 exactly: no '1.', '1e', '.5', leading zeros or non-ASCII digits. diff reads arbitrary files from disk, so the boundary is strict. - Unreadable or non-v2 input exits 2 (GNU diff 'trouble'), no longer conflatable with exit 1 'documents differ' in a CI gate. - The content-only comparison is now explicit: schema description and Usage §6 state that context/resolver metadata never participates, and the text renderer prints a note when the two contexts differ. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds HC-113 semantic diffing for hypercode.ir/v2 documents, enabling generators/CI to compute an affected-node set (hash-driven) with property-level reasons and an optional machine-readable feed.
Changes:
- Introduces
Sources/Hypercode/Diff/with a Foundation-free JSON parser, IR v2 read-back model (IRDocument), semantic differ (IRDiffer), and text/JSON renderers. - Adds
hypercode diff <old.ir.json> <new.ir.json> [--format text|json]to the CLI with diff-like exit codes (0/1/2). - Adds
hypercode.diff/v1JSON Schema, updates docs, and extends CI to validate diff output against the schema.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| workplan.md | Marks HC-113 as completed with scope details. |
| Tests/HypercodeTests/IRDiffTests.swift | End-to-end tests for diff semantics, parser behavior, and renderers. |
| Sources/HypercodeCLI/main.swift | Adds diff subcommand, argument parsing, exit code conventions, and context-note behavior. |
| Sources/Hypercode/Documentation.docc/Hypercode.md | Documents the new diff capability and public APIs/types. |
| Sources/Hypercode/Diff/JSONValue.swift | Adds JSONValue, JSONParser, and JSONError (Foundation-free, exact number lexemes). |
| Sources/Hypercode/Diff/IRDocument.swift | Adds IR v2 JSON read-back model used by the differ. |
| Sources/Hypercode/Diff/IRDiffer.swift | Implements hash-short-circuit tree diff + text/JSON renderers (hypercode.diff/v1). |
| Schema/hypercode-diff-v1.schema.json | Defines the machine-readable diff feed schema. |
| RFC/Hypercode.md | Updates RFC narrative to include hypercode diff and hypercode.diff/v1. |
| README.md | Adds hypercode diff to top-level CLI usage and schema links. |
| OVERVIEW.md | Updates conceptual overview to include diff in the toolchain story. |
| Examples/codegen-demo/README.md | Mentions hypercode diff as the productized hash comparison. |
| DOCS/Usage.md | Adds a new section documenting hypercode diff behavior, formats, and exit codes. |
| .github/workflows/swift.yml | Adds CI step to emit a diff and validate it against the new schema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…, reject raw control chars - Duplicate same-label siblings now pair by content hash first inside their label group, falling back to source order. A duplicate that merely moved reports as childrenReordered instead of two spurious property modifications — the invalidation feed no longer marks untouched modules stale on a pure swap. - JSONParser.parseString rejects unescaped U+0000…U+001F (RFC 8259 §7), matching the strict number grammar; \r\n is caught despite being a single Swift Character. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
The last piece of the M8 P0/P1 feature set:
hypercode diff <old.ir.json> <new.ir.json>— the invalidation signal for incremental regeneration, as a first-class compiler command.type[.class][#id]); added, removed and reordered children reported distinctly.--format jsonemitshypercode.diff/v1for generators; exit code isdiff-like (0 identical / 1 changed) for CI gates.Plumbing: hand-rolled Foundation-free JSON parser (house style — lexer/reader/emitter are all hand-rolled), with numbers kept as raw lexemes so
2^53+1comparisons stay exact (the lesson from the #23 review applied preemptively).IRDocumentread-back model +IRDiffer+ renderers inSources/Hypercode/Diff/.Stacked on #24. With this PR the release train is complete: explain (#21), IR v2 (#19/#20), contracts (#22), value validation (#23), codegen demo (#24), diff (#25) — all of M8 P0 plus HC-113 and HC-124.
Test plan
🤖 Generated with Claude Code