Investigating unexpected changes
SkillDocs & knowledgeUse when unexpected changes appear on your branch or worktree — commits you did not make, amended or force-pushed history, or a working tree that contradicts your memory — to reconstruct who did what and decide how to proceed.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Investigating unexpected changes skill
What this skill tells your AI
The instructions your AI receives, as published by scriptedalchemy/tracedecay in plugin/skills/investigating-unexpected-changes/SKILL.md and read by ahel’s review.
Parallel agents share branches and worktrees. Real sessions have hit this and
guessed: one Claude session found three of its branches amended under it and
called it "auto-merged... a repository watcher"; a Cursor session saw a test
file it "didn't write but which passes" and spent turns on blind git log
trying to explain it. Blind git archaeology cannot name the actor. TraceDecay
correlates every session to the branches, worktrees, and commits it touched, so
you can attribute the change instead of theorizing. Do that before you react.
Establish what changed
Pin the objective facts first; do not act on a hunch.
- Local ground truth:
git status,git log --oneline -20, andgit reflog -20(reflog survives amends and resets — it shows HEAD moving even whengit loglooks clean). - Semantic shape of the delta:
- Uncommitted working-tree drift →
tracedecay_commit_context(changed symbols, file roles, recent commit style) to see what moved without reading raw diffs. - Branch moved vs. where you expected → use Git's live merge-base and
git diff --name-only <base>...<head>as the file boundary, then pass those paths totracedecay_diff_context. Treattracedecay_branch_diffas a summary only after its commits/files agree with that live boundary; never act on a stale graph snapshot alone.
- Uncommitted working-tree drift →
Attribute it
Turn "what changed" into "who changed it" with the session-git correlation index.
tracedecay_sessions_for(git_ref:branch|worktree|commit,value, optionalsince/until) lists every session correlated with the artifact. Query the surprising commit sha first, then the branch or worktree if the commit is unattributed.- Read the
relationon each returned session:produced— that session made the commit (the actor you are looking for).observed— that session only saw it (a bystander, useful for timeline but not authorship).- unclassified legacy rows have no relation and still match; treat them as candidates, not proof, and corroborate with the session's messages below.
- Attribution is span-based, so a session that switched branches mid-run is
credited only for the spans it actually held — a
producedhit is trustworthy even across branch churn.
Read the acting session's context
Once you have the acting session id, recover why it made the change.
tracedecay_message_search(query, plusbranch/commitfilters, orparent_session_id) surfaces what the actor was told to do and what it reported — search the commit sha or the touched file names.tracedecay_lcm_grepwithscope: "session"and thatsession_idreturns bounded raw-message snippets for the one session;scope: "all"is the cross-session default.- Heed the
capped_sessionsdisclosure: a broad (scope: "all") grep can cap how many sessions it scans and say so. When the acting session may have been capped, rerun withscope: "session"and its id for complete results before concluding.
Decide
With the actor, their intent, and the delta in hand, choose:
- Compatible and wanted → adopt it: rebase or fast-forward onto the new HEAD and continue.
- Conflicting or unwanted → coordinate: the
producedsession id and its goal tell you whom to reconcile with rather than force-pushing over live work. - Ambiguous ownership → do not overwrite. A force-push over another agent's
producedcommit destroys unmerged work.
If a durable ownership convention emerges (for example "branch codex/* is
owned by the Codex worktree"), record it with tracedecay_fact_store so the
next session inherits it — see tracedecay:project-memory.
If tools are deferred or MCP fails
- Deferred (names listed without schemas): load once with ToolSearch —
select:tracedecay_sessions_for,tracedecay_commit_context,tracedecay_diff_context,tracedecay_branch_diff,tracedecay_message_search,tracedecay_lcm_grep(one batched call) — then call normally. - MCP error / timeout / disconnect: same tools via shell —
tracedecay tool sessions_for --args '{"git_ref":"commit","value":"<sha>"}',tracedecay tool commit_context,tracedecay tool diff_context,tracedecay tool branch_diff,tracedecay tool message_search,tracedecay tool lcm_grep(seetracedecay:using-the-cli). Never query.tracedecaydatabases directly; never fall back to blind git archaeology when the correlation index can name the actor.
Deliverable
Do not end without: the objective delta (which commits/files/symbols changed and
how HEAD moved), the attributed actor (session id + relation, or an explicit
"unattributed" when no session correlates), that session's intent from its
messages, and the chosen action (adopt / coordinate / hold). Report any
tracedecay_metrics: line.
Signals
- GitHub stars
- 73
- Forks
- 5
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
investigating-unexpected-changes- Source
- github.com/scriptedalchemy/tracedecay