| name | gse-design |
| description | Define architecture decisions, component decomposition, interface contracts. Triggered by /gse:design. |
GSE-One Design — Design
Arguments: $ARGUMENTS
Options
| Flag / Sub-command | Description |
|---|
| (no args) | Start design activity for the current sprint |
--decision <topic> | Log a specific architecture decision |
--show | Display current design document |
--interfaces | Focus on interface contract definitions |
--validate | Check design for completeness and consistency |
--help | Show this command's usage summary |
Prerequisites
Before executing, read:
.gse/status.yaml — current sprint number
docs/sprints/sprint-{NN}/reqs.md — requirements to design for
.gse/plan.yaml — living sprint plan (scope and constraints)
docs/sprints/sprint-{NN}/design.md — existing design (if any; authoritative format in plugin/templates/sprint/design.md)
.gse/decisions.md — previous architecture decisions (for consistency)
.gse/profile.yaml — user preferences
.gse/sources.yaml — external sources that may influence design
Workflow
Step 0 — Open Questions Gate (activity-entry scan, spec P6)
Before any architecture work, scan for pending Open Questions (OQ-) whose resolves_in: DESIGN.
- Enumerate sources — list
docs/intent.md (always) and docs/sprints/sprint-{NN}/*.md for the current sprint if it exists.
- Parse
## Open Questions sections. Extract entries where status: pending AND resolves_in: DESIGN.
- If zero matches → skip this step, proceed to Step 1.
- If ≥ 1 match → enter the Open Questions Gate per the user's
decision_involvement (see /gse:plan Step 0 for the canonical three-mode description — autonomous / collaborative / supervised). Resolutions are recorded in the origin artefact's ## Open Questions entry in place. Resolutions typically seed DEC-NNN architecture decisions in the upcoming design work (questions tagged impact: architectural are especially relevant here).
- Proceed to Step 1.
Step 1 — Scope Analysis
Identify which requirements need design work:
- Group requirements by component/module they affect
- Identify cross-cutting concerns (logging, auth, error handling)
- Detect requirements that impact existing architecture
Present scope: "Sprint S02 design covers 3 components: AuthModule (REQ-001..003), RateLimiter (REQ-007..009), WebhookHandler (REQ-012..014)."
Step 2 — Component Decomposition
For each component group, define:
Component: AuthModule
─────────────────────
Responsibility: Handle user authentication and session management
Dependencies: Database (stable), ConfigService (stable)
Dependents: APIRouter, WebhookHandler
Interface: see Step 3
Files: src/auth/authenticator.py, src/auth/session.py, src/auth/models.py
Requirements: REQ-001, REQ-002, REQ-003
Rules for decomposition:
- Each component has a single, well-defined responsibility
- Dependencies flow from volatile to stable (never reverse)
- Components communicate through explicit interfaces (no direct field access)
- Circular dependencies are forbidden (hard guardrail)
- When a heavy UI or I/O framework is in scope (Streamlit, React, Next.js, Django, Flask, FastAPI, …), the agent (via the
architect checklist) checks whether a framework-free domain module is warranted and, if so, proposes a DEC + a policy test enforcing the import boundary
Step 2.5 — Shared State Identification
For each piece of state (data, selection, session, filter, auth context, etc.) that must be visible or consistent across multiple components or pages, formalize it in the ## Shared State section of design.md. The common failure mode is silent duplication: each component invents its own instance of what is logically one piece of state, leading to inconsistency (e.g., a month filter widget that must be synchronized across 3 pages but lives as 3 independent state slots).
Algorithm:
-
Walk through the REQs and the component decomposition from Step 2.
-
For each component pair, ask: "Do they read or write any state that must stay consistent between them?"
-
If yes, add an entry to ## Shared State:
| Name | Scope (components) | Mechanism | Rationale | Traces |
|---|
selected_month | Dashboard, Books, Stats | framework session state (e.g., Streamlit st.session_state, React context, URL query param) | Month filter must be consistent across all views | REQ-003, REQ-005 |
current_user | All pages | session cookie + server-side store | Identity needed everywhere for authorization | REQ-001 |
-
If no shared state applies (e.g., CLI tool, pure library, strictly independent components), write the explicit disclaimer:
"No shared state identified — components are independent."
Never leave the section empty. An empty section is indistinguishable from "we didn't think about it". The explicit disclaimer confirms the question was considered.
Fields semantics:
- Name — the conceptual state name, not an implementation detail (
selected_month, not SelectedMonthProvider.state).
- Scope — list of components/pages/modules that read or write this state.
- Mechanism — how it is stored and synchronized (session state, URL param, global store, event bus, context, etc.). Choose the framework-appropriate mechanism.
- Rationale — one sentence on why this state must be shared (not duplicated).
- Traces — REQ IDs that motivate the sharing (e.g., a REQ saying "filter applies to all views").
Domain adaptation (P9):
- Web / mobile projects — typically has 1 to 5 shared state entries (selections, user identity, theme, navigation).
- CLI / library / scientific projects — often zero. The disclaimer line is common and legitimate.
- API / backend projects — usually has shared state in the form of request context, session, DB connection pool.
Persist the completed section as part of the design artefact.
Step 3 — Interface Contracts
For each component, define its public interface:
Interface: AuthModule
─────────────────────
authenticate(credentials: Credentials) -> Result[Session, AuthError]
- Input: username (str, 3-50 chars), password (str, 8+ chars)
- Output: Session object with token, expiry, user_id
- Errors: InvalidCredentials, AccountLocked, RateLimited
- Invariants: token is unique, expiry is always in the future
- Side effects: creates session record in database
validate_session(token: str) -> Result[User, AuthError]
- Input: JWT token string
- Output: User object if token is valid
- Errors: TokenExpired, TokenInvalid, UserNotFound
- Invariants: never returns a disabled user
- Side effects: none (read-only)
Step 4 — Architecture Decisions
For each significant technical choice, create a decision record as a Gate decision:
Decision: DEC-{NNN} — {Topic}
──────────────────────────────
Context: {Why this decision is needed now}
Options:
A. {Option A} — {Pros} / {Cons}
B. {Option B} — {Pros} / {Cons}
C. {Option C} — {Pros} / {Cons}
Recommendation: {Option X}
Rationale: {Why this option best fits the requirements and constraints}
Consequence horizon:
- Short-term (this sprint): {impact}
- Medium-term (3 sprints): {impact}
- Long-term (project lifetime): {impact}
Reversibility: High cost | Medium cost | Low cost (the spec §11.2 — Format scale, same as recorded in Step 5)
Gate: [Accept recommendation] / [Choose different option] / [Discuss]
Each decision is appended to .gse/decisions.md (the decision journal — authoritative format in plugin/templates/decisions.md, spec Section 11):
## DEC-{NNN} — {Topic}
- **Sprint:** {NN}
- **Date:** {YYYY-MM-DD}
- **Activity:** /gse:design
- **Tier:** Gate | Inform
- **Branch:** {branch-name}
- **Options considered:** {option A}, {option B}, ...
- **Chosen:** {selected option}
- **Rationale:** {why this option was chosen}
- **Consequence horizon:**
- **Now:** {immediate impact}
- **3 months:** {medium-term}
- **1 year:** {long-term}
- **Reversibility:** High cost | Medium cost | Low cost
- **Review trigger:** {when to revisit this decision}
- **Traces:**
- derives_from: [{REQ-NNN, DES-NNN, OQ-NNN}]
- impacts: [{DES-NNN, TASK-NNN}]
- supersedes: []
- **Status:** draft | accepted | superseded
- **Decided by:** user | agent
Step 5 — Design Validation (--validate)
Check the design for structural quality:
| Check | Rule |
|---|
| Coverage | Every requirement is addressed by at least one component |
| Circular dependencies | No circular dependency chains (HARD STOP if found) |
| Interface completeness | Every component has a defined interface |
| Error handling | Every interface method defines its error cases |
| Decision records | Every significant choice has a DEC record |
| Consistency | New decisions do not contradict existing ones |
Report findings using the architect agent checklist (see plugin/agents/architect.md — authoritative checklist).
Step 5.5 — Security Design Pass (security-auditor sub-agent)
Once the architecture decisions (DES-NNN) are drafted and the structural Quality Checklist (Step 5) is clean, invoke the security-auditor sub-agent ($([ -s .gse/registry ] && cat .gse/registry || cat ~/.gse-one)/agents/security-auditor.md — adopt this role) to perform threat modeling at the design layer, complementing the later code-level security review during /gse:review.
The agent reviews each DES-NNN through the OWASP Top 10 + CWE lens and flags:
- Authentication / authorization boundaries — where identity is checked, where privileges escalate.
- Data exposure risks — what crosses trust boundaries (network, storage, logs); where secrets live in the design.
- Input validation boundaries — what components receive untrusted input; where validation is placed.
- Crypto choices — algorithms cited, key-management implications, deprecated primitives.
- Third-party / supply-chain risks — external dependencies introduced by DES-NNN.
- Secret handling patterns — credentials, API keys, tokens surfaced in the design.
Triage:
- Findings emitted as RVW-NNN with
perspective: security-auditor and tag [DESIGN-SECURITY].
- HIGH findings block Persist: the user must amend the DES-NNN or create a compensating DEC-NNN acknowledging the risk with a mitigation plan.
- MEDIUM findings trigger a Gate: Amend the design / Accept with DEC-NNN justification / Defer to implementation review.
- LOW findings are informational and appended to
docs/sprints/sprint-{NN}/design.md under ## Security Notes for visibility at PRODUCE and REVIEW time.
Rationale: architectural security flaws (e.g., session-token storage scheme, auth boundary placement, crypto algorithm choice) are far cheaper to fix at design than at code-review. This pass front-loads AI-integrity per spec §P15 + §P16 and mirrors the architect checklist consultation at Step 5 (both are design-time audits, one structural, one security-focused).
Step 6 — Persist
Save the design document to docs/sprints/sprint-{NN}/design.md:
---
gse:
type: design
sprint: {NN}
branch: gse/sprint-{NN}/integration
status: draft
created: "{YYYY-MM-DD}"
updated: "{YYYY-MM-DD}"
traces:
derives_from: []
implements: [REQ-{NNN}, ...]
tested_by: []
decided_by: []
---
Content includes:
- Component diagram (text-based or Mermaid)
- Component descriptions with responsibilities
- Interface contracts
- Architecture decision references
- Dependency graph
Present the design for user approval (Gate). Set status to approved once confirmed.
Step 7 — Inform-Tier Decisions Summary (Creator-Activity Closure, spec P16)
Close the activity with a retrospective list of the Inform-tier decisions the agent made during design work (per P7 risk classification). DESIGN often contains many small autonomous choices that were individually low-stakes — typing conventions, import style, interface naming conventions, diagramming notation — none of which warranted an interruptive Gate on their own.
-
Assemble the list from the agent's conversation memory for this activity. Examples: "used TypeScript types instead of Zod schemas", "interface methods return Result<T, E> rather than throwing", "used Mermaid over ASCII for the component diagram".
-
If the list is empty (rare — all choices were Gated), display explicitly: "No inform-tier decisions made this activity — all choices were Gated." Then conclude DESIGN.
-
If the list is non-empty, present it and the Gate:
**Inform-tier decisions made during this design:**
- {decision 1}
- {decision 2}
- ...
Any of these you want to promote to a Gate decision?
**Options:**
1. **Accept all as-is** (default) — Record as an `## Inform-tier Decisions` section at the end of `docs/sprints/sprint-{NN}/design.md`.
2. **Promote one or more to Gate** — For each selected decision, walk through a standard Gate (Question / Context / Options with consequence horizons / Discuss). If the user picks an alternative, the agent updates the design to reflect the new choice, and the DEC-NNN is added to `decisions.md`.
3. **Discuss** — Explore any of the decisions before accepting or promoting.
-
Execute the chosen option. Accepted decisions are serialized as a markdown list under an ## Inform-tier Decisions section.