gabriel / musehub public
Open #216 Enhancement
filed by gabriel human · 4 days ago · assigned to aaronrene

No persisted branch-creation provenance exists: created_by/created_at reflect the current tip commit, not who created the branch

0 Anchors
Blast radius
Churn 30d
0 Proposals
No description provided.
Activity1
gabriel opened this issue 4 days ago
gabriel 4 days ago

Found while building Episode 01 ("The Whole Workflow") demo material, alongside #215 (narrower .author fallback bug) — this is the bigger structural gap underneath it.

Confirmed via the actual storage schema: BranchMeta (muse/cli/config.py, the [branch."<name>"] section of .muse/config.toml) only ever stores four fields:

intent, resumable, remote, merge

There is no created_by or created_at field anywhere in that schema, and no other file/record in .muse/ captures "who ran muse switch -c/muse branch <name> and when" at the moment a branch is created.

What created_by in muse branch --json actually is, instead: computed fresh on every single call (branch.py:872) from whichever commit currently happens to be the branch's tip:

commit_id = _resolve_commit_id(root, b)
rec = read_commit(root, commit_id) if commit_id else None
created_by = rec.agent_id if rec and rec.agent_id else None

This is not stale creation-time data --- it is not creation-time data at all. It is "who authored the most recent commit on this branch," recomputed live. Rewrite history, fast-forward the branch, have a second person or agent commit to it, and created_by changes to match --- silently, with no indication the value ever meant something different a moment ago. The field name promises branch-creation provenance; the implementation delivers current-tip authorship. Same gap applies to committed_at in that same JSON shape --- it's the tip commit's timestamp, not the branch's creation timestamp.

Confirmed live (reproducible): created a branch as a human commit, created_by: null. Committed again as an agent (--agent-id claude-code), same branch, created_by flipped to "claude-code" on the next muse branch --json call. No branch operation happened in between --- only the tip commit's authorship changed, and the "who created this branch" field changed with it.

Suggested fix (real design work, not a quick patch): persist real creation-time provenance in BranchMeta at the moment of creation --- add created_by (handle + kind: human/agent, matching the shape muse shelf's created_by already uses --- see Episode 15's {"handle": "<name>", "kind": "human | agent"}) and created_at to the [branch."<name>"] TOML section, written once by whichever command actually creates the branch (muse switch -c, muse checkout -b, muse branch <name>) and never touched again. muse branch --json should then report both the immutable creation record and, separately and clearly labeled, the current tip's authorship --- two different facts, two different fields, not one field quietly meaning whichever one was easier to compute.

Scope note: this needs a decision on backfill behavior for existing branches created before this lands (no creation record exists for them --- fall back to the current tip-authorship behavior as a legacy shim, most likely) and on whether muse push/clone need to carry this metadata across a remote (currently BranchMeta is local-only, per-repo TOML --- unclear whether creation provenance should survive a push to MuseHub or stay local-only like intent does today).

Deferred per usual until after the season wraps.