diff options
| author | Craig Jennings <c@cjennings.net> | 2026-04-19 14:08:30 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-04-19 14:08:30 -0500 |
| commit | ce951b692300d9f8d96af1ef01142748b4ea2bc0 (patch) | |
| tree | fee7bccb2b3f45c635338ab0e74a9fd204383f49 /docs | |
| parent | e50c732d7138c18749b96b57004a3e23f31bbaef (diff) | |
| download | rulesets-ce951b692300d9f8d96af1ef01142748b4ea2bc0.tar.gz rulesets-ce951b692300d9f8d96af1ef01142748b4ea2bc0.zip | |
feat: architecture skill suite — design, decide, document, evaluate
Four chained Claude Code skills covering the full architecture lifecycle:
arch-design Intake (stakeholders, scale, quality attributes, constraints)
→ candidate paradigms with honest trade-off analysis
→ recommendation + open-decision list
→ .architecture/brief.md
arch-decide ADR creation and management. Five template variants (MADR,
Nygard, Y-statement, lightweight, RFC). Lifecycle, review
process, adr-tools automation.
Forked from wshobson/agents (MIT). LICENSE preserved.
arch-document Full arc42-structured documentation (12 sections) from brief
+ ADRs + codebase. Dispatches to c4-analyze / c4-diagram for
Context, Building Block, Runtime, Deployment diagrams.
arch-evaluate Audits implementation against stated architecture.
Framework-agnostic checks (cyclic deps, stated-layer
violations, public API drift, forbidden deps) run on any
language. Opportunistically invokes language-specific linters
when configured (dependency-cruiser for TS, import-linter for
Python, go vet + depguard for Go). Never installs tooling.
Supporting docs at docs/architecture/:
- README.md suite overview, install steps, per-language linter install
commands (Python import-linter, TS dependency-cruiser, Go
golangci-lint, Java ArchUnit future, C/C++ IWYU future),
typical flow through the chain
- v2-todo.org deferred features (auto-gen linter configs, ArchUnit, CI
mode, DDD aggregate boundaries, visual dep graphs, retroactive
layering inference)
Makefile SKILLS extended with the four new entries; make install symlinks
them to ~/.claude/skills/ alongside existing skills.
Landscape: arch-decide fills the well-covered ADR bucket by adopting the
strongest community offering rather than reinventing. arch-design and
arch-evaluate fill gaps where no general-purpose skill existed. arch-document
fills the arc42 gap (C4 diagrams already covered by sibling skills).
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/architecture/README.md | 359 | ||||
| -rw-r--r-- | docs/architecture/v2-todo.org | 254 |
2 files changed, 613 insertions, 0 deletions
diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 0000000..e09efb0 --- /dev/null +++ b/docs/architecture/README.md @@ -0,0 +1,359 @@ +# Architecture Suite + +Four chained Claude Code skills for the full architecture lifecycle: **design**, **decide**, **document**, **evaluate**. Paradigm-agnostic (supports layered, hexagonal, microservices, event-driven, CQRS, DDD, and others). Language-aware (framework-agnostic checks work everywhere; language-specific linters augment when configured). + +## The Chain + +``` + ┌─────────────────┐ + New project → │ arch-design │ → .architecture/brief.md + └────────┬────────┘ + │ + (for each open decision) + │ + ▼ + ┌─────────────────┐ + │ arch-decide │ → docs/adr/NNNN-*.md + └────────┬────────┘ + │ + (when ready to formalize) + │ + ▼ + ┌─────────────────┐ + │ arch-document │ → docs/architecture/*.md + └────────┬────────┘ (dispatches to c4-analyze, c4-diagram) + │ + (once code exists, periodically) + │ + ▼ + ┌─────────────────┐ + │ arch-evaluate │ → .architecture/evaluation-YYYY-MM-DD.md + └─────────────────┘ +``` + +Skills are standalone — invoke any one directly. The flow above is the canonical path; you can enter at any point if the prerequisite artifacts already exist. + +## What Each Skill Does + +### [arch-design](../../arch-design/SKILL.md) + +Elicits the architecture: intake (stakeholders, scale, team, timeline), quality-attribute prioritization, constraints, then proposes 2-4 candidate paradigms with honest trade-off analysis. Picks one with rationale. Lists open decisions that become ADRs. + +**Output:** `.architecture/brief.md` + +### [arch-decide](../../arch-decide/SKILL.md) + +Records significant technical decisions as ADRs. Five template variants (MADR, Nygard, Y-statement, lightweight, RFC). Covers ADR lifecycle (proposed / accepted / deprecated / superseded), review checklist, and `adr-tools` automation. + +**Output:** `docs/adr/NNNN-<title>.md`, plus an index at `docs/adr/README.md`. + +**Forked from [wshobson/agents](https://github.com/wshobson/agents) — MIT.** + +### [arch-document](../../arch-document/SKILL.md) + +Produces full arc42-structured documentation from the brief + ADRs + codebase. All twelve arc42 sections. Dispatches to `c4-analyze` (for code-present systems) and `c4-diagram` (for textual descriptions) for the diagrams in sections 3, 5, 6, and 7. + +**Output:** `docs/architecture/01-introduction.md` through `12-glossary.md`, plus diagrams under `docs/architecture/diagrams/`. + +### [arch-evaluate](../../arch-evaluate/SKILL.md) + +Audits the codebase against the brief + ADRs. Four framework-agnostic checks (cyclic deps, stated-layer violations, public API drift, forbidden deps). Opportunistically invokes language-specific linters if they're already configured in the repo. + +**Output:** `.architecture/evaluation-YYYY-MM-DD.md` + +## Installation + +These skills live in this rulesets repo alongside the other skills (`debug`, `add-tests`, `c4-analyze`, etc.). Install globally once: + +```bash +make -C ~/code/rulesets install +``` + +This symlinks every skill (including the four `arch-*`) into `~/.claude/skills/`. Any Claude Code session on this machine will see them. + +To uninstall: + +```bash +make -C ~/code/rulesets uninstall +``` + +To check install state: + +```bash +make -C ~/code/rulesets list +``` + +## Optional: Language-Specific Linters + +`arch-evaluate` works without any external tooling — its framework-agnostic checks cover cycles, layer violations, API drift, and forbidden deps on any language Claude can read. **Installing the linters below is optional** and augments those checks with dedicated tooling: faster on large codebases, CI-friendly, and precise. + +Install only the ones you need for your active languages. + +### Python — import-linter + +Declarative import contracts. Config in `.importlinter` or `[tool.importlinter]` in `pyproject.toml`. + +```bash +pipx install import-linter +# or: pip install --user import-linter +# or (in a uv-managed project): uv add --dev import-linter +``` + +Verify: + +```bash +lint-imports --help +``` + +Example config (`.importlinter`): + +```ini +[importlinter] +root_package = myapp + +[importlinter:contract:layers] +name = Core layers +type = layers +layers = + myapp.presentation + myapp.application + myapp.domain + myapp.infrastructure + +[importlinter:contract:framework_isolation] +name = Domain isolation +type = forbidden +source_modules = + myapp.domain +forbidden_modules = + django + fastapi +``` + +### TypeScript / JavaScript — dependency-cruiser + +Rich import analysis with a JS config file. The de-facto standard for TS architectural linting. + +```bash +npm install --save-dev dependency-cruiser +# or globally: npm install -g dependency-cruiser +``` + +Verify: + +```bash +npx dependency-cruiser --version +``` + +Generate an initial config: + +```bash +npx dependency-cruiser --init +``` + +Then edit `.dependency-cruiser.cjs` to encode your architecture. Example rule: + +```javascript +module.exports = { + forbidden: [ + { + name: 'domain-no-infrastructure', + severity: 'error', + from: { path: '^src/domain' }, + to: { path: '^src/infrastructure' }, + }, + ], + options: { tsPreCompilationDeps: true, tsConfig: { fileName: 'tsconfig.json' } }, +}; +``` + +### Go — golangci-lint (with depguard) + +`go vet` (part of the stdlib) covers built-in checks. `depguard` (via golangci-lint) enforces import rules. + +```bash +# macOS +brew install golangci-lint + +# Linux / anywhere with Go +go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest +``` + +Verify: + +```bash +golangci-lint --version +go vet ./... +``` + +Example `.golangci.yml`: + +```yaml +linters: + disable-all: true + enable: + - depguard + +linters-settings: + depguard: + rules: + domain: + list-mode: lax + files: + - "$all" + - "!**/infrastructure/**" + deny: + - pkg: "github.com/yourorg/yourapp/infrastructure" + desc: "domain must not depend on infrastructure" +``` + +### Java — ArchUnit (v2+) + +Test-driven: architectural rules live in JUnit tests. Not invoked by `arch-evaluate` in v1. + +**Maven:** + +```xml +<dependency> + <groupId>com.tngtech.archunit</groupId> + <artifactId>archunit-junit5</artifactId> + <version>1.3.0</version> + <scope>test</scope> +</dependency> +``` + +**Gradle:** + +```groovy +testImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0' +``` + +Example rule (`src/test/java/archtest/LayerRules.java`): + +```java +@AnalyzeClasses(packages = "com.yourorg.yourapp") +class LayerRules { + @ArchTest + static final ArchRule layered = + layeredArchitecture().consideringAllDependencies() + .layer("Presentation").definedBy("..presentation..") + .layer("Application").definedBy("..application..") + .layer("Domain").definedBy("..domain..") + .whereLayer("Presentation").mayNotBeAccessedByAnyLayer() + .whereLayer("Application").mayOnlyBeAccessedByLayers("Presentation") + .whereLayer("Domain").mayOnlyBeAccessedByLayers("Application", "Presentation"); +} +``` + +Then run `mvn test` or `gradle test`. + +### C / C++ — include-what-you-use (v2+) + +Checks each source file's `#include` discipline. Not invoked by `arch-evaluate` in v1; listed for completeness. + +```bash +# macOS +brew install include-what-you-use + +# Arch Linux +sudo pacman -S include-what-you-use + +# Ubuntu/Debian +sudo apt install iwyu +``` + +Integrate via CMake: + +```cmake +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE include-what-you-use) +``` + +Verify: + +```bash +include-what-you-use --version +``` + +## Typical Flow + +### New project + +```bash +# 1. Shape the architecture +# In Claude Code: +/arch-design +# Answer intake questions, rank quality attributes, review candidates. +# Output: .architecture/brief.md + +# 2. Record each open decision +/arch-decide +# Once per significant decision. Output: docs/adr/0001-*.md, 0002-*.md, etc. + +# 3. Formalize (when ready) +/arch-document +# Generates all twelve arc42 sections + diagrams. +# Output: docs/architecture/*.md + +# 4. Audit (once code exists) +/arch-evaluate +# Report at .architecture/evaluation-YYYY-MM-DD.md +``` + +### Existing project with no architecture docs + +```bash +# 1. Retroactively capture +/arch-design # reconstruct the brief from what exists +/arch-decide # write ADRs for past decisions (date them honestly) +/arch-document # produce current-state arc42 docs + +# 2. Audit against the reconstructed intent +/arch-evaluate +``` + +### Continuous + +- Re-run `/arch-evaluate` periodically (on PR, before release, monthly) +- Every significant new decision → `/arch-decide` +- Brief or ADR changes → `/arch-document` to refresh + +## Where Things Land + +``` +<project-root>/ +├── .architecture/ +│ ├── brief.md ← arch-design +│ └── evaluation-YYYY-MM-DD.md ← arch-evaluate +├── docs/ +│ ├── adr/ +│ │ ├── README.md ← arch-decide (index) +│ │ └── NNNN-<title>.md ← arch-decide +│ └── architecture/ +│ ├── README.md ← arch-document (index) +│ ├── 01-introduction.md … ← arch-document +│ ├── 12-glossary.md +│ └── diagrams/ ← arch-document (via c4-*) +│ ├── context.svg +│ ├── container.svg +│ └── runtime-<scenario>.svg +``` + +## Dependencies Between Skills + +- `arch-decide` is standalone; nothing required from the others +- `arch-document` reads the brief and ADRs; without them, it stubs sections as TODO +- `arch-evaluate` requires the brief; without it, the skill stops and tells the user to run `arch-design` +- `arch-document` dispatches to `c4-analyze` (if code exists) and `c4-diagram` (otherwise) — both live in this same rulesets repo + +## Versioning and Deferred Work + +v1 covers the four core skills with the chain above. The deferred feature list — CI integration, auto-generated linter configs, ArchUnit integration, DDD aggregate boundaries, etc. — is tracked at [`v2-todo.org`](v2-todo.org). + +## Licensing + +- `arch-design`, `arch-document`, `arch-evaluate` — part of this rulesets repo +- `arch-decide` — forked from [wshobson/agents](https://github.com/wshobson/agents), **MIT**. See `arch-decide/LICENSE`. + +## Contributing / Modifying + +These are personal skills; fork as needed. If you change a skill and want to re-sync the global install symlink, re-run `make -C ~/code/rulesets install`. Symlinks point back at this repo, so edits propagate without re-install. diff --git a/docs/architecture/v2-todo.org b/docs/architecture/v2-todo.org new file mode 100644 index 0000000..4d40ad3 --- /dev/null +++ b/docs/architecture/v2-todo.org @@ -0,0 +1,254 @@ +#+TITLE: Architecture Suite — v2+ TODO +#+AUTHOR: Craig Jennings +#+DATE: 2026-04-19 + +Deferred work for the arch-* skill chain. v1 ships with the four core skills +and opportunistic linter integration. Items here extend capability, +precision, or scope and were intentionally deferred. + +* About + +Each item lists motivation, scope, and the skill(s) it touches. Priority hints +(=[#A/B/C]=) reflect rough judgement, not firm commitment. Rearrange freely. + +Related: [[file:README.md][README.md]] for the v1 architecture suite overview. + +* v2 Candidates + +** TODO [#A] Auto-generate linter configs from the brief :arch-evaluate: +SCHEDULED: <2026-05-15 Fri> + +Today the user hand-writes =.importlinter= / =.dependency-cruiser.cjs= / =.golangci.yml= +from the brief's declared layers. The skill should be able to emit a starter +config for the detected language. + +*** Scope +- Parse layers section of =.architecture/brief.md= +- Emit minimal config matching declared structure +- Place in repo with =--dry-run= mode to preview +- Never overwrite an existing config without =--force= + +*** Complication +- Each tool has different semantics (forbidden vs layer-based vs import rules) +- Mapping from "paradigm + layers" to tool-specific rules has edge cases +- Want to avoid generating wrong/incomplete rules that mislead users + +*** Touches +- =arch-evaluate= (config generation) +- =arch-design= (formalize the layers syntax in the brief) + +** TODO [#A] CI mode: exit codes and --fail-on :arch-evaluate: + +Today the skill produces a markdown report. For CI, need machine-readable +output and non-zero exit on violations. + +*** Scope +- =--output json=: structured findings for parsing +- Exit code: 0 (no errors), 1 (errors present), 2 (tool failures) +- =--fail-on=warning= flag for strict mode +- =--delta-since=<git-ref>=: only report findings introduced since that ref + +*** Touches +- =arch-evaluate= only + +** TODO [#A] ArchUnit integration (Java) :arch-evaluate: + +Java architectural linting happens via ArchUnit, which runs as JUnit tests. +The skill needs to know how to invoke it and parse its output. + +*** Scope +- Detect =archunit-junit5= dependency in =pom.xml= / =build.gradle= +- Invoke via =mvn test -Dtest=*ArchTest*= or =gradle test --tests *ArchTest= +- Parse JUnit XML or surefire reports for failures +- Map to unified finding format + +*** Complication +- ArchUnit requires someone to have written the rule classes +- Skill could also suggest generating rule tests from the brief (overlap with auto-gen task above) + +*** Touches +- =arch-evaluate= (invocation + parsing) + +** TODO [#B] include-what-you-use / cpp-linter integration (C/C++) :arch-evaluate: + +C and C++ have weaker architectural linting options than the dynamic +languages. =include-what-you-use= is the main tool; needs CMake integration +to run usefully. + +*** Scope +- Detect =.iwyu.imp= or CMake option =CMAKE_CXX_INCLUDE_WHAT_YOU_USE= +- Run a build with IWYU enabled, collect output +- Parse and report + +*** Complication +- Requires a full build (slow) +- Output is verbose; much is noise (re-sorting includes vs. real violations) +- May need a user-provided mapping file for vendored deps + +*** Touches +- =arch-evaluate= (invocation + parsing) + +** TODO [#B] DDD aggregate boundary checks :arch-evaluate: + +When the brief declares DDD tactical patterns (aggregates, repositories, +domain events), check that code respects the boundaries: aggregates only +referenced via their root, repositories only for aggregate roots, events not +crossing bounded contexts directly. + +*** Scope +- Extend brief syntax to declare aggregates + bounded contexts +- Framework-agnostic check: aggregate internals only accessed via root path +- Framework-agnostic check: repositories match declared aggregate roots 1:1 +- Flag direct cross-aggregate references + +*** Complication +- DDD is heterogeneous in practice — no single canonical structure +- Risk of being too prescriptive + +*** Touches +- =arch-design= (formalize DDD declaration in brief) +- =arch-evaluate= (checks) + +** TODO [#B] Auto-detect declared architecture from existing code :arch-design: + +For retroactive briefs: instead of asking the user to describe their +existing architecture, infer a likely layering from import patterns, propose +it, and let the user confirm/edit. + +*** Scope +- Dispatch to =c4-analyze= for module graph +- Cluster modules into implied layers using dep direction + naming +- Propose: "Looks like these layers: presentation → application → domain → infrastructure. Confirm or edit." +- Save confirmed layering to brief §7 + +*** Complication +- Inference can mislead — mixed codebases produce bad clusters +- Requires code organization that isn't already chaotic to work well + +*** Touches +- =arch-design= only + +** TODO [#B] ADR ⇄ brief cross-referencing :arch-decide: + +Currently the brief links to "ADRs TBD" and ADRs don't link back. Bidirectional +linking improves navigation and ensures the brief stays current. + +*** Scope +- =arch-decide= adds a "Brief section" field to new ADRs +- When an ADR is accepted, update brief §8 (Open Decisions) to check the box and link +- =arch-document= §9 generates a cross-reference table + +*** Touches +- =arch-decide= (write-back to brief) +- =arch-document= (index table) + +** TODO [#B] Visual dependency graph output :arch-evaluate: + +Beyond text report, emit a visual graph of cycles and layer violations. + +*** Scope +- Graphviz / mermaid output with violating edges highlighted in red +- Optional per-layer coloring +- Link to SVG/PNG from the markdown report + +*** Touches +- =arch-evaluate= (output rendering) + +** TODO [#C] Expanded paradigm library :arch-design: + +Add more paradigm entries to the candidate-considered table in arch-design: +CQRS+Event-Sourcing combined, saga orchestration, choreography, CRDTs, +space-based, reactive, etc. + +*** Complication +- More options isn't always better — risk of analysis paralysis +- Must keep trade-off analysis honest per paradigm + +*** Touches +- =arch-design= only + +** TODO [#C] Quality attribute scenario generator :arch-design: + +Given a top-ranked quality attribute ("performance"), generate concrete +testable scenarios in the format: "Under X, the system should Y within Z." + +*** Scope +- Scenario template per attribute class +- Measurable by default; flag vague ones for the user + +*** Touches +- =arch-design= (optional phase 2.5) + +** TODO [#C] Support for non-arc42 documentation formats :arch-document: + +Some teams prefer C4-only, ISO/IEC 42010 terminology, or a lighter 4+1 views +format. Add alternate templates. + +*** Scope +- Selectable =--format= in =arch-document=: arc42 (default), c4-only, 4+1, minimal +- Each format maps a subset of content + +*** Complication +- Duplicates effort; arc42 is already comprehensive +- May mean maintaining parallel templates + +*** Touches +- =arch-document= only + +** TODO [#C] PlantUML / Structurizr output :arch-document: + +Generate text-based architecture DSLs (PlantUML C4, Structurizr DSL) from the +decomposition, for teams that prefer those toolchains. + +*** Scope +- Output option in =arch-document=: emit structurizr or plantuml alongside markdown + +*** Touches +- =arch-document= (via c4-* dispatch) + +** TODO [#C] ATAM-style trade-off analysis :arch-design: + +For complex decisions, enable a deeper Architecture Trade-off Analysis +Method pass: identify sensitivity points, trade-off points, risks per +paradigm option. + +*** Complication +- ATAM is heavy; not appropriate for most projects +- Optional mode; don't make it default + +*** Touches +- =arch-design= (optional deep-dive) + +** TODO [#C] Interactive mode :arch-design: + +Instead of one-shot Q&A, walk the user through each phase as a guided +conversation with branching based on answers. + +*** Complication +- Hard to make conversational in a skill context +- Probably belongs as a slash command workflow, not a skill + +*** Touches +- =arch-design= (or a new =/arch-wizard= command) + +* Won't-Do + +** DONE Auto-implementation of architecture + +Generating code from a brief would sound appealing but crosses into tooling +that's inherently scoped to a language/framework. Out of scope for an +architectural skill suite. Leave to project-specific generators. + +** DONE Real-time collaboration + +These skills operate on filesystem artifacts (brief, ADRs, arc42 docs). +Concurrent editing is git's problem, not the skills'. + +* Notes + +- Tag entries with the skill(s) they affect (=:arch-design:=, =:arch-decide:=, + =:arch-document:=, =:arch-evaluate:=) so you can filter. +- Priority A items are what would most improve v1 for Craig's current stack + (Python / TS / Go). +- Java and C/C++ integration (ArchUnit, IWYU) is A-priority when Craig starts + using those languages, B otherwise. |
