Design
Use when a validated requirement set exists and the user is ready to turn it into an architecture — guides an architecture interview and a multi-agent pipeline that produces atomic component and interface specs before any code is written.From its SKILL.md
npx -y skills add Stormbreaker9000/groundwork --skill designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
21.8 KB, as published. Nobody here has run it
Design
Turn a validated requirement set into a structured architecture artifact through
an interview that covers what requirements deliberately cannot carry, followed by
a multi-agent generation pipeline. This is phase 2 of the groundwork SDLC
workflow — it follows requirements and precedes implementation.
When This Applies
Invoke when a validated requirement set exists under .sdlc/requirements/ and
the user is ready to turn it into an architecture:
- "Design this"
- "Let's do the architecture"
- "Turn the requirements into components"
- "What should the system look like structurally?"
Do NOT invoke for:
- Questions or explanations
- Bug reports
- Requests to read, explore, or explain existing code
- A request to build something for which no requirement set exists yet — send
the user to the
requirementsworkflow first
Do not write any application code at any point during this skill. This
skill produces design artifacts only — component and interface specs, ADRs,
plus assumptions.md and drivers.md. Nothing under .sdlc/design/ is
executable.
Phase 1 — Locate and Read the Input
Find .sdlc/requirements/. If it is absent, stop and direct the user to the
requirements workflow — there is nothing to design against.
Run the entry gate:
python3 skills/requirements/scripts/validate_requirements.py .sdlc/requirements
A non-zero exit stops the stage: designing against a structurally invalid
requirement set is meaningless. Fix or send the user back to requirements
before proceeding.
This is a structural gate only. A non-empty review_queue in index.yaml
does not block — do not treat it as a defect to clear before moving on.
Those low-confidence requirements and the open questions in assumptions.md
are frequently architecture decisions that correctly landed in the
requirements stage's out-tray. They are carried forward on purpose and opened
with, not resolved here in Phase 1 — see Phase 3.
Once the gate passes, read:
- Every requirement file (functional, non-functional, constraints, business rules, use cases)
index.yaml'sreview_queueassumptions.md's## Open Questions
If an existing codebase is present, scan it the same way requirements
does — a bounded 3–5 file read (root config, entry point, most relevant
existing modules), not a full audit. Stop once you have enough to form
grounded hypotheses about the runtime and stack in Phase 2.
Phase 2 — Hypothesise
One message, one question — the same shape as M1's hypothesis phase.
Propose:
- A candidate decomposition: 4–6 named components in plain terms (not yet
CMP-IDs — those are allocated by the orchestrator in Phase 5) - A stack hypothesis: your best guess at runtime, persistence, and deployment target, grounded in the requirement set and any codebase scan from Phase 1
Present as a single message and ask whether it matches.
Example — the tamagotchi requirement set:
"Based on the requirements, here's a candidate decomposition: a Pet State Store (persisted state, single source of truth), a Decay Engine (time-based state degradation, including offline-elapsed catch-up), a UI Renderer (mood display, interaction surface), an Input Handler (feed/play/clean/sleep actions), and a Save/Recovery layer (corrupted-file recovery, per NFR-004). Given the offline-only, single-user, low-footprint constraints, I'd guess a lightweight desktop-app stack with local file-based persistence and no backend service — but the specific runtime is still open (see Q-4 below). Does this decomposition match your vision, or are there pieces missing or wrong?"
This is ONE question. Do not ask multiple questions in this message.
Phase 3 — Architecture Interview
Six coverage areas the requirement set cannot carry, by construction:
- Runtime and stack — language, framework, runtime
- Persistence — storage mechanism, data model shape
- Deployment target — where this runs (desktop, server, edge, mobile, CLI)
- Integration points — external systems, third-party services, APIs
- Operational constraints — hosting, monitoring, on-call, resource budgets
- Team constraints — existing team skills, timeline, org standards
Why this interview exists. The requirement set cannot carry this
context — that is by construction, not omission. M1's content linter treats
implementation bias as a defect and its critic flags it, so nothing in
.sdlc/requirements/ says "Tauri" or "Postgres", and nothing should. This
stage therefore either asks or invents. The project's own history settles
which: an earlier build took an unexamined Electron recommendation and paid
to rip it out later. So this stage asks.
Open with the inherited open questions. Many of the Q- items in
assumptions.md are architecture decisions by nature — they landed in the
requirements stage's out-tray because they genuinely belong here, not because
they were missed. Surface them first, before the six coverage areas, not
after.
Worked example. The tamagotchi requirement set left Q-4 open: "Which
framework/runtime is chosen given the footprint constraint (Electron vs Tauri
vs native)?" NFR-002 (idle CPU/memory budget) and CON-001 (runtime
footprint boundary) both sit in review_queue because they rest on this
question. This is exactly this stage's call to make — it goes first:
"The requirements stage left one open question for architecture: Q-4 — which framework, given the footprint constraint? (1) Electron, (2) Tauri, (3) a native toolkit per platform. Idle CPU/memory (NFR-002) and the runtime footprint boundary (CON-001) both depend on this answer. Pick one, or describe another."
Rules for the remaining six areas:
- One question per message.
- Prefer 2–4 numbered options over open-ended questions when the answer
space is enumerable — this measurably improves answer quality, the same
rationale
skills/requirements/SKILL.mdapplies to its own interview. Reserve open-ended questions for genuinely open spaces. For example: "For persistence, should the pet state live in (1) a single local JSON/binary file, (2) an embedded database (e.g. SQLite), or (3) something else? Pick one, or describe another." - Infer from the codebase where obvious. Only ask what you cannot
determine. If Phase 1's scan already shows a Postgres connection string and
a
docker-compose.yml, do not ask about persistence or deployment target — state the inference and ask only for confirmation, or skip asking entirely if it is unambiguous. - A well-scoped request typically needs a handful of exchanges once the inherited questions are resolved. A greenfield system with no prior decisions may need more.
Proceed to Phase 4 once all six areas are covered (by answer or by confident
inference) and every inherited open question has a recorded disposition —
resolved (with the resolution) or still_open.
Phase 4 — design_context Synthesis
Before dispatching the pipeline, synthesise everything elicited into a
structured context object. This confirms shared understanding and serves as
the direct input to the design-orchestrator.
Render in-conversation:
**Design context:**
**System purpose:** ...
**Runtime & stack:** ...
**Persistence:** ...
**Deployment target:** ...
**Integration points:** ...
**Operational constraints:** ...
**Team constraints:** ...
**Out of scope:** ...
**Inherited questions:** [each Q-# with resolved / still open]
**Inherited review queue:** [requirement IDs, or "None"]
Ask: "Does this capture the design context correctly, or should I adjust anything before generating the architecture?"
Do not proceed to Phase 5 until the user confirms. If corrections are needed, update the context object and re-confirm. This is a hard stop, not a formality — nothing downstream runs on an unconfirmed context.
Phase 5 — Generate
The confirmed Phase 4 block serialises 1:1 to the design_context the
design-orchestrator consumes:
design_context:
requirements_root: ".sdlc/requirements"
system_purpose: string # restated from the requirement set, not re-elicited
runtime_and_stack: string
persistence: string
deployment_target: string
integration_points: string # external systems → boundary: external components
operational_constraints: string
team_constraints: string
out_of_scope: string # or "None identified"
inherited_open_questions:
- id: Q-4 # ID preserved from requirements/assumptions.md
statement: string
disposition: resolved | still_open
resolution: string # present only when resolved
inherited_review_queue: [ NFR-002, CON-001 ]
Step 1 — Generate (multi-agent pipeline):
Drive the pipeline through the agents under agents/, in this fixed order:
- design-orchestrator — reads the requirement set once on everyone's
behalf, identifies architecturally significant requirements (ASRs),
allocates
CMP-/IF-ID blocks, and dispatches ageneration_briefto each specialist. - component-specialist — decomposes the system into components, each with a single declared responsibility, tracing to the requirements that drove it.
- interface-specialist — receives the component set and turns every
declared capability into an interface with a
provider, operations, interaction style, and error modes. - design-critic — runs a two-phase review, judgment only: per-artifact
quality (ISO/IEC/IEEE 42010) and ASR coverage with tradeoffs and
sensitivity points named (ATAM-lite). Returns
gate: passorgate: fail. It does not runvalidate_design.py— nothing is on disk yet at this stage, anddrivers.md's gated headings are this critic's own output, so the structural check belongs downstream, at the formatter. - adr-generator — dispatched at Stage 9.5, after
gate: pass. Promotes resolvedQ-decisions anddeferred_to_decisionASRs into architecture decision records; never invents a rejected option, so a decision whose alternatives can't be recovered stays indrivers.mdand is reported inskippedinstead. Returnsdraft_adrs— an empty set is legal and means nothing qualified. - c4-generator — dispatched at Stage 9.6, after the ADR generator.
Supplies the two judgments the component and interface frontmatter cannot
carry — which components group into which deployable container, and who
the system's external actors are. Writes no file and authors no Mermaid;
it returns a
draft_diagram_modelthatgenerate_c4.pyprojects into the three C4 views inside the formatter's write. - design-formatter — writes the atomic component/interface/ADR files plus
assumptions.mdanddrivers.md, andindex.yaml'sreview_queue, back-fillstraces_to.adron the artifacts each ADR affects, runsgenerate_c4.pyagainst thedraft_diagram_modelto project the C4 views intodiagrams/, back-fillstraces_to.diagramson the components each diagram depicts, indexes the diagrams alongside every other artifact inindex.yaml, then re-runsvalidate_design.pyagainst everything it just wrote, diagrams included — the pipeline's single structural gate (see Step 4). Runs only ongate: pass. Do not advance past the critic on a failing or partial gate — the orchestrator re-dispatches only the affected artifacts back to their owning specialist and re-runs the critic.
Step 2 — Render in-conversation summary (before writing anything):
## Design Summary: <Feature Name>
**Overview:** [2-3 sentences: what's being architected, and the core shape of the solution]
**Components:**
- CMP-001 <title> — <one-line responsibility>
**Interfaces:**
- IF-001 <title> — provider: CMP-XXX, interaction: synchronous | asynchronous | mixed
**ADRs:**
- ADR-001 <title> — decision_status: accepted | proposed
**Diagrams:**
- DIA-001 System Context
- DIA-002 Container View
- DIA-003 Component View — <container>
**Decisions not recorded:**
- <source> — <reason>, or "None"
**Drivers:**
- ASRs: [requirement ID → why it shapes structure]
- Tradeoffs: [decision → gains vs. costs]
- Sensitivity points: [what would change the decision]
**Assumptions & Dependencies:** [key A-#/D-# items, or "None identified"]
**Open Questions:** [Q-# items still open, or "None"]
**⚠️ Triage before sign-off — review these specifically:**
- **Low-confidence artifacts:** [each `confidence: low` CMP/IF/ADR ID with its one-line reason — or "None"]
- **Open questions:** the items listed under **Open Questions** above.
These are the uncertain items; confirm or correct *these* rather than re-scanning the whole set. The same low-confidence list is persisted as `review_queue` in `index.yaml`.
**Next Step:** Implementation
interaction is declared per operation, so render mixed here when a
contract's operations disagree. It is computed for this summary only and is
never written to an artifact.
Render ADRs from draft_adrs.adrs — every ADR the generator emitted, with
its decision_status so the user can see at a glance which decisions were
actually recorded versus left pending. Render Decisions not recorded from
draft_adrs.skipped — each entry's source and reason, or "None" when
skipped is empty. This is the one point in the pipeline where skipped
reaches a human: it is produced at Stage 9.5 and otherwise carried only as
far as the formatter hand-off, so without this block a decision that did not
become an ADR is visible nowhere the user will ever look. Surfacing it here,
before any file is written, is also the only point at which it is actually
actionable — the user can ask for it to be revisited before sign-off, not
after.
Diagrams are derived from the component graph and the container grouping, so they are listed for orientation rather than review — the grouping itself is what the user should check, and it appears as the container names.
Step 3 — Sign-off gate:
Ask: "Does this capture the architecture accurately, or should we adjust anything before I write the files?"
No files are written until the user confirms. If corrections are needed, re-dispatch the affected artifacts to the owning specialist via the orchestrator, then re-summarise. This mirrors M1's invariant exactly and it is not relaxed here.
Step 4 — Write, then validate (hard gate):
On confirmation, run the formatter. Inside its write, order is fixed: the
CMP/IF/ADR files first, then assumptions.md and drivers.md —
drivers.md specifically, because the Context view's traces_from is
parsed from its ## Architecturally Significant Requirements section —
then generate_c4.py to project the C4 views, then the traces_to.diagrams
back-fill onto the components it names, then index.yaml. A generate_c4.py
exit 1 is a model failure, not a write failure: it means the model
contradicts the design set, so it re-dispatches to the c4-generator rather
than being repaired by hand. Exit 2 is an environment error (missing
directory, unreadable model), not a design failure.
Only then does the formatter, as part of its own contract, immediately
re-run the structural validator against everything it just wrote, diagrams
included (agents/design-formatter.md's "Validator re-run" section) — this
is the pipeline's single structural gate, and it is the first point at which
structure can be checked, since nothing was on disk before now. The
critic's earlier gate: pass was judgment only (per-artifact quality and ASR
coverage); it never ran this command.
python3 skills/design/scripts/validate_design.py .sdlc/design
The validator MUST exit 0. If it exits non-zero, do not treat the write as
done: fix the flagged files (re-dispatch to the owning specialist through the
critique loop) and re-run until clean. It requires pyyaml and jsonschema
(pip install pyyaml jsonschema); see skills/requirements/scripts/README.md
for the install and fallback details (the design validator shares the same
dependency story).
The formatter then runs the cross-artifact validator, which resolves the requirement↔design edge neither structural validator checks:
python3 skills/design/scripts/validate_traceability.py .sdlc/design \
--requirements .sdlc/requirements
It must also exit 0. Its errors are a design artifact citing a requirement
that does not exist, an ADR listing an unresolvable decision driver, and a
requirement with a requirement ID parked in traces_to.design/tests/code
— slots that hold design-artifact, test and source-file references. Its
warnings do not block: an FR no component addresses, an ADR body driver
missing from its own frontmatter, a requirement ID mentioned in an ADR's
drivers prose rather than listed as one, and the two index caveats below.
Exit 2 is neither: it means one of the two directories is missing, produces no findings, and is an environment problem to report as such — not a traceability failure to chase through the fixes below.
The errors do not share one fix:
dangling-traceandadr-driver-unresolvedflag a design artifact. Fix them the same way avalidate_design.pyfailure is fixed: re-dispatch the named artifacts to their owning specialist through the critique loop, then re-run until clean.dangling-reverse-traceandmisplaced-requirement-traceflag a requirement file, and this stage never writes into.sdlc/requirements/— the requirement→design edge is stored once, ondesign.traces_from. So there is nothing to re-dispatch and no loop to run. Report them to the user and stop, passing the validator's lines through as they are: each already names the requirement ID, its file path in trailing brackets, and the exact edit to make. Then re-run the design stage. Requirement sets written before these rules existed carry requirement IDs in those slots, which is precisely what they catch — so on an older project, expect them, expect the fix to be a hand edit in the requirements stage, and note that there is deliberately no migration script: rewriting requirement files from the design stage would make it a second writer.
index-unparseable and duplicate-id are warnings, but do not report them
as ordinary ones. They say the sweep ran over an index that was missing a
file or had collapsed two artifacts into one ID — so every other result on
that run, a clean one included, is unreliable in both directions. Tell the
user the sweep could not see the whole set, and what to fix, before you tell
them what it found.
Those warnings arrive after the write, not at the Step 3 sign-off. That ordering is inherent — nothing is on disk before the formatter runs, and computing coverage over drafts is the unreachable-gate mistake STO-215 fixed.
Then run the advisory content-quality linter and address any warn-severity
findings (the two validators above are the hard gates; the content linter guides
prose and shape). This is the only script-backed lint run in the stage — the
critic applied the same checks by inspection at gate time, because the files did
not exist yet. Route anything it turns up back through the critique loop to the
owning specialist rather than editing the written files by hand:
python3 skills/design/scripts/lint_design_content.py .sdlc/design
It always exits 0. dependency-cycle is the finding most worth acting on: it
means two components each need the other, which no structural check can see
because every individual edge resolves. Breaking it is a decomposition change,
so it re-dispatches to the component specialist, not the interface specialist.
Step 4b — Report traceability warnings:
Read formatter_result.traceability_rerun.warnings (empty if the sweep was
clean, not skipped) and surface them to the user before committing: each
uncovered-fr or adr-driver-untraced line, as returned. They are advisory
and do not block the commit — acting on them is the user's call, not a
condition of Step 5.
Step 5 — Commit:
git add .sdlc/design/
git commit -m "docs: add design artifact set for <feature-name>"
ADRs
This stage writes architecture decision records to .sdlc/design/adr/ in MADR
4.0 format, one atomic file per decision, validated by the same structural gate
as components and interfaces.
ADRs are derived, never elicited. The generator promotes decisions the
pipeline already recorded — resolved Q- questions from the architecture
interview, and ASRs the critic marked deferred_to_decision — and it never
invents a rejected option to fill out the template. A decision whose
alternatives cannot be recovered stays in drivers.md and is reported in the
generator's skipped list.
So an empty or absent adr/ directory is a legal outcome: it means nothing
qualified, not that something failed.
What This Stage Does Not Produce
C4 diagrams are produced, but not by this skill's judgment either — the
c4-generator supplies container grouping and actors at Stage 9.6, and
generate_c4.py projects the component graph into Context, Container and
Component views inside the formatter's write, before the structural gate.
Cross-artifact traceability is resolved, but not by this skill's judgment —
validate_traceability.py runs at Step 4 as a second hard gate and owns
traces_from resolution, FR coverage, ADR decision-driver resolution, and
traces_to.design resolution.
Dependency-cycle detection, orphan-interface detection, and prose-quality
sweeps over design artifacts are produced, but not by this skill's judgment
either — lint_design_content.py runs at Step 4, advisory, once the files
exist, per agents/design-critic.md's Scope boundaries.