From 4e719ee6bd2edbf7926be41338d58740407aa395 Mon Sep 17 00:00:00 2001 From: prode Date: Mon, 8 Jun 2026 21:24:33 -0300 Subject: [PATCH] feat(baseline): clear context and branch-first at spec boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fold two spec-boundary discipline steps into the shipped baseline templates: - /clear at each feature/spec boundary — start a spec on a clean context and reset once its PR ships; the Stop hook nudges when a spec's tasks are all checked. - Branch-first before implementation — git switch -c / (kebab case), enforced by the PreToolUse hook blocking commit/push on the default branch. Updates the CLAUDE.md workflow, the SDD guide loop, the wf-development agent, and the test-before-stop / block-destructive hooks. No spec — direct workflow adjustment requested by the user. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../templates/agents/wf-development.md.tmpl | 17 +++++++++++------ .../templates/guides/claude-code-sdd.md.tmpl | 3 ++- .../templates/hooks/block-destructive.sh.tmpl | 15 +++++++++++++++ .../templates/hooks/test-before-stop.sh.tmpl | 15 +++++++++++++++ .../templater/templates/root/CLAUDE.md.tmpl | 10 ++++++---- 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/internal/templater/templates/agents/wf-development.md.tmpl b/internal/templater/templates/agents/wf-development.md.tmpl index 3071dc2..9c630be 100644 --- a/internal/templater/templates/agents/wf-development.md.tmpl +++ b/internal/templater/templates/agents/wf-development.md.tmpl @@ -40,18 +40,23 @@ The `dev-*` skills below fill only the gaps BMAD covers that csdd did not. ## Operating procedure -1. **Confirm the entry gate.** Run `csdd spec status `. Do not start - architecture unless the requirements phase is approved. If it is not, send the - user back to `wf:product/discovery` → `discovery-handoff`. +1. **Confirm the entry gate on a clean context.** Run `/clear` before starting a + new feature, then `csdd spec status `. Do not start architecture + unless the requirements phase is approved. If it is not, send the user back to + `wf:product/discovery` → `discovery-handoff`. 2. **Run phases in order, gating each.** Architecture must be approved before stories; stories before readiness; readiness must be PASS before the first `tdd-cycle`. State the gate result before advancing. -3. **Drive implementation through `tdd-cycle`**, one task at a time, updating - `sprint-status.yaml` as tasks move. Never batch tasks "to save time". +3. **Branch, then drive implementation through `tdd-cycle`.** Before the first + task, create the feature's branch — `git switch -c /` in + kebab-case (`feat/` feature, `fix/` bugfix, `chore/` small adjustment; also + `refactor/` `docs/` `test/` `perf/`). Then run `tdd-cycle` one task at a time, + updating `sprint-status.yaml` as tasks move. Never batch tasks "to save time". 4. **Review every slice** with `code-reviewer` (and `security-reviewer` when auth / secrets / input handling is touched). Resolve blockers before the next task. 5. **Close the epic** with `dev-retrospective` and feed durable lessons back into - steering. + steering. Once the feature's PR ships, run `/clear` before the next feature so + context does not accumulate across specs. ## Gotchas diff --git a/internal/templater/templates/guides/claude-code-sdd.md.tmpl b/internal/templater/templates/guides/claude-code-sdd.md.tmpl index 87ddcbb..8fa60ab 100644 --- a/internal/templater/templates/guides/claude-code-sdd.md.tmpl +++ b/internal/templater/templates/guides/claude-code-sdd.md.tmpl @@ -1241,6 +1241,7 @@ move to next task **Rules:** +- Branch before the first task — create the spec's branch `/` in kebab-case (`feat/` feature, `fix/` bugfix, `chore/` small adjustment; also `refactor/` `docs/` `test/` `perf/`); never implement on the default branch. - 1 task per iteration — context hygiene. - Each role gets a fresh context — no accumulated bias. - The implementer always starts from a failing test; it MUST NOT write production code before a red test exists. @@ -1270,7 +1271,7 @@ Claude Code maps the autonomy/review concepts of SDD onto **permission modes** a Context management: - Reference files explicitly with `@path` (e.g., `@src/api/albums.ts`, `@specs/photo-albums/design.md`) instead of describing them. -- Use `/clear` to reset context between unrelated tasks — the per-task hygiene that keeps sub-agents unbiased. +- Use `/clear` to reset context between unrelated tasks, and at every feature/spec boundary — run it before `spec init` to start a feature on a clean context, and again once the feature's PR ships, so context does not accumulate across specs. Claude cannot run `/clear` itself; the Stop hook reminds the operator when a spec's tasks are all checked. - Ask for a plan (plan mode) before a large change; separate analysis, implementation, and validation into distinct prompts. - Do not mix many goals in a single request. diff --git a/internal/templater/templates/hooks/block-destructive.sh.tmpl b/internal/templater/templates/hooks/block-destructive.sh.tmpl index 0db9415..d3cd4d5 100644 --- a/internal/templater/templates/hooks/block-destructive.sh.tmpl +++ b/internal/templater/templates/hooks/block-destructive.sh.tmpl @@ -42,4 +42,19 @@ for pat in "${deny[@]}"; do fi done +# Branch-first guard: keep spec work off the default branch. Block `git commit` +# / `git push` while on main/master so each spec lands on its own branch, named +# / in kebab-case: +# ∈ feat | fix | chore | refactor | docs | test | perf e.g. feat/photo-albums +if printf '%s' "$cmd" | grep -Eq '(^|[^[:alnum:]_])git[[:space:]]+(commit|push)([[:space:]]|$)'; then + branch="$(git branch --show-current 2>/dev/null || true)" + if printf '%s' "$branch" | grep -Eq '^(main|master)$'; then + echo "blocked by .claude/hooks/block-destructive.sh: on the default branch '$branch' — branch first." >&2 + echo "Create the spec's branch, then commit: git switch -c / (kebab-case)" >&2 + echo " ∈ feat | fix | chore | refactor | docs | test | perf e.g. feat/photo-albums" >&2 + echo "If committing on the default branch is intentional, run it yourself outside the agent." >&2 + exit 2 + fi +fi + exit 0 diff --git a/internal/templater/templates/hooks/test-before-stop.sh.tmpl b/internal/templater/templates/hooks/test-before-stop.sh.tmpl index 01b2269..5f210b5 100644 --- a/internal/templater/templates/hooks/test-before-stop.sh.tmpl +++ b/internal/templater/templates/hooks/test-before-stop.sh.tmpl @@ -10,6 +10,21 @@ set -euo pipefail echo "Before reporting done, run the verify-change skill: tests, lint, typecheck, build — and paste the real output." >&2 +# Spec-boundary context hygiene: when the spec you're working on has all its +# tasks checked, nudge the operator to /clear before the next feature so context +# does not accumulate across specs. Claude cannot run /clear itself — this is a +# reminder to the human. Keyed off the most recently modified specs/*/tasks.md. +specs_dir="${CLAUDE_PROJECT_DIR:-$PWD}/specs" +latest_tasks=$(ls -t "$specs_dir"/*/tasks.md 2>/dev/null | head -n1 || true) +if [ -n "$latest_tasks" ]; then + total=$(grep -cE '^[[:space:]]*- \[[ xX]\]' "$latest_tasks" 2>/dev/null || true) + open=$(grep -cE '^[[:space:]]*- \[ \]' "$latest_tasks" 2>/dev/null || true) + if [ "${total:-0}" -gt 0 ] && [ "${open:-0}" -eq 0 ]; then + feature=$(basename "$(dirname "$latest_tasks")") + echo "Spec '$feature' has all tasks checked — once its PR ships, run /clear to reset context before the next feature." >&2 + fi +fi + # --- Hard gate (opt-in): uncomment and adapt to your project --------------- # if [ -f Makefile ] && grep -qE '^(test|verify):' Makefile; then # make verify || make test || { echo "verification failed — not done yet" >&2; exit 2; } diff --git a/internal/templater/templates/root/CLAUDE.md.tmpl b/internal/templater/templates/root/CLAUDE.md.tmpl index 550aa3b..3be6a32 100644 --- a/internal/templater/templates/root/CLAUDE.md.tmpl +++ b/internal/templater/templates/root/CLAUDE.md.tmpl @@ -55,12 +55,14 @@ between the markers. ## Workflow at a glance -1. `npx @protonspy/csdd spec init ` then iterate requirements → design → tasks. +1. **Start each feature on a clean context:** run `/clear`, then `npx @protonspy/csdd spec init ` and iterate requirements → design → tasks. 2. Each phase requires explicit human approval recorded in `spec.json`. 3. `ready_for_implementation` flips to `true` only after all three phases are approved. -4. Implementation runs one task per iteration with fresh-context sub-agents (implementer → reviewer → debugger), TDD red→green per task. -5. The `pr-review` skill commits a slice only after review is clean, then pushes — the `pre-push` hook runs the test gate and blocks a red push. -6. Steering is updated only when a new pattern emerges that the agent could not derive from the code. +4. **Branch before the first task:** create the spec's branch — `git switch -c /` in kebab-case (`feat/` feature, `fix/` bugfix, `chore/` small adjustment; also `refactor/` `docs/` `test/` `perf/`). The PreToolUse hook blocks commits on the default branch to enforce this. +5. Implementation runs one task per iteration with fresh-context sub-agents (implementer → reviewer → debugger), TDD red→green per task. +6. The `pr-review` skill commits a slice only after review is clean, then pushes — the `pre-push` hook runs the test gate and blocks a red push. +7. **Close each feature with a `/clear`:** once its PR ships, reset the context before the next spec so it does not accumulate across features. The Stop hook reminds you when a spec's tasks are all checked. +8. Steering is updated only when a new pattern emerges that the agent could not derive from the code. ## Non-negotiables