sprint
|
Works with
---
name: sprint
description: |
license: Apache-2.0
---
# Sprint Skill — Generic Sprint Management for bkit Users
> Sprint = meta-container above bkit's PDCA 9-phase. A sprint groups one or
> more features under a shared scope, budget, and timeline. Each sprint runs
> its own 8-phase lifecycle: prd -> plan -> design -> do -> iterate -> qa
> -> report -> archived.
## Quick Start
```
/sprint init my-launch --name "Q2 Launch" --trust L3
/sprint start my-launch
```
The skill handler routes through `<bkit-root>/scripts/sprint-handler.js`
(bkit convention — handlers live at the bkit repo root `scripts/` directory,
NOT inside skills/<name>/scripts/). The handler composes
Sprint 3 adapters (state-store + telemetry + doc-scanner + matrix-sync)
into Sprint 2 use cases (start / advance / iterate / qa / report / archive).
Sprint 1 entities (createSprint / SprintEvents / typedefs) are produced
and consumed transparently along the way.
> **Resolving `scripts/sprint-handler.js` in this document**: throughout
> this SKILL.md, references to `scripts/sprint-handler.js` mean
> `<bkit-root>/scripts/sprint-handler.js` (the canonical location).
> LLM dispatchers MUST NOT compose `skills/sprint/scripts/sprint-handler.js`
> — that path does not exist (Issue #107, fixed v2.1.19 S2 F2-1).
## Arguments
| Argument | Description | Example |
|----------|-------------|---------|
| `init <id>` | Create a sprint with default config | `/sprint init my-launch` |
| `start <id>` | Run auto-run loop bounded by Trust Level scope | `/sprint start my-launch --trust L3` |
| `status <id>` | Show current sprint state from disk | `/sprint status my-launch` |
| `list` | Union of state-store entries and master-plan discoveries | `/sprint list` |
| `phase <id> --to <phase>` | Advance to a specific phase | `/sprint phase my-launch --to qa` |
| `iterate <id>` | Run matchRate-100 loop (max 5 cycles) | `/sprint iterate my-launch` |
| `qa <id> --feature <name>` | Run 7-Layer data-flow check on one feature | `/sprint qa my-launch --feature auth` |
| `report <id>` | Generate KPI + lessons + carry-items report | `/sprint report my-launch` |
| `archive <id>` | Move to terminal `archived` status | `/sprint archive my-launch` |
| `pause <id>` | Manually pause a running sprint | `/sprint pause my-launch` |
| `resume <id>` | Re-evaluate triggers and resume | `/sprint resume my-launch` |
| `watch <id>` | Live dashboard (Sprint 5 — current returns snapshot) | `/sprint watch my-launch` |
| `feature <id>` | Per-feature operations (Sprint 5) | `/sprint feature my-launch --feature auth` |
| `fork <id>` | Fork into a new sprint (Sprint 5) | `/sprint fork my-launch --new my-launch-v2` |
| `help` | Print sub-action help | `/sprint help` |
| `master-plan <project>` | Generate multi-sprint Master Plan (agent isolated spawn) | `/sprint master-plan q2-launch --name "Q2 Launch" --features auth,payment` |
| `measure <id>` | Measure single gate / multi-gate / phase batch (v2.1.16 #94) | `/sprint measure my-launch --gate M4` |
## Trust Level Scope (auto-run boundary)
| Level | Stop after | Manual | Notes |
|-------|------------|--------|-------|
| L0 | prd | true | Each phase requires user approval |
| L1 | prd | true (hint) | Hint mode but still manual |
| L2 | design | false | Plan -> Design auto, Do requires approval |
| L3 | report | false | Plan -> Report auto, Archive requires approval (default) |
| L4 | archived | false | Full auto including archive (Trust >= 85 recommended) |
## Auto-Pause Safety Pins
Four armed triggers can pause a running sprint:
- `QUALITY_GATE_FAIL` — M3 > 0 OR S1 < 100
- `ITERATION_EXHAUSTED` — iter >= 5 AND matchRate < minAcceptable
- `BUDGET_EXCEEDED` — cumulativeTokens > config.budget
- `PHASE_TIMEOUT` — phase elapsed > config.phaseTimeoutHours
Pause writes an audit log entry and a `SprintPaused` event. Resume
re-evaluates the triggers and refuses if any are still firing.
## Cross-Sprint Architecture (Sprint 1+2+3+4)
```
USER COMMAND
v
skills/sprint/SKILL.md (this file — frontmatter triggers in 8 languages)
v
scripts/sprint-handler.js (English dispatcher)
v
Sprint 3: lib/infra/sprint -> { stateStore, eventEmitter, docScanner, matrixSync }
v
Sprint 2: lib/application/sprint-lifecycle -> startSprint / advancePhase / ...
v
Sprint 1: lib/domain/sprint -> createSprint / SprintEvents / typedefs
v
DISK: .bkit/state/sprints/<id>.json + .bkit/audit/<date>.jsonl
```
## Examples
See:
- `examples/basic-sprint.md`
- `examples/multi-feature-sprint.md`
- `examples/archive-and-carry.md`
## When NOT to Use
- Single-feature PDCA work — use `bkit:pdca` instead
- Starter level projects — sprint overhead exceeds value
- One-off bug fixes that do not warrant a master plan
## Delegation notes
Extended trigger keywords, moved here from the frontmatter description
(issue #129 token diet) — one anchor per language stays in the description;
the full multilingual list is preserved below:
- JA: スプリント開始, スプリント状態, マスタープラン, マルチスプリント計画, スプリントマスタープラン
- ZH: 冲刺开始, 冲刺状态, 主计划, 多冲刺计划, 冲刺主计划
- ES: iniciar sprint, estado sprint, plan maestro, plan multi-sprint, plan maestro sprint
- FR: demarrer sprint, statut sprint, plan maître, plan multi-sprint, plan maître sprint
- DE: Sprint starten, Sprint Status, Masterplan, Multi-Sprint-Plan, Sprint-Masterplan
- IT: avviare sprint, stato sprint, piano principale, piano multi-sprint, piano principale sprint
## Related Skills and Agents
- `bkit:pdca` — single-feature PDCA cycle (foundation primitive)
- `bkit:control` — automation level (L0-L4) — surfaces SPRINT_AUTORUN_SCOPE
- `bkit:sprint-orchestrator` (agent) — full lifecycle coordinator
- `bkit:sprint-master-planner` (agent) — plan/design generation
- `bkit:sprint-qa-flow` (agent) — 7-Layer dataFlowIntegrity verifier
- `bkit:sprint-report-writer` (agent) — KPI + lessons + carry items
## 10. Skill Invocation Contract (for LLM Dispatchers)
This contract specifies how an LLM dispatcher should construct the `args`
object for each of the 16 sub-actions when invoking the underlying handler
via `scripts/sprint-handler.js`.
### 10.1 Args Object Schema (per action)
| Action | Required | Optional | Example call |
|--------|----------|----------|--------------|
| `init` | `id`, `name` | `trust`/`trustLevel`, `phase`, `context`, `features` | `args = { id: "my-launch", name: "Q2 Launch", trust: "L3" }` |
| `start` | `id`, `name` | `trust`/`trustLevel`, `phase`, `context`, `features` | `args = { id: "my-launch", name: "Q2 Launch" }` (resume preserves phase) |
| `status` | `id` | — | `args = { id: "my-launch" }` |
| `list` | — | — | `args = {}` |
| `phase` | `id`, `to` | `approve` (boolean), `reason` (string) | `args = { id: "my-launch", to: "do", approve: true, reason: "Design review complete" }` |
| `iterate` | `id` | — | `args = { id: "my-launch" }` |
| `qa` | `id`, `featureName` | — | `args = { id: "my-launch", featureName: "auth" }` |
| `report` | `id` | — | `args = { id: "my-launch" }` |
| `archive` | `id` | `projectRoot` | `args = { id: "my-launch" }` |
| `pause` | `id` | `triggerId`, `severity`, `message` | `args = { id: "my-launch", triggerId: "USER_REQUEST" }` |
| `resume` | `id` | — | `args = { id: "my-launch" }` |
| `watch` | `id` | — | `args = { id: "my-launch" }` |
| `feature` | `id`, `action` | `featureName` (required for add/remove) | `args = { id: "my-launch", action: "list" }` |
| `fork` | `id`, `newId` | — | `args = { id: "my-launch", newId: "my-launch-v2" }` |
| `help` | — | — | `args = {}` |
| `master-plan` | `id` (projectId), `name` (projectName) | `features` (CSV or array), `trust`/`trustLevel`, `context`, `projectRoot`, `force` (boolean), `duration` | `args = { id: "q2-launch", name: "Q2 Launch", features: ["auth", "payment"] }` |
| `measure` | `id` | one of: `gate` (string) / `gates` (CSV or array) / `phase` (string); plus `trustLevel`, `source` ('manual'\|'auto'), `agentTaskRunner` (function in deps) | `args = { id: "my-launch", gate: "M4" }` |
### 10.1.2 `measure` action semantics (v2.1.16, Issue #94 F3)
`/sprint measure <id>` is the user-invokable partial-gate measurement command
added in v2.1.16. It routes the requested gate(s) through
`lib/application/quality-gates/measure-router.js` (single SoT shared with
sprint-orchestrator self-assessment) and persists results into
`sprint.qualityGates` subject to Trust Level scope.
**Three invocation modes (mutually exclusive precedence: gate > gates > phase)**:
```bash
/sprint measure my-launch --gate M4 # single gate
/sprint measure my-launch --gates M4,M8 # multi-gate (CSV)
/sprint measure my-launch --phase design # phase batch (ACTIVE_GATES_BY_PHASE[design])
```
**Agent routing** (Master Plan §11.3 AC4 — 7 gates × 4 agents):
| Gate | Agent | Source artifact |
|------|--------------------|--------------------------------------------------|
| M1 | gap-detector | Design §9 API Contract ↔ shipped implementation |
| M2 | code-analyzer | lib/ + tests/ quality scan |
| M3 | gap-detector | critical severity issue scan |
| M4 | gap-detector | Design §9 API Contract ↔ module boundaries (#92) |
| M7 | code-analyzer | style + naming convention scan |
| M8 | sprint-orchestrator| design §14 self-assessment checklist |
| S1 | sprint-qa-flow | 7-Layer hop traversal |
Gates outside this table (M5, M10, S2, S4) return
`{ ok: false, reason: 'unsupported_gate' }` — carried to v2.1.17.
**Trust Level scope** (Master Plan AC5):
- `L0` / `L1`: **preview mode** — measurement returned but
`sprint.qualityGates` NOT updated, no `gate_measured` audit entry.
- `L2` / `L3` / `L4`: **record mode** — qualityGates updated +
`gate_measured` audit entry emitted per gate.
**Audit emission** (when in record mode):
```json
{
"action": "gate_measured",
"category": "sprint",
"actor": "user",
"target": "<sprintId>",
"details": {
"sprintId": "...", "gateKey": "M4", "field": "M4_apiComplianceRate",
"agent": "gap-detector", "value": 100, "threshold": 95, "passed": true,
"source": "manual", "phase": "design", "trustLevel": "L3",
"previousValue": null
}
}
```
**ENH-292 alignment**: multi-gate / phase batch dispatches measurements
sequentially (no Promise.all) to avoid #56293 sub-agent caching 10x.
**Dispatcher requirement**: the LLM dispatcher (main session) must inject
`deps.agentTaskRunner` wrapping Claude Code's Task tool. Without it the use
case returns `reason: 'no_agent_runner'` per gate (deterministic, not silent
fail). The handler layer exposes `createTaskToolRunner({ invokeTaskTool })`
(in `scripts/lib/sprint-handler-shared.js`, re-exported from
`scripts/sprint-handler.js`) to build this wrapper:
```javascript
const { createTaskToolRunner } = require('<bkit-root>/scripts/lib/sprint-handler-shared');
const runner = createTaskToolRunner({
invokeTaskTool: async ({ subagent_type, prompt }) => {
// delegate to Claude Code's Task tool in the main session
return { text: await callTaskTool({ subagent_type, prompt }) };
},
});
await handleSprintAction('measure', { id, gate }, { agentTaskRunner: runner });
```
> **Fork mode changes when the result arrives (ENH-478, v2.1.37).**
>
> The snippet above assumes `callTaskTool` resolves to the subagent's finished
> text. On Claude Code v2.1.232 and later that assumption does not hold in an
> interactive session: fork mode is on by default, the Agent tool loses its
> `run_in_background` parameter, and "a background subagent's results reach Claude
> as a completion notification in a later turn"
> (code.claude.com/docs/en/sub-agents). The result is not lost — it arrives on a
> later turn — but it is not available inside the turn that spawned the subagent.
>
> A dispatcher that awaits it in-turn therefore receives nothing, and the gate
> reports `no_output`: an honest "not measured" rather than a wrong score, with
> the likely cause named in the message. To measure inside one turn, either run
> non-interactively (`-p`, where fork mode is off) or set
> `CLAUDE_CODE_FORK_SUBAGENT=0`.
>
> Nothing here is a workaround for a defect. It is the shape of the runtime, and
> a dispatcher that spans turns is the correct adaptation to it.
**Two invocation paths:**
1. **In-process (primary, main session):** the LLM dispatcher calls
`handleSprintAction(...)` directly with `deps.agentTaskRunner` injected.
Gate measurement works end-to-end.
2. **Subprocess CLI (`node scripts/sprint-handler.js ...`):** runs in a
separate Node process that cannot see the Task tool, so it passes `{}`
and gate measurement returns `no_agent_runner`. Use this path only for
non-measurement actions (status, list, help) or when the in-process path
is unavailable; for any action that measures gates, use the in-process
dispatcher call with an injected runner.
### 10.1.1 `phase --approve` semantics (v2.1.16, Issue #95)
When a sprint is at Trust Level L2 (`scope.stopAfter = "design"`) or any other
level whose `scope.requireApproval` blocks a forward transition, the user can
re-issue the `phase` action with `--approve` (and optional `--reason`) to
cross the scope boundary **for this single call only**:
```bash
/sprint phase my-launch --to do --approve --reason "Design review complete, M4/M8 gates pass"
```
Semantics (Master Plan §11.2 AC1-AC6):
- **Single-use**: `sprint.autoRun.scope` is NOT mutated. The next transition
faces the same scope check. To advance through multiple scope-blocking
transitions, re-issue `--approve` each time (or escalate Trust Level via
`/bkit:control level <N>`).
- **No trust escalation**: `sprint.autoRun.trustLevelAtStart` and the global
automation level (`/bkit:control`) are unchanged. The approval is recorded
per-call.
- **Audit-logged**: every `--approve` boundary crossing emits an
`audit-logger.writeAuditLog({ action: 'scope_boundary_approved', details: {
sprintId, from, to, trustLevel, stopAfter, approvedBy, reason } })` entry.
The `--reason "..."` value is the recorded rationale (null when omitted).
- **Without `--approve` the legacy deadlock behavior is preserved**: handler
returns `{ ok: false, reason: 'requires_user_approval', stopAfter, hint }`.
Use this when you want to advance past the scope boundary for one specific
transition (e.g., L2 design → do after design review) without permanently
relaxing the trust level.
#### 10.1.1.1 `--approve` does NOT bypass Quality Gate failures (v2.1.19 S1, CO-S0-6)
**Critical semantic clarification** (added v2.1.19 S1 in response to S0
discovery of ambiguity — master plan carry-over CO-S0-6):
`--approve` is the **Trust Level scope-boundary** escape hatch ONLY.
It is **NOT** a Quality Gate override mechanism.
| Situation | `--approve` works? | Correct remediation |
|-----------|--------------------|---------------------|
| Trust scope blocks transition (`requires_user_approval`) | ✅ Yes — single-use cross | Re-issue with `--approve --reason "..."` |
| Quality Gate fails (`gate_fail`, e.g., M8=not_measured) | ❌ No — gate still blocks | Run `/sprint measure <id> --gate <key>` first, then re-issue `phase` |
| Both scope + gate fail | ❌ Gate wins | Measure gate, then `--approve` if scope still blocks |
**Why this matters**: in v2.1.19 S0 (master plan §23 step 0) we attempted
`/sprint phase s0-sqm-baseline --to plan --approve` and observed
`{ ok: false, reason: 'gate_fail', ... }` despite `--approve`. This is
expected behavior — `--approve` does not satisfy `M8 designCompleteness`.
**Future work (deferred to v2.1.20+)**: `--allowGateOverride` flag may be
introduced as a *gate* override (with stronger audit + alarm trail than
`--approve`). Until then, gate failures must be resolved via `/sprint measure`.
### 10.1.3 Trust Level Mutation (Persistent) — v2.1.18 (Issue #101)
`/sprint trust <sprintId> --to <Level> [--reason "<text>"] [--force]`
Mutate the **stored** `sprint.autoRun.trustLevelAtStart` for a specific
sprint. Unlike `--approve` (single-use scope boundary override, §10.1.2) or
`--trustLevel L<N>` (per-call volatile override), this command **persists**
the trust level across all subsequent operations on the sprint.
**Use cases**:
- L1 sprint started conservatively, ready to escalate after design review.
- Demoting L4 sprint to L2 mid-flight after security concern.
- Recovering from L1 "preview-mode lockout" (#101 v2.1.16 root cause — @pruge
dandi-village-ledger `s1-foundation` scenario).
**Example**:
```bash
$ /sprint trust s1-foundation --to L3 --reason "P0 32/32 ready for measurement"
{
"ok": true,
"sprintId": "s1-foundation",
"from": "L1",
"to": "L3",
"reason": "P0 32/32 ready for measurement",
"actor": "user",
"forced": false,
"trustScoreAtMutation": null,
"blastRadius": "low",
"auditEntryId": "..."
}
$ /sprint measure s1-foundation --gate M1
{ "trustLevel": "L3", "mode": "record", "value": 92.3, ... } # ✦ now record mode
```
**Downgrade Guardrail**:
Major downgrades (≥2 levels, e.g. L4 → L2 or L3 → L1) require:
- `trustScore >= 80` (from `.bkit/state/trust-profile.json` `trustScore` field
— 6-component weighted sum: pdcaCompletionRate 0.25 / gatePassRate 0.2 /
rollbackFrequency 0.15 / destructiveBlockRate 0.15 / iterationEfficiency 0.15
/ userOverrideRate 0.1), **OR**
- `--force` flag (explicit override + `forced: true` audit + `blastRadius: 'high'`
for Defense Layer 6 alarm).
Minor downgrades (1-level diff, e.g. L3 → L2) are not blocked.
**Idempotent Path**:
`from === to` (e.g. `--to L3` when sprint already at L3) returns
`{ ok: true, noop: true }` and **also emits audit with `noop: true`** field
(CTO §C3 review: monitoring blind-spot prevention — surfaces automation
patterns hitting idempotent paths).
**Actor Auto-Detection** (CTO §E6 spoofing mitigation):
`actor` field is auto-detected:
- explicit `args.actor` (if 'user'|'agent'|'system'), else
- `process.env.CLAUDE_AGENT_ID` set → `'agent'`, else
- default `'user'`.
**Audit**:
Every mutation (including no-op) emits an `audit-logger` entry:
```json
{
"action": "sprint_trust_changed",
"category": "sprint",
"actor": "user",
"target": "s1-foundation",
"targetType": "feature",
"blastRadius": "low",
"details": {
"sprintId": "s1-foundation",
"from": "L1",
"to": "L3",
"reason": "...",
"trustScoreAtMutation": null,
"forced": false,
"noop": false,
"actor": "user",
"timestamp": "2026-05-21T..."
}
}
```
**Comparison Table**:
| Command | Scope | Persistence | Use When |
|---------|-------|------------|----------|
| `/sprint phase --to ... --approve` | Single transition | Single-use (no state change) | One-time boundary override (#95) |
| `/sprint trust --to <L>` ✦ | Whole sprint (this sprint only) | Persistent (sprint.autoRun.trustLevelAtStart) | Permanent policy change for this sprint |
| `/bkit:control level <N>` | Global (all sprints + PDCA) | Persistent (~/.bkit/state/control.json) | Global automation policy change |
| `--trustLevel <L>` (per-call) | Single call | Volatile (no state change) | One-time debug override |
### 10.2 Trust Level Acceptance
All actions that accept a Trust Level recognize three input forms (handled
by `normalizeTrustLevel` in `scripts/sprint-handler.js`):
- `args.trustLevel` (preferred, explicit handler arg)
- `args.trust` (CLI `--trust L3` natural mapping)
- `args.trustLevelAtStart` (stored property leak; defensive only)
Precedence: `trustLevel > trust > trustLevelAtStart`. Defaults to **`L2`**
when none provided or value is invalid (case-insensitive match against L0-L4).
**v2.1.19 S1 F1-4 default change**: default lowered from `L3` to `L2` per
Safe Defaults principle (master plan §3.2 Controllable AI Principles). The
handler now aligns with `lib/domain/sprint/entity.js createSprint` which
already defaulted to `L2` — eliminates the v2.1.16~v2.1.18 drift between
handler default (L3) and entity default (L2).
**`--trust L1` explicit warning**: when the user explicitly requests L1 at
`/sprint init`, the handler emits a `stderr` warning + audit
`sprint_trust_warning` event re: preview-mode lockout risk
(v2.1.18 #101 follow-up). The warning is education-only — L1 sprint init
still succeeds.
### 10.3 Natural Language Mapping Rules
When the user invokes the skill with mixed slash command + natural language
(e.g., `/sprint start S1-UX Phase 1 PRD please proceed thoroughly`), the
LLM dispatcher SHOULD:
1. **Extract action**: first non-flag token after `/sprint` → `action`.
2. **Extract id (kebab-case)**: scan remaining tokens for the first kebab-case
identifier (matches `/^[a-z][a-z0-9-]{1,62}[a-z0-9]$/`). Lowercase if
needed. Example: `S1-UX` → `s1-ux`.
3. **Disambiguate via AskUserQuestion**: if multiple kebab-case candidates
or none, prompt the user to confirm the intended sprint id.
4. **Load name from state**: for `start` action on an existing sprint, the
`name` field can be resolved by `handleStatus({ id })` first; otherwise
fall back to the id itself.
### 10.4 Example — Resume Existing Sprint
```text
User: /sprint start s1-ux
LLM dispatch:
1. action = "start", id = "s1-ux"
2. status = await handleSprintAction("status", { id: "s1-ux" })
3. name = status.sprint.name // "S1-UX P0/P1 Quick Fixes"
4. await handleSprintAction("start", { id: "s1-ux", name })
5. Handler invokes load-then-resume path (P0 fix) — phase preserved
```
### 10.5 Example — Ambiguous Natural Language
```text
User: /sprint start S1-UX Phase 1 PRD proceed thoroughly
LLM dispatch:
1. action = "start"
2. Candidates: ["s1-ux"] (kebab-case extracted from "S1-UX")
3. AskUserQuestion: "Did you mean to start sprint 's1-ux' and continue
with Phase 1 (PRD)?" → user confirms
4. await handleSprintAction("start", { id: "s1-ux", ... })
```
### 10.6 Error Handling
Handler returns `{ ok: false, error: <string>, ... }` on failure. LLM
dispatcher SHOULD surface the error verbatim to the user and offer
remediation (e.g., for `error: 'Sprint not found'`, suggest `/sprint list`).
### 10.7 CLI Mode (P1 fix)
The same handler is invokable as a standalone CLI when run as
`node scripts/sprint-handler.js <action> [id] [--flags]`. Useful for
headless tests, debugging, and CI integration. The CLI parser accepts
`--key value` and `--key=value` forms, with the first positional argument
after `action` treated as `id` if no `--id` flag is provided.
Exit codes: `0` (success), `1` (handler returned `ok: false`), `2`
(exception thrown).
## 11. Master Plan Generator (16th Sub-Action)
The `master-plan` action generates a multi-sprint roadmap via the
`bkit:sprint-master-planner` agent (isolated subagent spawn) and persists
both markdown documentation and state JSON.
### 11.1 Workflow
```
USER: /sprint master-plan q2-launch --name "Q2 Launch" --features auth,payment
|
SKILL.md dispatches -> scripts/sprint-handler.js handleMasterPlan
|
handleMasterPlan calls lib/application/sprint-lifecycle/master-plan.usecase.js generateMasterPlan
|
generateMasterPlan validates input + loads existing state (idempotent check)
|
If deps.agentSpawner provided: spawn bkit:sprint-master-planner agent -> markdown
If not: dry-run via templates/sprint/master-plan.template.md substitution
|
Atomic write: .bkit/state/master-plans/<projectId>.json (state first)
|
File write: docs/01-plan/features/<projectId>.master-plan.md (markdown)
|
Audit: lib/audit/audit-logger.js writeAuditLog({ action: 'master_plan_created' })
|
Optional Task wiring: deps.taskCreator called N times for N sprint tasks
```
### 11.2 Idempotency + Force Overwrite
- Default: idempotent. Second call with same projectId returns existing plan.
- `--force` flag: overwrites both state JSON and markdown. Audit entry has
`details.forceOverwrite: true`.
- Audit ACTION_TYPE remains `'master_plan_created'` for both cases (PM-S2G).
### 11.3 Dry-Run vs Agent-Backed Generation
When the caller (LLM dispatcher at main session) does NOT inject
`deps.agentSpawner`, the use case generates a minimal valid markdown by
substituting variables in `templates/sprint/master-plan.template.md`. The
output is a skeleton — header, context anchor placeholders, empty features
table, empty sprints array. This dry-run mode is useful for unit tests and
when the user wants a starting template to fill manually.
When `deps.agentSpawner` is injected, the use case calls it with
`{ subagent_type: 'bkit:sprint-master-planner', prompt: <built> }` and uses
the returned `output` field as the markdown content.
### 11.4 State Schema v1.0
The state JSON at `.bkit/state/master-plans/<projectId>.json`:
```json
{
"schemaVersion": "1.0",
"projectId": "q2-launch",
"projectName": "Q2 Launch",
"features": ["auth", "payment", "reports"],
"sprints": [],
"dependencyGraph": {},
"trustLevel": "L3",
"context": { "WHY": "", "WHO": "", "RISK": "", "SUCCESS": "", "SCOPE": "" },
"generatedAt": "2026-05-12T20:00:00Z",
"updatedAt": "2026-05-12T20:00:00Z",
"masterPlanPath": "docs/01-plan/features/q2-launch.master-plan.md"
}
```
The `sprints` array is populated by the S3-UX `context-sizer.js` use case.
S2-UX leaves it as an empty stub.
### 11.5 Task Management Integration (Optional)
When the caller injects `deps.taskCreator`, the use case iterates
`plan.sprints` sequentially (ENH-292 caching alignment) and calls
`deps.taskCreator(...)` once per planned sprint with `addBlockedBy` populated
from the previous sprint's task ID. This enables automatic Task list creation
for multi-sprint roadmaps.
When `deps.taskCreator` is undefined or `plan.sprints.length === 0`, Task
creation is silently skipped (no error).More Project Management skills
firecrawl-build-onboarding
firecrawl/skills
Get Firecrawl credentials and SDK setup into a project. Use when an application needs `FIRECRAWL_API_KEY`, when an agent should add Firecrawl to `.env`, when the user wants to authenticate Firecrawl for app code, or when choosing the first SDK and docs for a new Firecrawl integration. This skill includes its own browser auth flow, so it does not depend on the website onboarding skill.
email-sequence
coreyhaines31/marketingskills
When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions "email sequence," "drip campaign," "nurture sequence," "onboarding emails," "welcome sequence," "re-engagement emails," "email automation," "lifecycle emails," "trigger-based emails," "email funnel," "email workflow," "what emails should I send," "welcome series," or "email cadence." Use this for any multi-email automated flow. For cold outreach emails, see cold-email. For in-app onboarding, see onboarding-cro.
onboard
pbakaus/impeccable
Designs and improves onboarding flows, empty states, and first-run experiences to help users reach value quickly. Use when the user mentions onboarding, first-time users, empty states, activation, getting started, or new user flows.

