feat: Code Domain V2 — complete 7-phase roadmap (dev → main) (#69)
* feat(phase-1): typed delta algebra — replace DeltaManifest with StructuredDelta
Implements Phase 1 of the supercharge plan end-to-end.
## What changed
**Core type system (muse/domain.py)** - Remove `DeltaManifest` entirely. - Add `InsertOp`, `DeleteOp`, `MoveOp`, `ReplaceOp`, `PatchOp` TypedDicts — each discriminated by a `Literal["op-name"]` field for mypy narrowing. - Add `StructuredDelta` — `{domain, ops: list[DomainOp], summary}`. - `StateDelta = StructuredDelta` (was `DeltaManifest`). - `MergeResult` gains `op_log: list[DomainOp]`. - `DriftReport.delta` defaults to an empty `StructuredDelta`. - `MuseDomainPlugin.diff()` gains `repo_root: Path | None = None`.
**Storage (muse/core/store.py)** - `CommitRecord` and `CommitDict` gain `structured_delta: StructuredDelta | None`. - Stored at commit time; deserialized on read for `muse show`.
**Myers LCS MIDI diff (muse/plugins/music/midi_diff.py)** — new module - `NoteKey` TypedDict as the LCS comparison unit (5 fields). - `lcs_edit_script()`: O(nm) LCS DP + traceback → `list[EditStep]`. - `extract_notes()`: MIDI bytes → sorted `list[NoteKey]`. - `diff_midi_notes()`: top-level entry point → `StructuredDelta`. - Content IDs are deterministic SHA-256 of note field tuples.
**Music plugin (muse/plugins/music/plugin.py)** - `diff()`: returns `StructuredDelta` with `InsertOp`/`DeleteOp` for file additions/removals, `ReplaceOp` for non-MIDI modifications, and `PatchOp` with note-level `child_ops` for MIDI files when `repo_root` is available. - `apply()`: handles `DeleteOp`/`ReplaceOp`/`InsertOp` in-memory; workdir path rescans as before. - `drift()`: counts op kinds instead of accessing old manifest keys.
**CLI commands** - `commit.py`: computes and stores `structured_delta` against parent. - `show.py`: displays `commit.structured_delta` with per-op lines and `PatchOp` child_summary; falls back to manifest diff for old commits. - `diff.py`: calls `plugin.diff(repo_root=root)` and prints structured output. - `status.py`: extracts added/modified/deleted sets from `delta.ops`. - `checkout.py`: extracts removed/to_restore paths from `delta.ops`.
**Tests** - `test_structured_delta.py` (new): 38 tests for all op types and plugin behaviour. - `test_midi_diff.py` (new): 29 tests for note extraction, LCS algorithm, and `diff_midi_notes()` end-to-end. - `test_music_plugin.py`: updated to StructuredDelta API. - `test_cli_plugin_dispatch.py`, `test_plugin_apply_and_checkout.py`, `test_cli_coverage_gaps.py`: updated for new delta shape.
All 456 tests green. mypy strict: 0 errors. typing_audit --max-any 0: 0 violations.
* ci: only run on PRs targeting main (dev→main gate)
* feat: code-domain semantic commands + code tour de force demo (#54)
* feat: add code domain plugin with AST-based semantic versioning
Introduces muse/plugins/code/ — a first-class Muse plugin that treats source code as a structured system of named symbols rather than lines of text.
Key capabilities ---------------- - Python AST parsing via stdlib `ast` (zero new dependencies). Every function, class, method, variable, and import becomes a named symbol with a stable content-addressed identity (SHA-256 of normalized AST). - Semantic content IDs: two functions that differ only in whitespace or comments share the same content_id; reformatting a file produces no structured delta. - Rename detection: same body_hash + different name → ReplaceOp annotated "renamed to <new>". - Move detection: same content_id at a different address across files → cross-file move annotation on the DeleteOp/InsertOp pair. - Symbol-level OT merge: two agents modifying different functions in the same file auto-merge (ops commute); concurrent edits to the same function produce a conflict at address "src/utils.py::function_name" rather than a coarse file conflict. - Language adapter protocol (LanguageAdapter) for future TypeScript, Swift, Go adapters — falls back to file-level raw-bytes tracking for unsupported file types. - Full MuseDomainPlugin + StructuredMergePlugin conformance. - 76 tests: unit (AST parser, symbol diff golden cases, cross-file move annotation), snapshot (museignore, pycache filter, stability), semantic diff (add/remove/rename/reformat functions), merge (symbol- level conflict detection), drift, schema, protocol conformance. - Registered as "code" domain in muse/plugins/registry.py.
All gates pass: mypy strict (0 errors), typing_audit --max-any 0 (0 violations), pytest (773 tests, 0 failures).
* feat: add tree-sitter multi-language support to code plugin
Extends the code domain plugin from Python-only to 11 languages using tree-sitter — the same parsing technology used by GitHub Copilot, VS Code, Neovim, and Zed.
Languages added (all backed by real CSTs, no regex): JavaScript / JSX / MJS / CJS — function, class, method extraction TypeScript / TSX — + interface, type alias, enum, abstract class Go — methods qualified with receiver type (Dog.Bark) Rust — impl methods qualified with type (Dog.bark) Java — class, interface, method, constructor, enum C — function_definition extraction C++ — + class_specifier and struct_specifier C# — class, interface, struct, method, constructor, enum Ruby — class, module, method, singleton_method Kotlin — function, class (with method nesting)
All adapters compute content_id, body_hash, and signature_id from normalized CST text, enabling rename and implementation-change detection across all 11 languages. SEMANTIC_EXTENSIONS now covers 23 file extensions.
Adds 11 tree-sitter dependencies to pyproject.toml. Includes 25 new tests covering symbol extraction, qualified name construction, rename detection, and adapter routing for every supported extension.
* feat: add code-domain semantic commands and tour de force demo
Three new CLI commands impossible in Git:
- muse symbols: list every function, class, method in a snapshot, with content hashes, kind filter, file filter, and JSON output.
- muse symbol-log <address>: track a single named symbol through the full commit DAG — creation, renames, signature changes, implementation changes, cross-file moves — including through rename events where the address itself changes.
- muse detect-refactor: scan a commit range and emit a classified semantic refactoring report: RENAME (body_hash match), MOVE (content_id match), SIGNATURE, IMPLEMENTATION.
Also adds: - docs/demo/tour-de-force-code.md: 11-act narration script for a code plugin demo — from first commit through symbol-level auto-merge, muse symbol-log, muse detect-refactor, and multi-language support. - docs/demo/README.md: demo hub presenting both the music and code demos side by side with the shared architecture explained.
All three commands pass mypy --strict, zero typing_audit violations, 797 tests green.
---------
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* feat: code domain plugin — AST-based semantic versioning (#53)
Adds muse/plugins/code/ — a first-class Muse plugin treating source code as a structured system of named symbols. Includes tree-sitter support for 10 languages, semantic content IDs, rename/move detection, symbol-level OT merge. All gates: mypy strict 0 errors, typing_audit --max-any 0, 797 tests green.
* feat(code): supercharge code plugin with 9 new semantic commands
Add a full suite of code-domain CLI commands that are structurally impossible in Git — treating the codebase as a typed, content-addressed symbol graph rather than a bag of text lines.
New shared helper: - muse/plugins/code/_query.py: symbols_for_snapshot(), walk_commits(), walk_commits_range(), flat_symbol_ops(), touched_files(), file_pairs()
New analysis commands (read-only): - muse grep: search the symbol graph by name, kind, language — not text - muse blame: per-symbol attribution — one answer per function, not per line - muse hotspots: symbol churn leaderboard — which functions change most - muse stable: symbol stability leaderboard — the bedrock of your codebase - muse coupling: semantic file co-change analysis — hidden dependencies - muse compare: deep semantic diff between any two historical snapshots - muse languages: language + symbol-type breakdown of any snapshot
New agent-scale commands: - muse patch: surgical per-symbol modification — modify exactly one named symbol - muse query: symbol graph predicate DSL (kind/language/name/file/hash)
All commands support --json for pipeline integration. All pass mypy strict, typing_audit --max-any 0, and 797 pytest tests.
Update docs/demo/tour-de-force-code.md with all 12 commands as a full paradigm-shift narrative. Update docs/demo/README.md to reflect the complete command matrix.
* feat(music): 9 new semantic commands — version control that understands music
Add a full suite of music-domain CLI commands that are structurally impossible in Git — treating MIDI files as typed, content-addressed graphs of note events rather than binary blobs.
New shared helper: - muse/plugins/music/_query.py: NoteInfo, load_track(), load_track_from_workdir(), key_signature_guess(), detect_chord(), notes_by_bar(), notes_to_midi_bytes(), walk_commits_for_track()
New analysis commands (read-only): - muse notes: Every note as musical notation (pitch, beat, duration, velocity) - muse note-log: Note-level commit history — which notes changed in each commit - muse note-blame: Per-bar attribution — which commit introduced these notes? - muse harmony: Chord analysis + Krumhansl-Schmuckler key detection - muse piano-roll: ASCII piano roll visualization with bar separators - muse note-hotspots: Bar-level churn leaderboard across all tracks - muse velocity-profile: Dynamic range, RMS, and per-dynamic-level histogram
New agent-scale commands: - muse transpose: Surgical pitch transformation — shift all notes by N semitones - muse mix: Combine notes from two MIDI tracks into a single output track
All commands support --json for pipeline integration. All pass mypy strict, typing_audit --max-any 0, 797 pytest tests green.
Add docs/demo/tour-de-force-music.md with a 9-act narrative. Update docs/demo/README.md and muse/cli/app.py to include both music and code domain commands together.
Closes #56
* fix(code): close 4 architectural gaps — validation, deps, find-symbol, temporal query (#58)
Patch syntax validation (gap 1) -------------------------------- - Add validate_source() to TreeSitterAdapter: parse content with the tree-sitter grammar for that language, walk the CST for ERROR/MISSING nodes, return a precise line-level error message. - Add validate_syntax(source, file_path) public function to ast_parser.py: dispatches to ast.parse for Python, validate_source for all tree-sitter languages, no-op for unsupported extensions. - patch.py: replace Python-only ast.parse guard with validate_syntax call. muse patch now validates syntax for all 11 supported languages before writing to disk.
muse deps (gap 2 — no dependency graph) ----------------------------------------- - New command muse/cli/commands/deps.py. - File mode: extract import-kind symbols from the snapshot for a file (what does it import?). --reverse scans all other files' import symbols for references to the target (what imports it?). - Symbol mode (address contains ::): Python-only call extraction via ast.walk on the function node, collecting ast.Call targets as callees. --reverse scans all Python files in the snapshot for callers of the bare function name. - --commit for historical snapshots; --json for pipelines.
muse find-symbol (gaps 3 & 4 — cross-branch, temporal hash search) -------------------------------------------------------------------- - New command muse/cli/commands/find_symbol.py. - Walks ALL CommitRecords in the object store (get_all_commits), sorted oldest-first, scanning InsertOps in each structured_delta. - --hash HASH: re-parses the snapshot blob for each matched InsertOp to obtain the exact content_id and filter by prefix. Finds when a specific function body first entered the repository, across every branch. - --name NAME: matches bare symbol name (exact or prefix with *). - --kind KIND: restricts to a symbol kind. - --all-branches: additionally enumerates every branch tip via .muse/refs/heads/ and checks its HEAD snapshot for current presence. - --first: deduplicate on content_id, keeping only the first appearance.
muse query --all-commits (gap 4 — temporal hash= across history) ----------------------------------------------------------------- - New --all-commits flag on the existing muse query command. - When set, walks all commits ordered oldest-first, applies the full predicate DSL against each snapshot (re-parses blobs). - Deduplicates on content_id, annotating the first commit each unique hash was seen. "hash=a3f2c9 --all-commits" answers: when did this function body first appear, and on which branch? - Mutually exclusive with --commit.
All gates: mypy strict 0 errors, typing_audit --max-any 0, 797 tests green.
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* fix(ci): run only on push to main and PRs targeting main
* fix(code): close 4 architectural gaps — validation, deps, find-symbol, temporal query
Patch syntax validation (gap 1) -------------------------------- - Add validate_source() to TreeSitterAdapter: parse content with the tree-sitter grammar for that language, walk the CST for ERROR/MISSING nodes, return a precise line-level error message. - Add validate_syntax(source, file_path) public function to ast_parser.py: dispatches to ast.parse for Python, validate_source for all tree-sitter languages, no-op for unsupported extensions. - patch.py: replace Python-only ast.parse guard with validate_syntax call. muse patch now validates syntax for all 11 supported languages before writing to disk.
muse deps (gap 2 — no dependency graph) ----------------------------------------- - New command muse/cli/commands/deps.py. - File mode: extract import-kind symbols from the snapshot for a file (what does it import?). --reverse scans all other files' import symbols for references to the target (what imports it?). - Symbol mode (address contains ::): Python-only call extraction via ast.walk on the function node, collecting ast.Call targets as callees. --reverse scans all Python files in the snapshot for callers of the bare function name. - --commit for historical snapshots; --json for pipelines.
muse find-symbol (gaps 3 & 4 — cross-branch, temporal hash search) -------------------------------------------------------------------- - New command muse/cli/commands/find_symbol.py. - Walks ALL CommitRecords in the object store (get_all_commits), sorted oldest-first, scanning InsertOps in each structured_delta. - --hash HASH: re-parses the snapshot blob for each matched InsertOp to obtain the exact content_id and filter by prefix. Finds when a specific function body first entered the repository, across every branch. - --name NAME: matches bare symbol name (exact or prefix with *). - --kind KIND: restricts to a symbol kind. - --all-branches: additionally enumerates every branch tip via .muse/refs/heads/ and checks its HEAD snapshot for current presence. - --first: deduplicate on content_id, keeping only the first appearance.
muse query --all-commits (gap 4 — temporal hash= across history) ----------------------------------------------------------------- - New --all-commits flag on the existing muse query command. - When set, walks all commits ordered oldest-first, applies the full predicate DSL against each snapshot (re-parses blobs). - Deduplicates on content_id, annotating the first commit each unique hash was seen. "hash=a3f2c9 --all-commits" answers: when did this function body first appear, and on which branch? - Mutually exclusive with --commit.
All gates: mypy strict 0 errors, typing_audit --max-any 0, 797 tests green.
* fix(ci): run only on push to main and PRs targeting main
---------
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* feat(code): add call-graph tier — impact, dead, coverage commands (#60)
Adds three new code-domain commands that unlock the full power of the call-graph foundation laid by muse deps:
muse impact <address> Transitive blast-radius analysis via BFS over the reverse call graph. Answers "if I change this function, what else could break?" — depths 1, 2, … until the closure is exhausted. Risk-level indicator (🟢/🟡/🔴).
muse dead [--kind] [--exclude-tests] Dead code detection. A symbol is a candidate when its bare name appears in no ast.Call node AND its module is not imported anywhere in the snapshot. Distinguishes definite dead (module not imported) from soft dead (module imported but function never called directly).
muse coverage <class_address> [--show-callers/--no-show-callers] Class interface call-coverage. Lists every method of a class, marks which ones are called anywhere in the snapshot, and prints a coverage percentage — no test suite required.
Shared infrastructure: muse/plugins/code/_callgraph.py — ForwardGraph / ReverseGraph types, build_forward_graph, build_reverse_graph, transitive_callers BFS. deps.py refactored to import from _callgraph.py (no duplicate AST logic).
All three commands support --json and --commit <REF>. mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* feat(code): Phase 2 — query v2 predicate grammar + muse query-history
muse query upgrades to a full v2 predicate grammar: - OR, NOT, and parenthesis grouping via recursive descent parser - New predicate keys: qualified_name, body_hash, signature_id, lineno_gt, lineno_lt (no external dependencies) - All operators: = ~= ^= $= != (>= <= for lineno) - JSON output now includes schema_version:2 wrapper and end_lineno - Backward-compatible: existing "key=value" "key~=value" still work
New module muse/plugins/code/_predicate.py: - Token → Parser → Predicate pipeline - Public API: parse_query(str | list[str]) → Predicate - Drives both muse query and muse query-history
muse query-history PREDICATE... [--from REF] [--to REF]: - Walks a commit range, accumulating per-symbol history - Reports: first seen, last seen, commit count, change count - JSON with schema_version:2 - Answers: "find all Python functions introduced after v1.0"
New store function walk_commits_between() for bounded range walking. mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
* feat(code): Phase 3 — .muse/indices/ infrastructure and muse index command
New module muse/core/indices.py: - symbol_history index: address → chronological event timeline (commit_id, op, content_id, body_hash, signature_id per event) - hash_occurrence index: body_hash → list of addresses that share it - load/save helpers for both indexes - index_info() for status reporting - All indexes: schema_version:1, updated_at timestamp, fully rebuildable
New command muse index (multi-command Typer app): - muse index status: show present/absent/corrupt status and entry counts - muse index rebuild: walk full commit history to rebuild symbol_history and/or hash_occurrence; --index NAME for selective rebuild
Design: - Indexes are derived, optional, and fully rebuildable — zero impact on repository correctness if absent - symbol_history enables O(1) lineage/symbol-log instead of O(commits) scan - hash_occurrence enables O(1) clone detection and hash= queries - Incremental updates can be wired into the commit hook in a future phase
mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
* feat(code): Phase 5 — multi-agent coordination layer
New storage layer muse/core/coordination.py: - .muse/coordination/reservations/<uuid>.json advisory symbol leases - .muse/coordination/intents/<uuid>.json declared operations - Reservation: address list + run_id + branch + TTL-based expiry - Intent: extends a reservation with operation type and detail string - All records: write-once, schema_version:1, expiry-enforced by is_active()
Six new coordination commands:
muse reserve ADDRESS... --run-id ID --ttl N --op OP Advisory symbol reservation. Warns if addresses already reserved by another agent. Never blocks — purely coordination signal.
muse intent ADDRESS... --op OP --detail TEXT --reservation-id UUID Declares a specific operation (rename/move/extract/delete/...) before executing it. Enables forecast to predict conflicts more accurately.
muse forecast [--branch B] [--json] Predicts merge conflicts from active reservations and intents. Three conflict types: address_overlap (1.0), blast_radius_overlap (0.75), operation_conflict (0.9). Uses Python call graph for blast-radius.
muse plan-merge OURS THEIRS [--json] Dry-run semantic merge plan. Classifies diverging symbols into: symbol_edit_overlap, rename_edit, delete_use, no_conflict. Reads committed snapshots — does not modify anything.
muse shard --agents N [--language LANG] [--json] Partitions the codebase into N low-coupling work zones using import graph connectivity + greedy component partitioning balanced by symbol count. Reports cross-shard edges as coupling score.
muse reconcile [--json] Reads coordination state + branch divergence, recommends merge ordering (fewer conflicts first) and integration strategy (fast-forward / rebase / manual) for each active branch.
mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
* feat(code): Phase 6 — ConflictRecord taxonomy, muse breakage, muse invariants
MergeResult v2 — ConflictRecord taxonomy New ConflictRecord dataclass in domain.py carries structured conflict metadata alongside the existing conflicts: list[str]: - conflict_type: symbol_edit_overlap | rename_edit | move_edit | delete_use | dependency_conflict | file_level (legacy) - ours_summary / theirs_summary: short change descriptions - addresses: list[str] of involved symbol addresses Added as MergeResult.conflict_records: list[ConflictRecord] (default []). Fully backward-compatible — existing callers that don't populate it continue to work; plugins that implement StructuredMergePlugin can enrich it.
muse breakage Detects symbol-level structural breakage in the working tree vs HEAD: - stale_import: imports a symbol no longer in the HEAD snapshot - missing_interface_method: class body missing methods found in HEAD Purely structural — no code execution, no type checker, no network. Operates on the committed symbol graph + current working-tree parse. Supports --language filter and --json output.
muse invariants Enforces architectural rules from .muse/invariants.toml: - no_cycles: import graph must be acyclic (DFS cycle detection) - forbidden_dependency: source_pattern must not import forbidden_pattern - layer_boundary: lower layers must not import from upper layers - required_test: public functions must have corresponding test functions Minimal built-in TOML parser — no extra dependencies. All rules run against the committed snapshot; no working-tree parsing. Creates invariants.toml if absent — guided onboarding message shown. Supports --commit REF to check historical snapshots and --json output.
mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
* feat(code): Phase 7 — semantic versioning metadata on StructuredDelta + CommitRecord
SemVerBump type alias (Literal["major", "minor", "patch", "none"])
StructuredDelta gains two optional v2 fields: sem_ver_bump: inferred impact of this delta on the public API breaking_changes: sorted list of symbol addresses whose public contract was removed or incompatibly changed
infer_sem_ver_bump(delta) → (SemVerBump, list[str]) Pure function in domain.py, domain-agnostic: delete public symbol → major + address added to breaking_changes rename public symbol → major + address added to breaking_changes signature_only change → major + breaking insert public symbol → minor impl_only (body changes) → patch metadata/formatting only → none PatchOp child_ops → recurse into children (structural)
CommitRecord gains: sem_ver_bump: SemVerBump = "none" (default for legacy + non-code) breaking_changes: list[str] = []
commit command: After computing structured_delta, calls infer_sem_ver_bump() and stores both on the delta and the CommitRecord. First commit (no parent) stays at "none" / [].
muse log: Long-form view now shows SemVer: MAJOR / MINOR / PATCH when non-none, plus first 3 breaking-change addresses ("+N more" when list is longer).
mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
* feat(code): Phase 1 — lineage, api-surface, codemap, clones, checkout-symbol, semantic-cherry-pick (#62)
Six new code-domain commands, all additive with zero schema changes:
muse lineage ADDRESS Full provenance chain of a symbol through commit history: created, renamed_from, moved_from, copied_from, modified, deleted. Rename/move detected by matching content_id across Insert+Delete pairs.
muse api-surface [--diff REF] Public API surface at a snapshot. With --diff REF shows added/removed/ changed public symbols between two commits. Public = kind in {function,class,method,...} and name not starting with _.
muse codemap [--top N] Semantic topology: modules ranked by size, import in-degree, import cycle detection via DFS, high-centrality symbols, boundary files (high fan-out, zero fan-in). Reveals codebase structure at a glance.
muse clones [--tier exact|near|both] Exact clones: same body_hash at different addresses (copy-paste). Near-clones: same signature_id, different body_hash (same contract, diverged implementation). Cluster output with member addresses.
muse checkout-symbol ADDRESS --commit REF [--dry-run] Restore a single symbol from a historical commit into the working tree. Only the target symbol's lines change; everything else is untouched. --dry-run prints the unified diff without writing.
muse semantic-cherry-pick ADDRESS... --from REF [--dry-run] [--json] Cherry-pick named symbols from a historical commit, not entire files. Applies each symbol patch to the working tree at the symbol's current location; appends at end if symbol is not in the current tree.
All six commands support --json and --commit REF (where applicable). mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* feat(code): Phase 4 — metadata_id, canonical_key, composite refactor classification (#65)
SymbolRecord gains two new fields (backward-compatible: "" for pre-v2 records):
metadata_id SHA-256 of symbol metadata that wraps the body without being part of it: decorators + async flag for Python functions, decorator list + bases for Python classes. Stubbed ("") for tree-sitter adapters — future adapters can enrich this by reading modifier/annotation nodes.
canonical_key Stable machine handle: {file}#{scope}#{kind}#{name}#{lineno}. Disambiguates overloads and nested scopes. Unique within a snapshot. Enables agent-to-agent symbol handoff without re-querying.
New classification helpers:
muse/plugins/code/_refactor_classify.py classify_exact() hash-based exact classification: rename | move | rename+move | signature_only | impl_only | metadata_only | full_rewrite classify_composite() batch heuristic classification across a set of added/removed symbols — detects extract, inline, split, merge with confidence scores and evidence RefactorClassification full typed result (to_dict() → JSON-ready)
muse detect-refactor --json now emits schema_version:2 with total count.
Python _make_*_record() helpers thread file_path and class_prefix for accurate canonical_key computation. tree-sitter TreeSitterAdapter uses scope prefix extracted from the qualified_name.
mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* feat(code): Phase 7 — semantic versioning metadata on StructuredDelta + CommitRecord (#68)
SemVerBump type alias (Literal["major", "minor", "patch", "none"])
StructuredDelta gains two optional v2 fields: sem_ver_bump: inferred impact of this delta on the public API breaking_changes: sorted list of symbol addresses whose public contract was removed or incompatibly changed
infer_sem_ver_bump(delta) → (SemVerBump, list[str]) Pure function in domain.py, domain-agnostic: delete public symbol → major + address added to breaking_changes rename public symbol → major + address added to breaking_changes signature_only change → major + breaking insert public symbol → minor impl_only (body changes) → patch metadata/formatting only → none PatchOp child_ops → recurse into children (structural)
CommitRecord gains: sem_ver_bump: SemVerBump = "none" (default for legacy + non-code) breaking_changes: list[str] = []
commit command: After computing structured_delta, calls infer_sem_ver_bump() and stores both on the delta and the CommitRecord. First commit (no parent) stays at "none" / [].
muse log: Long-form view now shows SemVer: MAJOR / MINOR / PATCH when non-none, plus first 3 breaking-change addresses ("+N more" when list is longer).
mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
* Merge PR #68 — Phase 7 semantic versioning metadata on StructuredDelta + CommitRecord
Clean merge — no conflicts. mypy: 0 errors · typing_audit: 0 violations · pytest: 797 passed.
---------
Co-authored-by: Gabriel Cardona <gabriel@tellurstori.com>
Comments
0No comments yet. Be the first to start the discussion.