Timeline Manager — ultrathink
Overview
Manage the branching decision timeline that tracks every audit, fork, merge, and rollback in a BoardClaude project. The timeline makes strategic decisions visible: which approaches were tested in parallel, which won, and why. Every meaningful choice becomes a node in a horizontal tree, backed by git worktrees for isolated experimentation.
The timeline is the visual heart of BoardClaude. It tells the complete story of how a project evolved through structured experimentation rather than linear guessing.
Prerequisites
- •Git repository initialized: !
git rev-parse --is-inside-work-tree 2>/dev/null || echo "NOT A GIT REPO" - •BoardClaude state dir: !
ls .boardclaude/state.json 2>/dev/null || echo "NOT FOUND" - •Current branch: !
git branch --show-current 2>/dev/null - •Active worktrees: !
git worktree list 2>/dev/null
Operations
FORK — Create a Strategy Branch
Create an isolated worktree to test a hypothesis without affecting the main branch.
Steps:
- •Validate inputs: Require a branch name and hypothesis description
- •Create git worktree:
bash
BRANCH_NAME="bc/$1" WORKTREE_PATH=".boardclaude/worktrees/$1" git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME"
- •Copy
.boardclaude/config to the new worktree (panels, agent definitions — NOT audit history):bashcp -r panels/ "$WORKTREE_PATH/panels/" cp -r agents/ "$WORKTREE_PATH/agents/" mkdir -p "$WORKTREE_PATH/.boardclaude/audits"
- •Initialize worktree state: Create a fresh
state.jsonin the worktree with the fork metadata:json{ "project": "<project name>", "panel": "<active panel>", "branch": "bc/<branch-name>", "audit_count": 0, "latest_audit": null, "latest_score": null, "score_history": [], "forked_from": { "branch": "<source branch>", "audit_id": "<latest audit id at fork time>", "commit": "<git commit hash>", "score": <score at fork time> }, "worktrees": [], "status": "active" } - •Record fork event in the source branch's
timeline.json:json{ "id": "fork-<timestamp>", "type": "fork", "branch": "<source branch>", "timestamp": "<ISO 8601>", "hypothesis": "<what is being tested>", "children": [], "parent": "<latest audit id>", "to_branch": "bc/<branch-name>", "worktree_path": ".boardclaude/worktrees/<name>" } - •Update source
state.json: Add the new worktree to theworktreesarray and record it inbranches:json{ "branches": { "bc/<branch-name>": { "forked_from": "<source branch>", "forked_at": "<audit id>", "status": "active", "hypothesis": "<what is being tested>", "latest_audit": null, "worktree_path": ".boardclaude/worktrees/<name>" } } } - •Report: Tell the user the worktree path and how to start working in it
COMPARE — Side-by-Side Branch Evaluation
Load audit results from two or more branches and produce a detailed comparison.
Steps:
- •
Load audit results from each branch:
- •Read each branch's
.boardclaude/state.json(or the worktree's state) - •Load the latest audit JSON from each branch's
.boardclaude/audits/ - •If a branch has no audits yet, prompt the user to run an audit first
- •Read each branch's
- •
Produce side-by-side score comparison:
code┌──────────────────────────────────────────────────────────────┐ │ Branch Comparison: <comparison id> │ ├─────────────┬──────────────────┬────────────────────────────┤ │ Agent │ <branch A> │ <branch B> │ ├─────────────┼──────────────────┼────────────────────────────┤ │ Boris │ XX (+/-delta) │ XX (+/-delta) │ │ Cat │ XX (+/-delta) │ XX (+/-delta) │ │ ... │ ... │ ... │ ├─────────────┼──────────────────┼────────────────────────────┤ │ COMPOSITE │ XX.X │ XX.X │ └─────────────┴──────────────────┴────────────────────────────┘
- •
Calculate per-agent deltas: For each agent, compute the score difference between branches and relative to the fork point (the last audit on the source branch before forking)
- •
Identify which branch wins on each dimension:
- •Mark the winner per agent with an indicator
- •Note dimensions where the difference is within noise range (<3 points)
- •Highlight dimensions where one branch has a decisive advantage (>10 points)
- •
Produce recommendation:
- •Overall winner based on composite score
- •Key differentiator (which agent/dimension swung the result)
- •Risk analysis (does the winner have any critical issues the loser does not?)
- •Recommended action: merge winner, continue experimenting, or hybrid approach
- •
Save comparison to
.boardclaude/audits/compare-{timestamp}.json:json{ "comparison_id": "compare-<timestamp>", "timestamp": "<ISO 8601>", "branches": [ { "name": "<branch A>", "audit_id": "<audit id>", "composite": <score>, "agent_scores": { "<agent>": <score>, "..." : "..." } }, { "name": "<branch B>", "audit_id": "<audit id>", "composite": <score>, "agent_scores": { "<agent>": <score>, "..." : "..." } } ], "deltas": { "<agent>": <branch_a - branch_b>, "..." : "..." }, "winner": "<branch name>", "key_differentiator": "<explanation>", "recommendation": "<merge | continue | hybrid>" }
MERGE — Integrate Winning Branch
Merge the winning worktree branch into the target branch (usually main).
Steps:
- •Validate: Confirm the branch to merge exists and has at least one audit
- •Merge the git branch:
bash
git checkout <target-branch> git merge "bc/<branch-name>" -m "merge(bc/<branch-name>): score XX.X, <key differentiator>"
- •Archive losing branches — do NOT delete them, they are data:
- •Update their status to
"abandoned"instate.json - •Record the abandonment reason (from comparison data)
- •Remove their worktree directories:
bash
git worktree remove ".boardclaude/worktrees/<losing-branch>"
- •Update their status to
- •Log merge event in
timeline.json:json{ "id": "merge-<timestamp>", "type": "merge", "branch": "<target branch>", "timestamp": "<ISO 8601>", "merged_branch": "bc/<branch-name>", "score_delta": "+/-XX.X composite", "parent": "<winning branch's latest audit id>" } - •Update losing branches in
timeline.json— set their status:json{ "id": "<losing branch audit id>", "status": "abandoned", "abandon_reason": "<from comparison recommendation>" } - •Clean up: Prune stale worktree references:
bash
git worktree prune
- •Report: Show the merge result, updated score, and cleaned-up branches
ROLLBACK — Revert to a Previous Audit State
Roll back to a known good state when an experiment goes wrong.
Steps:
- •Create a new branch from the target audit's commit (do NOT use
git reset --hard):bashAUDIT_COMMIT=$(jq -r '.nodes[] | select(.id == "<audit-id>") | .commit' .boardclaude/timeline.json) git worktree add ".boardclaude/worktrees/rollback-<audit-id>" -b "bc/rollback-<audit-id>" "$AUDIT_COMMIT"
- •Restore
.boardclaude/state.jsonfrom the target audit point - •Log the rollback event in
timeline.json:json{ "id": "rollback-<timestamp>", "type": "rollback", "branch": "<current branch>", "timestamp": "<ISO 8601>", "target_audit": "<audit-id>", "reason": "<user-provided reason>", "parent": "<current latest audit>" } - •Run a fresh audit on the restored state to confirm scores match expectations
State Files
.boardclaude/state.json
Tracks the current project state, audit history, and active branches.
{
"project": "<project name>",
"panel": "<active panel name>",
"branch": "<current git branch>",
"audit_count": 5,
"latest_audit": "audit-20260212-143022",
"latest_score": 87,
"score_history": [44, 58, 72, 81, 87],
"current_audit": {
"id": "<audit id or null>",
"state": "<IDLE | INGEST | PANEL_AUDIT | SYNTHESIZE | REPORT | COMPLETE>",
"started_at": "<ISO 8601 or null>",
"panel": "<panel name>",
"branch": "<branch>",
"commit": "<git commit hash>"
},
"branches": {
"bc/<branch-name>": {
"forked_from": "<source branch>",
"forked_at": "<audit id>",
"status": "<active | merged | abandoned>",
"hypothesis": "<what was being tested>",
"latest_audit": "<audit id or null>",
"worktree_path": "<path or null if removed>"
}
},
"worktrees": ["<list of active worktree paths>"],
"status": "<active | idle>"
}
.boardclaude/timeline.json
Append-only event log that forms the branching tree visualization.
{
"nodes": [
{
"id": "<unique id>",
"type": "<audit | fork | merge | rollback>",
"branch": "<git branch>",
"timestamp": "<ISO 8601>",
"parent": "<parent node id or null>",
"commit": "<git hash, for audit nodes>",
"scores": { "<agent>": "<score>" },
"composite": "<number, for audit nodes>",
"label": "<human-readable description>",
"status": "<active | merged | abandoned, for audit nodes>",
"abandon_reason": "<string, for abandoned nodes>",
"hypothesis": "<string, for fork nodes>",
"children": ["<child node ids, for fork nodes>"],
"to_branch": "<target branch, for fork nodes>",
"merged_branch": "<branch that was merged, for merge nodes>",
"score_delta": "<string description, for merge nodes>",
"target_audit": "<audit id, for rollback nodes>",
"reason": "<string, for rollback nodes>"
}
]
}
Node types and their required fields:
| Field | audit | fork | merge | rollback |
|---|---|---|---|---|
| id | required | required | required | required |
| type | "audit" | "fork" | "merge" | "rollback" |
| branch | required | required | required | required |
| timestamp | required | required | required | required |
| parent | required | required | required | required |
| commit | required | - | - | - |
| scores | required | - | - | - |
| composite | required | - | - | - |
| label | required | - | - | - |
| status | optional | - | - | - |
| hypothesis | - | required | - | - |
| children | - | required | - | - |
| merged_branch | - | - | required | - |
| score_delta | - | - | required | - |
| target_audit | - | - | - | required |
| reason | - | - | - | required |
Timeline Visualization Data
The timeline JSON is designed to be consumed by the dashboard's TimelineTree component:
- •Main branch runs horizontally left-to-right
- •Fork nodes branch downward, creating parallel tracks
- •Audit nodes are circles with score-based coloring:
- •Red: composite < 55 (FAIL)
- •Yellow: composite 55-69 (MARGINAL)
- •Green: composite 70-84 (PASS)
- •Blue: composite >= 85 (STRONG_PASS)
- •Merge arrows point from the winning branch back to main
- •Abandoned branches are greyed out with the abandon reason on hover
- •Each audit node shows a mini radar chart on hover
Error Handling
- •No git repo: Refuse to fork/merge. Timeline-only operations still work.
- •Dirty working tree: Warn before fork. Require clean state for merge.
- •Merge conflicts: Report the conflict, do NOT auto-resolve. Let the user decide.
- •Missing worktree: If a recorded worktree path does not exist, update state to reflect removal.
- •Orphaned branches: On any operation, check for branches in state that no longer exist in git and mark them as abandoned.
Worktree Cleanup
Periodically clean up stale worktrees to prevent disk bloat:
# List all worktrees git worktree list # Remove a specific worktree git worktree remove ".boardclaude/worktrees/<name>" # Prune stale references git worktree prune # Delete the git branch after worktree removal (optional) git branch -d "bc/<name>"
Always archive before removing — the audit data from abandoned branches is valuable for the timeline visualization and for understanding what approaches were tried.