Skip to content

Commit d97d30e

Browse files
clkaoclaude
andauthored
debrief: route split-root debriefs to the state checkout, not the definition dir (#449)
Resolve {debrief_root} from status --boot --json (entity_dir) in a new Phase-1 Step 1b and thread it through all four _debriefs/ touch-points. Split-root commits become path-scoped state-checkout commit+push with the rebase-conflict halt; an entity_dir_present==false halt-gate stops a declared-but-absent checkout before any git -C {state_checkout} op. Single-root path unchanged. Add a deterministic fixture regression guard (skills/integration) covering AC-1 (split-root: file in checkout, trunk HEAD byte-identical), AC-2 (single-root negative control), AC-3 (numbering from checkout only -> -04, orphan untouched), and AC-4 (absent-checkout halt). The guard drives the real boot record and transcribes the skill's git sequence; it is a regression guard / live-drive seed, not a substitute for the validation-stage live drive. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ef53f07 commit d97d30e

2 files changed

Lines changed: 445 additions & 5 deletions

File tree

skills/debrief/SKILL.md

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,23 @@ The user may provide a workflow directory path as an argument. If they didn't, s
2525

2626
Store the confirmed path as `{dir}`.
2727

28+
### Step 1b — Resolve the debrief home
29+
30+
The debrief home is not always `{dir}`. For a split-root workflow (its README declares a `state:` checkout) the established `_debriefs/` history and the auto-syncing convention live in the state checkout, not the definition dir on the code branch. Let the binary tell you which it is rather than re-parsing `state:` yourself:
31+
32+
1. Run `${SPACEDOCK_BIN:-spacedock} status --boot --json --workflow-dir {dir}` once and read three fields the binary already resolves: `state_backend` (`single-root` | `split-root`), `entity_dir` (the absolute resolved debrief home), and `entity_dir_present`.
33+
2. Set `{debrief_root} = entity_dir`. Use `{debrief_root}/_debriefs/` everywhere `_debriefs/` appears below.
34+
35+
- `state_backend == single-root``entity_dir` is `{dir}`; debriefs read, write, and commit under `{debrief_root}/_debriefs/` on the current branch (unchanged behavior).
36+
- `state_backend == split-root` → set `{state_checkout} = entity_dir` (`= {debrief_root}`). **Halt-gate:** if `entity_dir_present` is `false` the declared checkout is NOT materialized (an orphan state branch with no linked worktree — a fresh clone or a removed worktree). HALT, report "state not initialized," and stop. Do NOT fall back to writing into `{dir}` on the code branch. Tell the captain to run `spacedock state init` (manual fallback: `git fetch origin {state_branch} && git worktree add {state_checkout} {state_branch}`), then re-run the debrief. Otherwise the reads, the new-file write, and the commit all run in the state checkout on its own branch — never in `{dir}` on the code branch. Resolve the state branch from the checkout itself: `git -C {state_checkout} rev-parse --abbrev-ref HEAD`.
37+
38+
The debrief skill is user-invocable independent of a first-officer boot, so it cannot assume the checkout has converged — hence the explicit `entity_dir_present` gate before any `git -C {state_checkout}` operation.
39+
2840
### Step 2 — Determine session boundaries
2941

3042
Check for an existing debrief to anchor the session start:
3143

32-
1. Look for `{dir}/_debriefs/*.md` files. Sort by filename (lexicographic = chronological).
44+
1. Look for `{debrief_root}/_debriefs/*.md` files. Sort by filename (lexicographic = chronological).
3345
2. If a prior debrief exists, read the most recent one's YAML frontmatter and extract the `last-commit` field. The current session starts from the next commit after that hash.
3446
3. If no prior debrief exists, fall back: use `git log --oneline --reverse -- {dir} | head -1` to find the first-ever commit in the workflow directory, or use commits from the last 24 hours if the history is large.
3547

@@ -270,7 +282,7 @@ If `gh` is not authenticated or fails, report the error and suggest the captain
270282

271283
### Step 1 — Determine sequence number
272284

273-
Look at existing files in `{dir}/_debriefs/` matching today's date pattern `{YYYY-MM-DD}-*.md`. The sequence number is one more than the highest existing sequence for today, or `1` if none exist.
285+
Look at existing files in `{debrief_root}/_debriefs/` matching today's date pattern `{YYYY-MM-DD}-*.md`. The sequence number is one more than the highest existing sequence for today, or `1` if none exist. For split-root this counts the state-checkout debriefs only — never `{dir}/_debriefs/` — so numbering continues the established history and a same-named orphan left in the definition dir cannot perturb the sequence.
274286

275287
### Step 2 — Calculate duration
276288

@@ -286,10 +298,10 @@ Calculate the difference as a human-readable duration (e.g., `~2h30m`).
286298
### Step 3 — Write the file
287299

288300
```bash
289-
mkdir -p {dir}/_debriefs
301+
mkdir -p {debrief_root}/_debriefs
290302
```
291303

292-
Write the debrief to `{dir}/_debriefs/{date}-{sequence:02d}.md`:
304+
Write the debrief to `{debrief_root}/_debriefs/{date}-{sequence:02d}.md`:
293305

294306
```markdown
295307
---
@@ -348,13 +360,32 @@ next session", "Other backlog", "Ideation"}
348360

349361
### Step 4 — Commit the debrief
350362

363+
**Single-root** — commit on the current branch:
364+
351365
```bash
352366
git add {dir}/_debriefs/{date}-{sequence:02d}.md
353367
git commit -m "debrief: session {date} #{sequence} — {summary}"
354368
```
355369

370+
**Split-root** — commit path-scoped in the state checkout on its own branch, then push so peers see it (the state checkout is one shared, non-branched index; a bare `git add -A` / `git commit` would sweep up a sibling writer's staged entity, so name the path):
371+
372+
```bash
373+
git -C {state_checkout} add -- _debriefs/{date}-{sequence:02d}.md
374+
git -C {state_checkout} commit -m "debrief: session {date} #{sequence} — {summary}" -- _debriefs/{date}-{sequence:02d}.md
375+
git -C {state_checkout} push origin {state_branch}
376+
```
377+
378+
On a non-fast-forward push rejection, integrate peers and re-push (the single-file commit replays atop the peer's; disjoint paths → no conflict):
379+
380+
```bash
381+
git -C {state_checkout} pull --rebase origin {state_branch}
382+
git -C {state_checkout} push origin {state_branch}
383+
```
384+
385+
If the `pull --rebase` CONFLICTS, HALT: `git -C {state_checkout} rebase --abort`, report the conflicting path(s), and stop — never force-push or auto-resolve. If the checkout has no `origin` remote, commit locally and skip the push.
386+
356387
Where `{summary}` is a brief count like "8 tasks completed, 3 new filed".
357388

358389
Report the file path to the captain:
359390

360-
> Debrief written to `{dir}/_debriefs/{date}-{sequence:02d}.md` and committed.
391+
> Debrief written to `{debrief_root}/_debriefs/{date}-{sequence:02d}.md` and committed.

0 commit comments

Comments
 (0)