Agent DevOps SOP
The whole SOP in one paragraph
Two lanes, five skills, one build journal. Worktrees keep work off main until you ship; /ship and /wrap make sure nothing goes live broken. The journal at the bottom of each devtask makes multi-week projects survive context resets and contributor handoffs.
What to actually do
The whole workflow boils down to four commands and one habit:
Most sessions look like this:
| When | Run | What Claude / the hooks do for you |
|---|---|---|
| Starting something that changes behavior | /feature [<slug>] |
Picks the right lane, creates a worktree, symlinks env files, briefs you on the devtask if resuming — then immediately starts Phase 1 |
| Building | (confirm after each phase) | Drives phase by phase; after each phase reports what was done + how to test it, then asks before continuing to the next |
| Ready to deploy | /ship |
Verifies preview, audits commits, rebases, pushes, watches the deploy, confirms live URL |
| End of session | (just stop) | The wrap-on-stop hook auto-flushes the journal entry (commits, branch, last_session); auto-push-on-stop then pushes everything |
To skip inter-phase confirmation: append complete full implementation to the /feature call — Claude works through all phases unattended and only pauses for blocking decisions or if context runs low.
You don’t need to remember /wrap. The Stop hooks handle journal-flush and push automatically. Run /wrap manually only if you want to add narrative to the journal entry, mark a phase complete, or explicitly decide what to do with an open worktree before stopping.
Which path? — do I need a devtask first?
The discriminator isn’t size — it’s “will multiple sessions need to share state?” If yes, the journal is the mechanism for sharing that state, and you need a devtask doc to anchor it. If no, just /feature directly with a free-text description.
| What you’re doing | Path |
|---|---|
| Typo, copy fix, doc edit, single image | Edit on main, just stop — no skill needed |
| One-session feature you’ll finish today | /feature "short description" |
| Multi-session project worth handing off | /brainstorm → /devtask → /feature <slug> |
| Resuming a multi-session project | /feature <slug> (look up the slug below) |
What’s a slug?
A slug is the kebab-case identifier of an existing devtask — the filename of docs/devtasks/<slug>.md minus .md. Examples: Sentinel → sentinel, Image database → imagedatabaseplan, Agent DevOps SOP → agent-devops-sop. Visible in the URL: https://sponicgardens.com/docs/devtasks/<slug>.html.
You don’t have to remember slugs — every card on the public docs index and the intranet DevControl → Docs tab has a one-click Copy slug button. Click, paste into Claude after /feature , done.
For tiny edits
For tiny edits (typo, doc, image catalog, new devtask): skip the worktree. Edit on main, just stop. The auto-push hook handles the deploy.
Special cases:
/brainstorm— thinking out loud; no commits, no worktree, no plan files/devtask— save the conversation as a published spec/journal "..."— force a manual journal entry (rare; Claude does this proactively while you build)/wrap— manual session-close override (rare; auto-flush handles the common case)
1. Why this works
The two sentences everyone needs to internalize
Every commit on main deploys to production within ~3 minutes. No staging, no PR review, no manual gate. The auto-push-on-Stop hook turns “I’m done with this Claude session” into “this is now live.”
Worktrees are how you work without going live. Separate copy of the repo, separate branch — Claude edits, you preview locally, all without touching main. When you’re confident, you “ship” it.
The skills (/feature, /ship, /wrap) encapsulate the git mechanics so you don’t have to think about them. The build journal captures decisions automatically so a future session — or a different contributor — can pick up cold.
2. Two lanes, not three
| Lane A — Worktree | Lane B — Direct to main |
|
|---|---|---|
| When | Anything that changes user-visible behavior | The safe-list (right column) only |
| Lane B safe-list | — | Single-line copy fixes · *.md docs outside apps/ · image-catalog additions · new DevTasks via /devtask · CI version bumps |
| Skill | /feature → /ship |
(regular commit) → /wrap |
| Goes live | Only after /ship succeeds |
On Stop hook (~3 min) |
| Reversible? | Yes — worktree is contained until you ship | Only by another commit |
If you can’t put your change on the Lane B safe-list, it goes through a worktree. There are no “I’m sure it’s fine” exceptions; auto-push has been wrong before.
3. The lifecycle
A single Claude session moves through up to five phases. You don’t have to do them in order — most sessions skip THINK and SPEC:
/wrap is an optional manual override of the auto-flush — most sessions don’t need it.
Common entry points:
- “I’m thinking about X” → start at THINK (
/brainstorm) - “Work on phase 2 of [existing devtask]” → start at BUILD (
/feature sentinel) - “Quick copy fix on the homepage” → Lane B; commit on
main, then/wrap
For multi-week projects, this same inner loop runs once per session and an outer loop wraps it — see §5.
4. The five skills
- No worktree, no commits, no plan file.
- Conversational only — tradeoffs, options, push-back.
- Suggests
/devtaskwhen ready to capture.
- Devtask slug → reads journal, briefs current state.
- Free-text → chooses Lane A or Lane B.
- Worktree named
claude/<slug>-β¦for traceability.
- Appends to the active devtask’s journal entry.
- Categories:
decision,blocker,tested,next,insight. - Does not commit — sweeps up at
/wrap.
- Preview screenshot → commit-message audit → rebase → push.
- Watches Cloudflare Pages deploy; confirms live URL renders.
- Refuses if you’re not in a worktree.
- Worktree status, commit-message audit, live-URL check.
- Auto-fills today’s journal entry; updates frontmatter.
- Prints copy-paste traceability summary.
/brainstorm — think out loud
Stays conversational only. No worktree, no commits, no plan file. When you’re ready to capture, suggests /devtask. When you’re ready to build, suggests /feature. The explicit “no artifacts, just talk” lane.
/devtask — capture the spec
Writes four files — markdown source at docs/devtasks/<slug>.md (with YAML frontmatter and a ## Build journal placeholder), HTML render in apps/garden/docs/devtasks/, public docs index entry, intranet DocsTab entry. The spec becomes the durable reference that BUILD points at.
/feature [<slug>] — start or resume a build
Routes by entry shape:
/feature sentinel(devtask slug) — reads the journal, briefs you on phase / last decision / next step. Attaches to the existing worktree fromrelated_worktreesif local, otherwise createsclaude/sentinel-<suffix>./feature "fix homepage header"(free-text) — picks Lane A or B based on the description; defaults Lane A./featurealone — asks “what are we building?”
When creating a worktree, also symlinks every apps/*/.env*.local file from the main checkout into the worktree (so npm run dev boots with full config) and writes the slug to .claude/active-devtask so other skills can find the active devtask deterministically.
After setup, Claude immediately starts Phase 1 (or the next_step phase on resume) and drives the build phase by phase. After each phase it delivers: what was built, how to test it (numbered steps + expected behavior), a one-sentence preview of the next phase, and a “Ready to continue?” prompt.
Before presenting any test plan, Claude sets up the environment automatically: applies database migrations (Supabase MCP or CLI), deploys edge functions, sets secrets from Bitwarden, starts the dev server, and verifies external source connectivity. Manual steps are only asked of the user when every automated path has been exhausted — and even then, Claude prepares the exact command or URL so it’s a single user action. “Known limitations” that are really setup gaps don’t get labelled as limitations — they get escalated with a specific ask.
Append complete full implementation to skip inter-phase confirmation — Claude runs all phases unattended and only pauses for blocking decisions or low context.
Removes “do I need a worktree?” from the user’s decision burden, removes the cold-start cost on resume, removes the “why is the dev server broken?” surprise, removes the context-switch friction between setup and actual building, and removes the burden of running setup commands after each phase.
/journal "..." — capture state mid-build
- A non-obvious decision is made (going with X over Y because Z)
- A blocker is hit (something stops forward progress)
- A phase is completed (frontmatter
phases_doneincrements) - A test result is observed in a specific environment (Local / Production / alpu.ca)
You can also call it manually: /journal "decision: bucket region EU". Manual entries are typically terser; Claude-initiated entries include the why. Categories: decision, blocker, tested, next, insight.
Where entries appear. Two places, in sync: the markdown source at docs/devtasks/<slug>.md (under ## Build journal) AND the public HTML page — every devtask’s rendered page has a <div id="journal-entries"> slot at the bottom that auto-renders new entries. So the build journal of any in-progress devtask is visible at https://sponicgardens.com/docs/devtasks/<slug> to anyone reading the spec.
Does NOT commit. The journal stays as a working-tree change until /wrap sweeps it up — avoids commit noise. If you stop without /wrap, a soft pre-Stop nudge surfaces a one-line reminder when there were commits but no journal entry.
/ship — encapsulated deploy
Verifies in dev preview (screenshot inline) → audits commit messages → rebases onto origin/main → fast-forward pushes → watches the Cloudflare Pages deploy → confirms live URL renders → offers worktree cleanup. Rebasing is the most error-prone manual git operation a non-engineer hits; encapsulation removes the failure mode.
/wrap — optional manual session-close
wrap-on-stop.sh— for any devtask-tied session with commits, writes a structured journal entry (date, contributor, branch, commits) and updateslast_sessionin the YAML frontmatter. Idempotent.auto-push-on-stop.sh— prompts Claude to commit + push the working-tree changes (including the just-written journal entry).
So 95% of sessions: just stop. The hooks do the close.
Run /wrap manually only when:
- You want to add narrative to the journal entry (the auto-flush writes structured fields only — no prose). Better: call
/journal "decision: β¦"mid-session, which Claude does proactively anyway. - You want to ship/abandon/keep an open worktree explicitly before stopping (the hooks don’t touch worktrees).
- You want to mark a phase complete and bump
phases_donein frontmatter before the auto-flush runs.
If none of those apply, just stop the session.
5. The build journal
The journal lives in the same <slug>.md file as the spec. It serves three audiences:
- Future you — what was I doing last week?
- Other contributors — pick up cold without verbal handoff.
- The public page — every devtask’s published HTML has a “Build journal” section at the bottom that auto-renders new entries, so anyone reading the spec also sees the build progress.
Frontmatter (YAML at the top of <slug>.md)
---
slug: sentinel
title: Sentinel
status: planning # planning | in-progress | shipped | abandoned
phases_total: 13
phases_done: 0
phases_in_progress: []
phases_blocked: []
last_session: null
next_step: "Read the spec; pick a phase to start; run /feature sentinel"
related_worktrees: []
contributors: []
---
/devtask writes this when creating a new spec. /feature updates status, last_session, related_worktrees, contributors on entry, and writes the slug to .claude/active-devtask so other skills can find the active devtask deterministically. /wrap updates phase counts and next_step on exit, and clears the state file. The intranet DocsTab reads status and phases_done/phases_total to render a live status badge for in-progress devtasks.
Journal entry format (one per session, newest at top)
Worked example
### 2026-05-06 Β· Haydn Β· phase 5 Β· claude/sentinel-phase-5-abc1
**Done:** Wired R2 client in apps/control/src/lib/sentinel-storage.ts;
added bucket config to env.ts.
**Decisions:**
- Bucket region: EU (compliance)
- Bucket name: sentinel-artifacts (matches existing naming)
**Tested:** Local β Β· Production β (token missing R2 perm)
**Next step:** Update Bitwarden DevOps token; retry production upload.
**Commits:** abc123, def456
**Session:** cs_xyz789 (search via mcp:ccd_session_mgmt)
/journal appends notes mid-session — Claude calls it proactively on decisions, blockers, phase boundaries, and env-test results. The wrap-on-stop hook fills in the structured fields (branch, commits, last_session) automatically at session end. You only narrate when you want to add nuance to what Claude already captured.
Long-running projects: the outer loop
A real project — Sentinel, document-management, the AI host — spans many sessions over weeks. The inner loop above runs once per session; an outer loop wraps it:
A new contributor running /feature sentinel cold reads the frontmatter (knows it’s at phase 5, blocked on Cloudflare token), reads the latest journal entry, and starts work without asking anyone. The conversation is rebuildable any time from the journal.
When context gets heavy mid-session
Standard handoff procedure:
State lives on disk, not in the conversation.
6. Commit message convention
<type>(<scope>): <subject under 72 chars, imperative mood>
Why this change: <one or two sentences β the why, not the what>
[optional: see docs/devtasks/<slug>.md]
Co-Authored-By: Claude <[email protected]>
Types: feat | fix | copy | docs | chore | refactor | infra
Scopes: garden | control | skills | hooks | infra | devtasks | image-gen | <free-text-if-clearly-bounded>
/ship audits commit messages on the worktree branch before pushing. /wrap audits commits landed in the session and either offers an amend (if unpushed) or a follow-up clarifying commit (if already pushed — never --amend pushed history).
7. Checklists
Post-session — /wrap validates these
- Active worktree shipped or explicitly abandoned
- No stale worktrees > 7 days
- All session commits pushed to
main - Commit messages have
<type>(<scope>): <subject>+ why-line - Live URL of every changed surface returns 200 + expected content
- Build journal entry written for any in-progress devtask
- Traceability summary captured
First day — for a new contributor
The first-day setup checklist (BW unlock, session-recording hook, env files, smoke tests of /brainstorm / /feature / /ship) lives in Onboard a new machine under "Agent DevOps SOP β how we work with Claude" β "First day on a new machine." That's the single source of truth for new-machine setup; this SOP is the steady-state workflow.
8. Out of scope
We deliberately don’t do these — discipline first, automate when discipline fails:
- Pull request review. Three PMs auto-deploying makes a PR queue theatre. Preview-in-worktree replaces review-in-PR.
- Branch protection on
main. The skills enforce the same invariants softly. - Multi-stage staging. One environment, with worktree previews as the only “before live” step.
- Mandatory pre-commit / pre-push hooks beyond what CI runs today.
- Automated changelog. The build journal is the changelog for long-running devtasks; small one-off changes don’t need one.
Tooling adapters (Codex, etc.): the lane policy and lifecycle are tool-agnostic. The five skills are Claude-Code-specific harness behavior; under another agent, equivalents would need CLI scripts that perform the same git/preview/journal/push operations. Defer until someone actually switches.
Build journal
Entries are appended by /feature, /journal, and /wrap. Newest at the top.
2026-05-07 Β· Haydn Β· v1.7 — setup-first before testing; no known-limitation dumping
Done: Added a set up first, test second mandate to /feature Step 6. Before the phase-complete report, Claude now works through a setup checklist: apply migrations (Supabase MCP or CLI), deploy edge functions, set secrets from BW, start dev server, verify external source connectivity. Manual steps are only escalated after every automated path fails, and even then Claude prepares the exact command so it’s a single user action. Eliminated the “known limitations” anti-pattern — gaps get either documented as deferred scope or escalated with a specific ask.
Decisions:
- Table format for the setup checklist (task β automated path) is scannable and explicit about fallback order. Easier to audit than prose.
- “Known limitations are not a category” phrasing is intentionally blunt — the previous phase-complete report in the day-in-review build session produced a multi-page manual-steps document instead of a ready-to-test environment. That should never happen again.
- Environment-ready item added as item 0 in the report format, before what-was-done — because if the environment isn’t ready, the test steps are irrelevant.
Tested: Skill file update only — behavior verified on next phased devtask invocation.
Next step: Dogfood on day-in-review build — resume Phase 1, verify Claude applies the migration and deploys functions without asking the user to run CLI commands.
Commits: (this commit)
2026-05-07 Β· Haydn Β· v1.6 — /feature drives the build phase by phase
Done: Removed the “hand off and stop” constraint from the /feature skill. It now starts executing Phase 1 immediately after worktree setup — no waiting for the user to prompt. After each phase it delivers a structured report: what was built (bullet list), how to test it (numbered steps with expected behavior), what was deferred, a one-sentence preview of the next phase, and a continue prompt. Full-implementation mode (/feature <slug> complete full implementation) runs all phases unattended, pausing only for blocking decisions, missing dependencies, or low context.
Files changed:
.claude/skills/feature/SKILL.md— new invocation shape, replaced Step 6, updated Step 8 framing, fixed “What you do NOT do”docs/devtasks/agent-devops-sop.md— workflow table, lifecycle diagram,/featureΒ§4 descriptionapps/garden/docs/devtasks/agent-devops-sop.html— HTML sync of all three changes above
Decisions:
- Phase-complete report format: what-done bullets + numbered test steps + deferred list + next-phase preview + continue prompt. This is the minimum to let a non-technical user verify a phase without opening a terminal.
- Full-impl mode triggered by trailing “complete full implementation” (not a flag). More natural to type and matches how a PM would phrase it.
- Context off-ramp in full-impl mode: complete the current sub-task, write a journal entry, tell the user exactly where things stand. Avoids a mid-task cliff.
- Inter-phase pauses (not mid-phase) are the right unit. Pausing mid-phase means the user can’t test anything yet; pausing between phases means they always get a testable, complete unit.
Next step: Dogfood on the next phased devtask — invoke /feature <slug> cold and verify Phase 1 starts without a prompt, report is clear, and testing steps match actual app behavior.
Commits: (this commit)
2026-05-07 Β· Haydn Β· v1.5 β fold first-day checklist into the onboarding doc
Done: Moved the SOP's "First day — for a new contributor" checklist into the onboard-new-machine doc, where new-machine setup actually happens. The SOP page now shows a one-paragraph pointer to the onboarding doc instead of the checklist itself; the canonical setup sequence lives in one place.
The onboarding doc now has:
- New rows in "What lives where" for the Agent DevOps SOP, the five auto-loaded Claude skills, the
wrap-on-stop.shhook, and thesetup-worktree-env.shsymlink helper. - A new section "Agent DevOps SOP — how we work with Claude" right after BW unlock — short workflow recap (
/feature β build β /ship β just stop) plus the first-day checklist relocated from the SOP. - The bootstrap "Session prompt for a new machine" updated to read the SOP doc as part of the initial onboarding sequence (between
CLAUDE.mdandsystemarchitecture.md).
Decisions:
- The SOP is the steady-state workflow doc; the onboarding doc is the new-machine setup doc. Setup belongs with credentials, BW unlock, and per-machine hook installation — not in the workflow reference. Co-locating it there means a contributor reads through one doc top-to-bottom on day one, not two.
- HTML table additions kept light (just SOP + skills rows) to avoid noise; markdown table is more verbose with hook + script rows for completeness. The HTML is the curated render.
- Bootstrap prompt order: CLAUDE.md (auto-loaded) β SOP (how we work) β systemarchitecture.md (deep infra). Natural reading order for day one.
Tested: Local β — both files render, links resolve, tag balance clean.
Next step: Dogfood by another contributor onboarding to a new machine — they should read top-to-bottom of onboard-new-machine and have everything they need, without bouncing into the SOP doc for setup steps.
Commits: (this commit)
2026-05-06 Β· Haydn Β· v1.4 β slug discoverability + "Which path?" decision table
Done: Added two new subsections at the top of the SOP to close onboarding gaps that surfaced during dogfood testing:
- “Which path? — do I need a devtask first?” — a 4-row decision table mapping work shape (typo / one-session / multi-session / resuming) to path. Discriminator is “will multiple sessions need to share state?” — not size.
- “What’s a slug?” — a green callout defining the term, three worked examples (
sentinel,imagedatabaseplan,agent-devops-sop), URL pattern, and a pointer to the new copy-slug buttons.
Plus a one-click Copy slug button on every doc card in two surfaces: the intranet docs-tab.tsx (React) and the public devtasks/index.html (static HTML + inline JS in the existing dynamic-button loop). Click copies just the slug (not the full /feature <slug> invocation), shows “Copied!” briefly.
Decisions:
- Slug only, not full invocation. The user already types
/featureor has it in muscle memory; the friction is just the slug. - Hidden until hover on both surfaces, matching the existing
.hide-btnUX pattern. Reduces visual noise for casual readers. - The discriminator phrasing matches the auto-journal mental model: state that needs to outlive a single session belongs in a journal entry inside a devtask; state that doesn’t, doesn’t.
Tested: Local β — both surfaces render the button on hover; click extracts the right slug from href (verified agent-devops-sop on the first card). TypeScript clean. The “Copied!” feedback requires document focus to test fully (clipboard API restriction in headless eval), but DOM wiring is correct.
Next step: Dogfood by another contributor — they should hover any card on the public docs index, click “Copy slug”, paste into a fresh Claude session after /feature , and have it just work.
Commits: (this commit)
2026-05-06 Β· Haydn Β· v1.3 β /wrap auto-flush + drop traceability summary
Done: Replaced the v1.1 journal-nudge-on-stop.sh (which only warned) with a new wrap-on-stop.sh Stop hook that writes the journal entry automatically — for any devtask-tied session with commits, it appends a structured entry (date / contributor / branch / commits) and updates last_session in the YAML frontmatter, then auto-push fires next and pushes the result. Idempotent. Reframed /wrap SKILL.md as an optional manual override. Dropped the copy-paste traceability summary entirely. Cut the lifecycle-diagram WRAP step from a discrete column to “(STOP) → auto-flush + auto-push” annotation. Updated the workflow table: “End of session → just stop” replaces the explicit /wrap row.
Decisions:
- The Stop hook writes structured fields but no prose; narrative comes from
/journalcalls during the session. Claude is already journaling proactively on decision/blocker/phase/env-test triggers, so the auto-flush completes the picture without requiring user action. - Drop the copy-paste traceability summary — it was busywork. If traceability matters, it belongs IN the journal (with persistence + a public URL), not printed for the user to paste somewhere.
/wrapmanual stays for narrative-add and worktree-management. v1.0 had it as the mandatory close; v1.3 makes it the rare manual override. Mental model: “just stop, hooks handle it” replaces “remember to run/wrap.”- New hook order:
wrap-on-stopruns beforeauto-push-on-stopso the journal entry lands in the same auto-push cycle.
Tested: Local β — three test cases against a synthetic devtask: no today entry β minimal entry created; today entry exists without commits block β commits appended; rerun β idempotent. Edge cases (no active-devtask, no recent commits) exit silently with 0.
Next step: after deploy, dogfood in a real session. Then return to the deferred slug-discoverability work (queued as v1.4).
Commits: (this commit)
2026-05-06 Β· Haydn Β· v1.2 β workflow-first cleanup + auto-journal coverage
Done: Restructured top of doc as workflow-first (“What to actually do” replaces “Quick reference”) so a developer sees the run sequence — /feature β build β /ship β /wrap — before any concepts; renamed §1 “The mental model” to “Why this works”; collapsed §3 Lifecycle by moving the multi-week outer loop and the context-heavy handoff into §5; updated §4 /journal and §5 to call out that journal entries also render on the public HTML page via the <div id="journal-entries"> slot; added that slot to the SOP HTML and rendered prior entries into it.
Decisions:
- Lead with the workflow, not the catalog. New contributors need to see the sequence (
/feature β build β /ship β /wrap) before they read about lanes, lifecycles, or skills. - Auto-journal messaging belongs in the workflow table, not buried in §4. The fact that “Claude does this for you” needs to be visible before anyone reads the deep dive.
- Multi-week and context-handoff moved into §5 because they’re build-journal concepts; §3 is just the inner loop now.
Tested: Local β — markdown + HTML render in garden-static; tag balance clean; new strings present in the rendered page.
Next step: ship as Lane B (doc-only). First dogfood test is the next contributor’s /feature session.
Commits: (this commit)
2026-05-06 Β· Haydn Β· v1.1 β env loading + auto-journaling
Done: Added setup-worktree-env.sh (symlinks .env*.local from main into worktrees, idempotent); journal-nudge-on-stop.sh Stop hook (soft, never blocks); .claude/active-devtask session-state file pattern; /feature Step 7 proactive-journaling triggers (decision / blocker / phase / test result); updated /journal to read the state file; updated /wrap to clear it.
Decisions:
- Symlink not copy for env files — keeps the two checkouts in sync on any edit, and
.env.localisn’t the kind of file you want to diverge silently. - Resolve main checkout via
git worktree list --porcelain(first entry), not via the script’s own path. The script is committed and lives in every worktree, not just main. - Active-devtask file lives at
.claude/active-devtask(per-worktree). Gitignored. - Journal-nudge hook is soft only (writes to stderr, exits 0). Aligns with low-friction reminder preference.
- Proactive-journaling triggers narrowed to four. Routine commits and mechanical edits intentionally don’t trigger.
Tested: Local β — env-setup script idempotent + recreates symlink when missing; nudge hook fires when commits exist but no today entry, silent when today entry exists.
Next step: dogfood on the next non-trivial feature build to see if the proactive-journaling triggers are the right granularity.
Commits: 87a6288
2026-05-06 Β· Haydn Β· implementation complete
Done: Authored five skills (/brainstorm, /feature, /journal, /ship, /wrap); extended /devtask to write the new YAML frontmatter and ## Build journal placeholder; extended the intranet docs-tab.tsx to render live status badges from live_status field; rewrote this SOP doc as an evergreen runbook (was previously a build plan / RFC).
Decisions:
- Worktree naming on resume: attach if local branch exists, otherwise fresh
claude/<slug>-<suffix>. - Session ID surfacing: if the harness exposes it, use it; else fall back to date + topic, searchable via
mcp__ccd_session_mgmt. - Multiple devtasks per session:
/featurelocks the session to one; switching requires/wrapfirst. - Live status badge automation: hand-set in
docs-tab.tsxfor v1; build-time frontmatter parsing is v2.
Tested: Local β (garden-static preview, full page render). Live verified after the previous push (4f84013).
Next step: First real test is the next non-trivial feature build done by another contributor.
Commits: 71f49f3 (and the prior 4f84013)