- name
- lakebase-sftdd-workflows
- description
- Spec-First Test-Driven Development (SFTDD) with evolutionary design, against paired Lakebase branches: the design lane is Spec Driven Development (SDD) and the build lane is canonical Beck-style Test Driven Development (RED-GREEN-REFACTOR), composed with paired-branch primitives (cheap experiments, parent-aware schema diff, real per-branch databases). Spec-first means the spec is drafted, reviewed, and frozen at gates before any build cycle runs; evolutionary means the spec, the architecture, and the database all evolve increment over increment. Use when planning a new feature, running design-spec gates, running TDD cycles, comparing parallel experiments, or detecting workflow bad smells. Imports software-design-principles canon. Builds on lakebase-scm-workflows + lakebase-release-workflows.
- user-invocable
- true
# lakebase-sftdd-workflows – agent contract
Agent-facing contract: hard rules, phase flow, agent prompt index, and concrete code patterns for the substrate primitives.
For the human-facing overview (lexicon, roles narrative, how-to-use prompts, project entry points) see [`README.md`](README.md).
## Hard rules
The contract every agent (Navigator, Driver, Orchestrator) and every human collaborator must honor.
1. Tests are immutable until the test list itself is renegotiated through the PO. Never delete or weaken a test to make it pass.
2. "Minimal code" means minimal *honest* code that satisfies the current test list, not just the current test. Use the test list as your horizon.
3. After every GREEN, ask: "would a fresh reader infer the right concept from this API now?" If no, request REFACTOR before the next test.
4. Test at the outermost public boundary that maps to the AC. Inner-loop unit tests are reserved for pure logic that can't be exercised through the outer boundary.
5. A correct refactor should not change the outer-boundary tests. A refactor that requires editing tests is suspect.
6. Never make a private method public to test it.
7. Test count is a lagging indicator. The leading indicator is "how cheap is the next test?" Rising cost = design problem.
8. Spike code is throwaway. Promote nothing from a spike branch into a TDD branch except notes.
9. Experiments are scoped to a story (the branch forks from feature HEAD). N=1 is one experiment per story (iterative refinement, no promote/synthesize ceremony); N>=2 races competing strategies for that story. The PO accepts a story's experiment by **merge** (git-merge + run its migrations against the feature branch DB), or discards/revises it.
See [`agents/navigator.md`](agents/navigator.md) and [`agents/driver.md`](agents/driver.md) for per-role specializations.
## Phases and gates
The kit is **Spec-First Test-Driven Development (SFTDD)**: it composes two disciplines back to back. The **design lane is Spec Driven Development (SDD)** – spec drafting, architectural review, test-list construction, all driven by `/design` – and the **build lane is Test Driven Development (TDD)** – the RED → GREEN → REVIEW → REFACTOR cycles driven by `/build`. Spec-first means SDD freezes the spec at the `spec` + `test_list` gates; TDD only starts once they are approved, so the build always runs against a reviewed spec.
**Iterative and evolutionary.** The freeze is per increment, not forever. Across increments, all three dimensions evolve and are never treated as static: the **spec and features** are living , each sprint the PO re-plans, folding in what the last working software revealed; the **architecture** evolves under fitness functions (`@architectural-design-principles/evolutionary-architecture.md`); and the **database** evolves by migration on the paired branch, diffed against its parent (`@architectural-design-principles/evolutionary-database-design.md`). The rule is: spec-first within an increment, evolutionary across increments.
Gates are keyed (not numbered): `spec` / `plan` / `test_list` / `promote` / `deploy`. The SDD lane runs PER STORY (it streams), and experiments + plans are per-story.
| Step (per story unless noted) | Output | HITL gate |
|---|---|---|
| Spec drafting | `feature-spec.{md,json}` (feature) + per-story `story.{md,json}` + `acs/<AC>.{md,json}` | **`spec` gate** |
| Architectural review | `layer` + `architectural_notes` on each AC; `architecture.{md,json}` (holds the NFRs) | folds into the `spec` gate |
| Test-list construction | per-story `test-list-per-story.json` (scoped from the feature `test-list.{md,json}`) | **`test_list` gate** |
| Build (per AC) | cut a per-story experiment; RED -> GREEN -> REVIEW -> REFACTOR cycles producing tests + code | Continuous: smells; per story: **accept (merge) / discard / revise** |
| Deploy | working software on the experiment branch (reachable + verify) | **`deploy` gate** |
Sprint planning has its own **`plan` gate**. For N>=2 experiments within a story, the menu-pick promote/synthesize decision is recorded under `synthesis/<F>/`. Refuse to transition if prior-step artifacts are missing or invalid.
### Enhancement review (placeholder, TODO)
Enhancements are decided iteratively. After a feature ships, new work is proposed and prioritized with the Product Owner during sprint planning (`/plan`) - the same gate that commits any sprint - so the loop keeps returning to the PO for the next increment.
**TODO (not yet implemented):** add a review role that inspects the **running, deployed software** (post-`deploy`) and recommends concrete enhancements back to the PO as candidate features for the next `/plan`. This mirrors the existing review lens (the Architect Reviewer / Navigator review the spec and code) but aimed at observed runtime behavior rather than source. To flesh out: the trigger point (post-`deploy`), the inputs (the reachable endpoint + `feature-status`), the output (enhancement candidates feeding `planning/feature-proposals.md`), and the PO hand-off. Until this lands, enhancements are surfaced manually at sprint planning.
The phases + gates above are the PER-FEATURE pipeline that `/design` (phases 0 to 2 + gates 1 to 4) and `/build` (phase 4) run. They sit inside a larger orchestrated loop:
## Orchestrated commands (the dev loop)
Every command is a thin invocation of the deterministic orchestrator driver (`lakebase-sftdd-drive`), scoped to a phase range. The driver sequences the work and spawns each role as a subagent (`claude -p --agent <role>`); routing is code, not an LLM. Gates always pause for a human decision: `--gates interactive` (the default for the live slash commands) stops at each gate so the human answers; `--gates proxy` (headless / CI) has the Human Proxy answer.
```
Tier 1: /sprint = plan ─> [PLAN GATE] ─> per feature: /design ─> /build ─> /deploy
▲ │
└──────────────────── working software feeds back ─────────────────┘
Tier 2: /plan /design /build /deploy (run ONE phase, then stop + suggest next)
/spike (throwaway exploration, outside the loop)
```
- **`/sprint [name]`** (Tier 1, the top-level orchestrator): runs the whole sprint as one continuous flow, plan to the plan gate, then claim + drive each backlog feature `design` -> `build` -> `deploy`. Re-invoked per cycle; resumable (halts at the next HITL gate for the human, continues on re-run). `lakebase-sftdd-drive --sprint <name>`.
- **`/plan [name]`** (Tier 2, sprint planning, ABOVE the per-feature loop): the **Spec Author** proposes the candidate breakdown (`.sftdd/planning/feature-proposals.md`); the **Architect** t-shirt-sizes the candidates (`.sftdd/planning/estimates.json`, XS/S/M/L/XL); the **Product Owner** commits the backlog by authoring a `feature-request.md` per feature that fits sprint capacity; the deterministic `sync-backlog` step projects `.sftdd/sprints/<name>/backlog.json` (committed ids + sizes); the **sprint plan gate** is the HITL checkpoint. Stops there (does not flow into design). Requires project intake (`product-overview.md` + `nfrs.md`, +`design-brief.md` for UI) as a precondition. `--sprint <name> --plan-only`.
- **`/design <feature-id>`**: the **SDD (Spec Driven Development)** lane. Claims the paired branch (Step 0), enforces the feature's `feature-request.md` + project intake (Step 0.5, a precondition, NOT a gate), then drives the per-story design lane (Spec Author -> Architect Reviewer -> Test Strategist) to the spec + test_list gates, producing the executable spec. `--only design`.
- **`/build <feature-id>`**: the **TDD (Test Driven Development)** lane. RED -> GREEN -> REVIEW -> REFACTOR cycles + per-story acceptance against the frozen spec, to ready-for-review (requires the SDD lane done). `--only build`.
- **`/deploy <feature-id> [--target local] [--story <s>]`**: deploys the merged feature (or one story's branch) + verifies reachable + feature-verify; the **deploy gate** is the working-software review the PO signs off (the local target is the only one implemented; remote release is the scaffolded `merge.yml`). `--only deploy`. For a hands-on review the human can run `./scripts/run-dev.sh` to serve the app locally (migrates + hot-reload) and open it in a browser.
- **`/spike <slug> [--for <feature>]`**: throwaway exploration on its own paired branch, OUTSIDE the workflow (no gates). Notes carry forward into a feature's design-spec gate; code is never promoted. `lakebase-sftdd-spike`.
The same orchestrated path runs for real and headless; headless, the Human Proxy stands in for the human at every supply + gate (below).
## Headless / Human Proxy mode
By default every gate is HITL (the workflow halts for the Product Owner). When `LAKEBASE_SFTDD_HUMAN_PROXY=1` (set by CI and the smoke), the approver role is **performed by** the `human-proxy` identity, a diligent stand-in, not a rubber stamp. For the artifact gates (`spec`/`plan`/`test_list`/`promote`), it approves a `gates.json` gate and emits `gate.approved` only when both hold (the `deploy` gate is certified differently, see the `/deploy` bullet below):
- **Given the artifacts:** the gate's expected artifacts EXIST (a missing one is refused).
- **Format-conformant:** each validates against its declared format (JSON against its schema; narrative MD against its required sections, see `references/spec-format.md` + `lakebase-sftdd-gate-conformance`). A malformed artifact, or one missing a required section, is refused.
So the producing role's job here is to HAND the approver complete, conformant artifacts, recording its recommended resolutions (decisions, NFR acceptances, orderings) INSIDE them rather than leaving open questions for a human reply. A gate advances because real well-formed work was verified, never because it was skipped; a missing/malformed artifact hard-blocks in CI exactly as for a human.
Beyond the gates, the Human Proxy stands in wherever the path needs human input (`lakebase-sftdd-human-proxy` has two subcommands, `supply` and `approve`; both validate-then-place, neither fabricates or skips):
- **Project intake** (precondition of `/plan` + `/design`): `supply`s `product-overview.md` / `nfrs.md` / `design-brief.md` from `$LAKEBASE_SFTDD_RECORDED_INTAKE_DIR`; `lakebase-sftdd-intake` then passes because they're present + conformant.
- **`/plan` backlog:** the Architect sizes the candidates live; the Proxy `supply`s the recorded `feature-request.md` files (the PO's groomed sprint). `sync-backlog` projects `backlog.json` (committed ids + sizes).
- **`/deploy` gate:** confirms the app came up reachable AND the verify passed, then records `gate.approved`; never approves a non-reachable or failed-verify deploy.
Check the mode with `[ "$LAKEBASE_SFTDD_HUMAN_PROXY" = "1" ]`. Absent/unset = normal HITL.
## Configuration (one source of truth per setting)
Every knob has exactly ONE home; see [`CONFIG.md`](CONFIG.md) for the full table + writers. In brief:
- **Project settings** (what the project IS: `uiTrack`, `gates`, `deployTarget`, the per-role model matrix, build cadence) live only in `.lakebase/sftdd-config.json`, resolved **file -> code default** by `resolveSftddSettings`. There is no env or flag override at read time. The writers are create-project (create-time, e.g. `--ui-track`) and the drive's write-through flags (`--gates` / `--deploy-target` / `--no-sizing`), which persist INTO the file before it is read.
- **`uiTrack` is the single door for the UX lane.** It drives BOTH the UX Designer (design-guide / `ia.md` / adherence gate) AND the e2e harness (create-project derives e2e from it, and refuses a UI project without it). A UI project can never run with the UX lane off.
- **Run-mode knobs** (record/replay, headless, debug, e.g. `LAKEBASE_SFTDD_HUMAN_PROXY`, `_AUTO_CONTINUE`, `_RECORD_DIR`) are per-invocation `LAKEBASE_SFTDD_*` env vars, read via `sftddEnv` (one door each). They are NOT project settings and never belong in `sftdd-config.json`.
- **Capture-time conditions** live in a scenario's `scenario.json` and are funneled into create-project flags by `capture-scenario.sh`; they never reach the drive directly.
## Agent roles (the per-role agent runtime)
Each role is a separate agent definition under [`agents/`](agents/) with frontmatter (`name`, a `description` that is the auto-selection criteria, least-privilege `tools`, a strongly-recommended `model`, `memory: project`, `color`) and a body that is its system prompt. The roles communicate only through the artifacts on disk, the artifact is the inter-agent API.
- [`agents/product-owner.md`](agents/product-owner.md) – the PO's facilitator: runs the intake interviews + drafts `product-overview.md` / `nfrs.md` / `design-brief.md`, authors the sprint's `feature-request.md` files at `/plan`, and is the approver at every HITL gate. Headless, the Human Proxy plays the PO.
- [`agents/spec-author.md`](agents/spec-author.md) – the Spec Author (BA). At `/plan`, proposes the feature breakdown from `product-overview.md` + `nfrs.md` (`feature-proposals.md`, the PO's input). At `/design` phase 0, turns one feature's `feature-request.md` into the structured draft spec (`feature-spec.{md,json}` + stories + ACs).
- [`agents/ux-designer.md`](agents/ux-designer.md) – between phase 0 and 1, **UI projects only**: owns `design-guide.{md,json}` + `ia.md` and the UX adherence gate. Skipped for API/CLI/Infra-only features.
- [`agents/architect-reviewer.md`](agents/architect-reviewer.md) – phase 1, populates `layer` and `architectural_notes`, covers every `nfrs.md` Required item via `architecture.json` `brief_ref`, imports `software-design-principles`.
- [`agents/test-strategist.md`](agents/test-strategist.md) – phase 2, builds the Beck-style ordered test list.
- [`agents/navigator.md`](agents/navigator.md) – phase 4 PLAN + RED + REVIEW.
- [`agents/driver.md`](agents/driver.md) – phase 4 GREEN + REFACTOR.
- [`agents/release-engineer.md`](agents/release-engineer.md) – `/deploy`: deploys the built increment to its target, polls reachable, runs the feature verify, hands the evidence to the PO for the deploy gate. Composes on `lakebase-release-workflows` for remote/release-on-merge.
The **orchestrator** is the deterministic driver (`lakebase-sftdd-drive`), **not an LLM agent**: it routes over `workflow-state.json`, hands each phase to the right role agent above, carries artifacts forward, and surfaces every gate to the PO. It writes no spec/code/test/deploy.
**How the orchestrator runs them.** The role defs are scaffolded into the project's `.claude/agents/` (so Claude Code can discover + spawn them; the skill copy is the source). The driver computes the next action as a pure function of the recorded state, then spawns the role for that phase via `claude -p --agent <role>`. Routing is code, not a model: there is no LLM orchestrator session. Before spawning a role, the driver resolves the model from the project's `.lakebase/sftdd-config.json` via `resolveSftddSettings` (`roles.<role>.model`, the single source of truth for project settings). Resolution is `sftdd-config.json role model ?? legacy .lakebase/agent-config.json (override ?? recommended) ?? built-in recommended ?? inherit`: `agent-config.json` is honored only as a fallback for projects scaffolded before `sftdd-config.json`. The HIL sets per-project models at `lakebase-create-project`; each role's recommended model lives in its definition's `model:` (mirrored in `RECOMMENDED_MODELS`).
## References
- [`references/spec-format.md`](references/spec-format.md) – full `.sftdd/` directory layout + markdown ↔ JSON contract.
- [`references/orchestrator-contract.md`](references/orchestrator-contract.md) – how the agent DRIVING `/sprint` `/design` `/build` `/deploy` must behave: drive to completion via `lakebase-sftdd-next`, surface only HITL gates + blockers, report outcomes (not process), verbose/eval narration opt-in. The orchestrator's counterpart to `agent-operating-rules.md`; the command templates load it.
- [`references/next-schema.md`](references/next-schema.md) – the `lakebase-sftdd-next` / `.sftdd/next.json` "what next" surface the orchestrator contract drives on.
- [`references/agent-logging.md`](references/agent-logging.md) – structured agent log format + per-role emit points. Every role emits what it is doing via `lakebase-sftdd-log` (debug = reasoning, info = outputs) to the centralized `.sftdd/agent-log.jsonl`.
- `scripts/sftdd/schemas/` – JSON Schemas validated by `spec-sync.ts`.
- [`../software-design-principles/SKILL.md`](../software-design-principles/SKILL.md) – engineering canon (SOLID, DRY, clean code, layered architecture, cross-cutting concerns, NFRs). Required reading for Architect Reviewer and Navigator.
## tag → runner map
عرض على GitHub