一键导入
architect
Step 2 — Architecture and domain design, one feature at a time
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Step 2 — Architecture and domain design, one feature at a time
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Step 1 — discover requirements through stakeholder interviews and write Gherkin acceptance criteria
Generate and update architecture diagrams, living glossary, and system overview from existing project docs
Enforce code quality using ruff, pytest coverage, and static type checking
Create pull requests with conventional commits, proper formatting, and branch workflow
Flow protocol — design and operate state machine workflows with FLOW.md + WORK.md
Create releases with hybrid major.minor.calver versioning and optional custom release naming
| name | architect |
| description | Step 2 — Architecture and domain design, one feature at a time |
| version | 2.0 |
| author | system-architect |
| audience | system-architect |
| workflow | feature-lifecycle |
Step 2: conduct the architectural interview, design the domain model, write architecture stubs, record decisions as ADRs, and generate test stubs. The system-architect owns this step entirely.
Load this skill when starting Step 2 (Architecture) after the PO has moved a BASELINED feature to in-progress/.
During architecture, correctness priorities are (in order):
uv run task test-fast passes after stub generationDesign correctness is far more important than lint/pyright/coverage compliance. Never run lint or static-check during architecture — those are handoff-only checks.
docs/features/in-progress/ contains exactly one .feature file (not just .gitkeep). If none exists, STOP — update WORK.md @state to [IDLE] and stop. Never self-select or move a feature yourself.Status: BASELINED. If not, escalate to PO — Step 1 is incomplete.Rule: blocks with Example: blocks and @id tags. If not, escalate to PO — criteria have not been written.pyproject.toml → locate [tool.setuptools] → confirm directory exists on disk.git branch --show-current must output feat/<stem> or fix/<stem>. If it outputs main or any other branch, stop — the SE must create the correct branch via skill version-control before architecture begins.pyproject.toml → locate [tool.setuptools] → record packages = ["<name>"]ls <name>/<name>/Note on feature file moves: The PO moves .feature files between folders. The system-architect never moves, creates, or edits .feature files. Verify WORK.md has the correct @id and @branch set before beginning architecture work.
docs/system.md — all sections: domain model, Context, Container, module structure, constraints, ADR indexdocs/glossary.md if it exists — use existing domain terms when naming classes, methods, and modules; do not invent synonyms.feature file (full: Rules + Examples + @id)tree <package>/ — understand package structure without reading every file.py files whose names match nouns from the feature — understand what already exists before adding anything. Do not read the entire package.The arch interview surfaces decisions that must be recorded as ADRs. Each unresolved question becomes one ADR.
Three techniques surface decisions the feature file has not yet made explicit. Apply them during the domain analysis pass.
Critical Incident Technique (CIT) — Flanagan 1954 Ask about a specific failure scenario rather than a general description.
Laddering / Means-End Chain — Reynolds & Gutman 1988 Climb from surface constraint to architectural consequence.
Silent Pre-mortem (before writing anything)
"In 6 months this design is a mess. What mistakes did we make?"
For each candidate class:
2 ivars? → split
1 reason to change? → isolate
For each external dep:
For each noun:
If pattern smell detected, load skill apply-patterns.
For each unresolved decision identified during domain analysis:
Frame the question: state the decision as a clear question with known alternatives.
Example: "Should FrameworkAdapter be a typing.Protocol or an ABC?"
State constraints: list what is known from the feature file, glossary, and existing ADRs that constrains the answer.
Evaluate alternatives: for each option, state the consequence. Apply laddering to surface hidden consequences.
Record the decision: write one ADR per question. Use the template in adr.md.template.
## Context — the question + constraints that produced it## Decision — one sentence## Reason — one sentence## Alternatives Considered — rejected options with reasons## Consequences — (+) and (-) outcomesCommit each ADR as it is finalized: feat(<feature-stem>): add ADR-<slug>
Only create an ADR for non-obvious decisions with meaningful trade-offs. Routine YAGNI choices do not need a record.
From docs/glossary.md + Rules (Business) in the .feature file:
docs/system.md)Update the ## Domain Model section of docs/system.md:
### Deprecated subsection. Never edit existing live entries — code depends on them.## Context and ## Container sections if new actors, external systems, or containers are identified.The PO reads docs/system.md but never writes to it.
Apply to the stub files just written:
If any check fails: fix the stub files before committing.
From the domain analysis, write or extend .py files in <package>/. For each entity:
Stub rules (strictly enforced):
... — no logic, no conditionals, no imports beyond typing and domain typesExample — correct stub style:
from dataclasses import dataclass
from typing import Protocol
@dataclass(frozen=True, slots=True)
class EmailAddress:
value: str
def validate(self) -> None: ...
class UserRepository(Protocol):
def save(self, user: "User") -> None: ...
def find_by_email(self, email: EmailAddress) -> "User | None": ...
File placement (common patterns, not required names):
<package>/domain/<noun>.py — entities, value objects<package>/domain/service.py — cross-entity operationsPlace stubs where responsibility dictates — do not pre-create ports/ or adapters/ folders unless a concrete external dependency was identified in scope. Structure follows domain analysis, not a template.
Run uv run task test-fast once. It reads the in-progress .feature file, assigns @id tags to any untagged Example: blocks (writing them back to the .feature file), and generates tests/features/<feature_slug>/<rule_slug>_test.py — one file per Rule: block, one skipped function per @id. Verify the files were created, then stage all changes (including any @id write-backs to the .feature file).
Commit: feat(<feature-stem>): add architecture and test stubs
WORK.md @state: STEP-3-WORKINGsystem.mdIf during architecture you discover behavior not covered by existing acceptance criteria:
WORK.md and escalate to PO.feature fileTemplates for files written by this skill live in this skill's directory (architect/):
system.md.template — docs/system.md structure (domain model + Context + Container sections included)adr.md.template — individual ADR file structure (includes ## Context section)Base directory for this skill: .opencode/skills/architect/
Relative paths in this skill (e.g., scripts/, reference/) are relative to this base directory.
Note: file list is sampled.