gabriel / muse public
symlog-followup.md markdown
140 lines 6.9 KB
Raw
sha256:87e65c3a0f38438d20b4534feb442bd274da6a5a7f0f5f95e9c4e4dfefa86c42 feat: muse#53 item 2 — muse code blame prefers symlog journal Sonnet 5 patch 10 hours ago

muse symlog — Follow-up Items

Background

Issue #51 delivered the full symlog foundation: per-symbol journaling at commit time, muse symlog read CLI with filters, lifecycle management (expire/delete/GC), and @{N} ref resolution for muse code cat, muse symlog resolve, and muse symlog diff. All 55 test IDs (SL_01–SL_55) are green.

This issue captures the items explicitly deferred from #51 plus useful extensions that emerged during implementation.


Deferred from #51

1. Analytics commands — muse symlog coupling and muse symlog hotspots ✅ IMPLEMENTED

The live symlog journal is a rich, already-written dataset. Two analytics commands can read it in O(1) per symbol without touching commit history:

muse symlog hotspots [--top N] [--file path] [--json] — ranks symbols by churn (number of symbol-modified entries in the journal). Complements muse code hotspots (which reads commit history) with a zero-scan alternative that is always up to date.

muse symlog coupling [--file path] [--json] — finds symbol pairs that share commit IDs across their logs (i.e. they always change together). Surfaced purely from symlog data, no AST traversal needed.

2. muse blame integration ✅ IMPLEMENTED

muse blame "file.py::Symbol" currently reconstructs authorship by scanning commit history. With symlogs in place, the per-symbol change record already contains author and commit ID at each index. blame should prefer the symlog when available — O(1) per symbol instead of O(commits).

Note on command path: the actual command is muse code blame ADDRESS (same naming situation as item 7). It now prefers the symlog journal when one exists, falling back to the full BFS commit-history scan only when: no journal exists yet, --from REF is given (the journal has no concept of "as reachable from an older ref" the way the BFS walk's starting boundary does), or --kind moved/--kind signature is requested (categories the journal's created/modified/deleted/renamed classification can never produce). Rename chains are followed via the journal's own born_from pointers, matching the pre-existing rename-tracking behavior.

3. muse code narrative rewrite

muse code narrative "file.py::Symbol" generates a plain-English description of a symbol's lifecycle. It currently works from AST diffs across commits. The symlog journal is the canonical source of that history now — narrative should read from symlog entries, gaining richer metadata (operation, author, born-from chains).

4. Remote symlog sharing

Symlogs are currently local-only — they are not pushed or pulled. For teams sharing a MuseHub remote, symlogs are silently missing on clones. The correct design:

  • muse push bundles .muse/symlogs/ alongside commits.
  • muse pull merges incoming symlog entries (append-only, no conflicts).
  • muse bundle create includes symlogs in the msgpack payload.

5. Symlog entries for non-code domains — ⏸️ CONFIRMED STILL BLOCKED

The extractor returns {} for non-parseable files, so MIDI tracks, binary assets, and schema files produce no symlog entries. For music repos this is the wrong trade-off: a MIDI symbol (track::chorus) should produce a symlog entry when the Harmony domain plugin identifies a change. Deferred until the domain plugin API supports content-ID extraction for non-code artifacts.

Re-verified while clearing this backlog (not just left alone on faith): extract_symbols()/_extract_body_hashes() in muse/core/symlog.py import muse.plugins.code.ast_parser.parse_symbols directly and unconditionally — there is no MuseDomainPlugin.extract_symbols()-style dispatch hook a MIDI (or any other non-code) plugin could implement instead. The existing MIDI plugin (muse/plugins/midi/plugin.py) does have note-level content-ID concepts, but only for its own 3-way merge logic — nothing symlog could call into today. Building the generic domain-plugin symbol-extraction interface (and the MIDI-side implementation of it) is a substantial feature in its own right, not a quick add alongside this ticket's other items — genuinely still blocked, correctly left open rather than hacked around.

6. Relative time syntax (@{1.day.ago}, @{yesterday}) ✅ IMPLEMENTED

@{N} addresses work by index. Git's reflog also supports relative time syntax (HEAD@{1.hour.ago}). Symlog --since/--until cover the filtering use case, but @{1.day.ago} as a direct ref specifier is more ergonomic in agent prompts.


New items from implementation

7. muse checkout-symbol "file.py::Symbol@{N}" ✅ IMPLEMENTED

Restore a prior version of a single symbol to disk without touching any other file. The natural extension of muse code cat "addr@{N}" — cat reads, checkout restores. Critically useful for surgical recovery: "undo the change to this one function without reverting the whole commit."

Note on command path: this command already existed as muse code checkout-symbol ADDRESS --commit REF (not a bare top-level muse checkout-symbol, despite this ticket's heading) — it restores a symbol surgically into the working tree, splicing only that symbol's lines. The missing piece this item actually delivers: ADDRESS can now embed a symlog ref directly ("file.py::Symbol@{N}"), resolved via the existing resolve_symlog_addr(), making --commit optional. No new top-level alias was added — one name for one command, per workspace convention.

8. muse symlog grep PATTERN [--file path] [--json] ✅ IMPLEMENTED

Search symbol bodies across their full symlog history. Answers: "when did this symbol last contain the string deprecated?" or "which version of this function called session.add?" Reads object store bodies via resolve_symbol_body for each entry.

9. muse symlog show "file.py::Symbol@{N}" ✅ IMPLEMENTED

Convenience alias for muse code cat "file.py::Symbol@{N}" with human-focused output: operation, author, timestamp header, then the full symbol body. Useful for interactive exploration ("show me what this function looked like two changes ago").

10. muse symlog stat [--file path] [--json] ✅ IMPLEMENTED

Summary statistics for a symbol or file: total entries, operation breakdown (created/modified/deleted/renamed), most active author, first and last commit IDs, date range. Useful for code review context and agent decision-making.

11. Symlog entries for muse revert ✅ IMPLEMENTED

muse revert records a reflog entry for the branch ref move, but writes no symlog entries for the symbols it touches. A revert of a commit that modified compute_total should produce a symbol-modified: revert <commit_id> entry in that symbol's log.

12. muse symlog prune-orphans [--dry-run] [--json] ✅ IMPLEMENTED

Find symlog files whose symbol address no longer exists in the current snapshot and remove them. Analogous to muse gc for unreachable objects — keeps the .muse/symlogs/ tree clean after large-scale renames or file deletions.

File History 1 commit
sha256:87e65c3a0f38438d20b4534feb442bd274da6a5a7f0f5f95e9c4e4dfefa86c42 feat: muse#53 item 2 — muse code blame prefers symlog journal Sonnet 5 patch 10 hours ago