| name | shift-change |
| description | Live decision-review session between graveyard shifts. Compile every decision and approval currently waiting on the user — across ALL prior shifts, not just the latest — walk them together, and RECORD each outcome onto GitHub as shaped permission rather than executing it live (execution is the graveyard's job; building/merging mid-meeting just makes the user wait). Reactions are cues to capture; even approvals are deferred to the next graveyard. End by publishing the report and — with standing permission — launching that graveyard shift. |
Shift Change
The daytime counterpart to graveyard-shift, and the other half of the primary development loop:
shift change (live, short, user-attention-dense) → graveyard shift (autonomous, long, user-attention-free) → repeat.
Graveyard shifts maximize what gets built while the user is away. Shift change maximizes what the user's scarce live attention resolves: the decisions, approvals, and live verifications that only they can do. The loop is efficient precisely because each side stays in its lane — the graveyard never waits on the user, and the user never spends live time on things the graveyard could have done.
The spine: write it up, don't execute it
A shift change converts live decisions into written, shaped GitHub permission. The graveyard executes them — not this session. This is the load-bearing rule and the one most easily broken. When the user approves something during the walk, the action you take is to record that approval onto the issue (a decision comment, a ready/greenlit signal, a reshaped body) so the next graveyard can execute it without them. You do not build it, open the PR, run the review loop, or merge it here.
Why: executing live makes the user wait between decisions. The whole value of a live session is decision density — walking many forks quickly while their attention is here. The moment you drop into an implement→test→review→merge grind, the meeting stalls behind one item and the other decisions don't get made. The user's time is for deciding; the graveyard's time is for doing. (This rule was written from a real failure: a session took the user's greenlights as live commands, spent the meeting building and merging, and made the user wait through execution that belonged overnight.)
The only things that actually happen during a shift change:
- Read-only investigation that informs a decision (read the code, check state, verify an assumption) — fast, in service of the call being made.
- Live verification that needs the user's eyes/hands (driving a running build) — see that section below.
- Writing decisions onto GitHub — comments, new issues, labels, reshaped bodies,
shape-an-epic. This is the session's actual output.
- A genuinely explicit now-imperative ("do this right now, I'm watching", "I need this merged this second") — rare, and narrow.
Everything else — every "build it / ship it / just do it / merge it" said about a backlog item while planning — is an approval to record and defer, not a command to execute now.
The agenda: current state, not the latest shift
Open by compiling everything currently waiting on the user, swept from reality — never from memory of what the last shift produced:
gh pr list --draft and open agent-authored PRs (each is a parked decision)
- The most recent graveyard brief's decision section — and anything it carried forward
- Issues explicitly awaiting the user (a fork posted as a proposal comment, an approval gate)
- Queued live verifications (changes that need the user's eyes/hands on the running app)
Present it as one screen, each item with its age. An item waiting since three shifts ago is the most important line, not a stale footnote — old pending fixes are why the user keeps re-hitting bugs that "were already fixed." Hiding the ball — surfacing only the newest shift's output — is this skill's named failure mode.
Also sweep the running register — but surface it as context, not agenda. Before the walk, read gh issue list --label running (the live cross-shift jobs a prior shift or an earlier live session launched — a long eval, a training run, a remote agent, a background build; entry shape in docs/knowledge-homes.md → "The running register"). Mirror the graveyard-shift start-of-shift sweep, but for the opposite purpose: the graveyard reads running to avoid colliding with held resources; the shift-change reads it to keep those jobs out of the decision queue. Surface each as an in-flight actor with age — "eval #37 running 4h, holds the GPU, ETA ~2 of 3" — sitting alongside the agenda as live context, explicitly NOT as a decision awaiting the user. A still-running job is not a fork: there is nothing to approve, reshape, or reject, so filing it as a waiting-on-you item is exactly the noise this skill strips. It matters only so the user isn't surprised by held hardware or a job in motion, and so the walk doesn't misread it as a stalled decision. (One exception: if its heartbeat has gone stale past the threshold, that is a real item — "job #N looks dead, reap it?" — because reaping is a confirmed decision per the register's lifecycle.)
Cues, not actions
The core behavioral rule of a live session. The user's reactions are cues — invitations to explain, capture, and queue — not commands to execute. Jumping to action on a reaction fragments the conversation the user is trying to have, takes the decision out of their hands, and spends agents on something that may not be the priority.
| The user says... | It is... | You do... |
|---|
| "What the fuck?" / "I thought we fixed this" | A request for explanation | Explain the state in words: what happened, where the fix lives, why they're still hitting it. Then ask what they want done. |
| "This is broken" / hits a bug mid-session | A capture cue | File (or find) the GitHub issue, add it to this session's decision list, continue the walk. |
| "That's annoying" / "not what I need" about a built thing | A design cue | Record the reaction on the PR/issue; queue the reshape question for this session's list. |
| "Build it" / "ship it" / "just do it" / "merge it" about a backlog item | An approval to record | Record the greenlight on the issue (decision comment + ready/greenlit signal; reshape the body if needed) so the next graveyard executes it. Do NOT build/merge it live. |
| "Do it right now" / "I'm watching" / "I need this merged this second" | A live imperative | Act now — genuinely urgent or needs their presence. Narrow; don't stretch a backlog approval into this. |
| "Go do the next graveyard shift" / the meeting wraps | The handoff/release | Launch it (see end state below). |
The test before launching any agent or making any change mid-session: did the user issue a now-imperative, or approve/react to a backlog item? A backlog approval gets recorded and deferred; a reaction gets words and a queue entry; only an explicit now-imperative gets executed live. When in doubt, it was an approval-to-record — write it onto the issue and let the graveyard run it. The tell for a true live imperative is time pressure or presence ("right now", "while I'm here", "I need to see it") — not mere assent ("yeah, build that"). (Background work already in flight is fine to keep running and report on; the rule governs starting new work off a cue.)
This inverts the graveyard's "default to shipping" rule — deliberately. Overnight, asking is the failure mode; live, jumping is. The session's whole purpose is to put decisions in front of the user, so taking one away from them mid-discussion defeats it.
Live verification happens here
Serial app/desktop driving can't parallelize (one window, one set of hands) and is exactly what live time is for. Get builds up proactively: if the agenda includes draft PRs needing live tests, have the right build compiled and running before the user asks "is there a build for me?" When multiple drafts sit on different branches, sequence them — one binary at a time — and announce each build's SHA + branch label.
Outcomes land on GitHub before the session ends
Every item walked gets its durable state updated during the session, not batched to later. But "updated" means the decision is recorded, not the work is done — execution is the graveyard's job (see the spine above):
- Approved → record the greenlight on the issue/PR (decision comment +
ready/greenlit signal) so the next graveyard merges/builds it. Do NOT merge or build it live (unless it's an explicit now-imperative per the table).
- Rejected → close the PR/issue with the reason as a comment.
- Reshaped → edit the issue body to the new shape; the next graveyard picks it up correctly.
- New cue captured → a new issue, filed before the conversation moves on, shaped enough that a graveyard worker can execute it without the user.
The chat is disposable; GitHub is the record. A decision the user made out loud that never reached the issue will be lost and re-asked — the most expensive possible waste of the session. The second-most-expensive waste is executing that decision live instead of recording it — it stalls the meeting behind one item. Record, defer, keep walking.
Close out the brief you worked
The brief is a conversation object, not a write-once log — the agenda you walked came out of a specific Notion brief, and that brief should show how the conversation ended. Once you've extracted everything you needed from a brief and landed its outcomes on GitHub, close it out before moving to the next brief:
printf '## What we did (%s)\n\n- ...\n' "$(date +%F)" > /tmp/closeout.md
python3 ~/.config/ai-briefs/notion_briefs.py append <brief-url> --file /tmp/closeout.md --divider
python3 ~/.config/ai-briefs/notion_briefs.py set-status <brief-url> --status Done
The lifecycle is In Progress → Ready → (Superseded | Done) (see ~/.config/ai-briefs/README.md). After the closeout footer, pick the retiring status by where the work went:
- Done — the thread is genuinely finished: its decisions are resolved/acted on and nothing carries forward. "Done, here's how."
- Superseded — the work lives on somewhere else, so this page is now just history: (a) a newer report of the same kind replaced it with open items carried forward, or (b) a strategy
Brief graduated into a tracked GitHub epic — its decisions now live in issues, so the brief is no longer the source of truth. This is the common ending for a big topic Brief: once you've turned its agreed to-dos into issues (the whole point of shift-change — "the deliverable of a decision is an issue"), append a closeout pointing at the epic and flip the brief Ready → Superseded. Don't leave it Ready — a brief lingering Ready after its epic exists is the stale-Ready smell, the reason a later "what should I have open?" review finds four Ready docs that are really one live decision plus three graveyards.
The footer + status flip are what let you move to the next brief without losing the thread. If a brief is still mid-work, leave it In Progress (the visible "still being worked" signal); only retire it (Done or Superseded) when it's truly closed out.
End state: cue the next graveyard
The session is done when the waiting-on-user list is empty (each item resolved, or explicitly deferred with that recorded on the issue). Close with a one-screen wrap:
- What was decided and where it landed
- What's now unblocked
- Publish/update the Notion report so it reflects the new state — that report is the baseline for the next shift-change conversation. Structure it decisions-first: the open 🟥/🟢 decisions sit at the very top, above the fold, above any shipped/status recap — the reader opens it to find what needs their call, and a decision buried below a done-log is a decision they'll miss (see
~/.config/ai-briefs/README.md → Structure: lead with the decisions).
Then run. The user has granted standing permission: when a shift-change conversation wraps, you are released to launch the next graveyard shift without waiting for a fresh one-word cue. Don't end on "say the word and I'll run" — end on "everything's recorded; I'm running the next graveyard now (stop me if you'd rather I didn't)," then launch it. The release is the natural close of the loop: discuss → write up → run → report → discuss again. (If the user has explicitly gated graveyard work — paused Codex, capped the budget, said "not tonight" — honor that gate instead and say what's queued for when it lifts.)
The groomed, GitHub-resident backlog is the handoff artifact. The next graveyard shift needs nothing from this chat because everything it needs is on the issues — which is exactly what lets you be released to run it immediately.
When NOT to use this skill
- The user wants to deep-dive one feature or bug live — just work it synchronously; don't force the agenda walk.
- Nothing is waiting on the user — say so in one line and offer to start the next graveyard shift directly.
- Mid-graveyard (user still away) — that's the other skill's territory.