From architect
When commands make architecture decisions (choosing tech stacks, patterns, frameworks, databases, etc.), they MUST log those decisions to `_state.json.decisions[]` for auditability and future reference.
npx claudepluginhub navraj007in/architecture-cowork-plugin --plugin architectThis skill uses the workspace's default tool permissions.
When commands make architecture decisions (choosing tech stacks, patterns, frameworks, databases, etc.), they MUST log those decisions to `_state.json.decisions[]` for auditability and future reference.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
When commands make architecture decisions (choosing tech stacks, patterns, frameworks, databases, etc.), they MUST log those decisions to _state.json.decisions[] for auditability and future reference.
Log a decision whenever your command:
Do NOT log:
Examples of decisions to log:
Each decision is a JSON object in the decisions[] array:
{
"id": "D-NNN",
"title": "Choose PostgreSQL for primary database",
"rationale": "ACID compliance for order consistency. Team has PostgreSQL expertise. Query flexibility for future analytics features.",
"alternatives_rejected": [
"MongoDB (weak multi-document transactions, overkill for relational data)",
"DynamoDB (cost scales poorly with joins, limited query flexibility)"
],
"trade_offs": "Higher operational complexity than managed cloud DBs. Team must maintain backups. Cold-start slower than serverless options.",
"made_by_command": "blueprint",
"timestamp": "2026-04-24T14:32:10Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique decision ID (e.g., "D-001", "D-002"). Increment sequentially within a project. |
title | string | Yes | Brief decision title (3-10 words). E.g., "PostgreSQL for primary database" |
rationale | string | Yes | Why this choice? What does it enable? What problem does it solve? (2-5 sentences or bullets) |
alternatives_rejected | array of strings | Yes | What were the runner-up options and why did they lose? Makes future reconsideration easier. At least 2 alternatives. |
trade_offs | string | Yes | What are you giving up? What becomes harder or more expensive? (1-3 sentences) |
made_by_command | string | Yes | Which command made this decision? (e.g., "blueprint", "sdl", "scaffold") |
timestamp | string | Yes | ISO-8601 timestamp when decision was made (e.g., "2026-04-24T14:32:10Z") |
1. Read current _state.json (if exists)
2. Read SDL and extract/determine tech choices
3. For each decision (e.g., database choice):
a. Create decision object with all 7 fields
b. Append to _state.json.decisions[] array
4. Write _state.json back to disk
# Read existing state
import json
from datetime import datetime
state = json.load(open('architecture-output/_state.json')) if os.path.exists(...) else {"decisions": []}
# Make a decision
new_decision = {
"id": f"D-{len(state.get('decisions', [])) + 1:03d}",
"title": "PostgreSQL for primary database",
"rationale": "ACID compliance for order consistency. Team has expertise. Query flexibility for analytics.",
"alternatives_rejected": [
"MongoDB (weak transactions, overkill for relational data)",
"DynamoDB (cost scales poorly, limited queries)"
],
"trade_offs": "Higher ops complexity. Team maintains backups. Cold-start slower than serverless.",
"made_by_command": "blueprint",
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# Append to decisions array
state.setdefault("decisions", []).append(new_decision)
# Write back
json.dump(state, open('architecture-output/_state.json', 'w'))
// JavaScript equivalent
const fs = require('fs');
const path = require('path');
const stateFile = 'architecture-output/_state.json';
const state = fs.existsSync(stateFile)
? JSON.parse(fs.readFileSync(stateFile, 'utf8'))
: { decisions: [] };
const newDecision = {
id: `D-${String(state.decisions.length + 1).padStart(3, '0')}`,
title: "PostgreSQL for primary database",
rationale: "ACID compliance for order consistency. Team has expertise. Query flexibility for analytics.",
alternatives_rejected: [
"MongoDB (weak transactions, overkill for relational data)",
"DynamoDB (cost scales poorly, limited queries)"
],
trade_offs: "Higher ops complexity. Team maintains backups. Cold-start slower than serverless.",
made_by_command: "blueprint",
timestamp: new Date().toISOString().replace('Z', 'Z') // Ensure Z suffix
};
state.decisions.push(newDecision);
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
Decision IDs are per-project (not global). Start at D-001 for the first decision:
D-001D-002D-003 (continues sequence, not restart)ID format: D-NNN where NNN is zero-padded 3-digit number.
If your command makes multiple decisions, create one object per decision:
{
"decisions": [
{
"id": "D-001",
"title": "PostgreSQL for primary database",
"rationale": "...",
"alternatives_rejected": ["..."],
"trade_offs": "...",
"made_by_command": "blueprint",
"timestamp": "2026-04-24T14:32:10Z"
},
{
"id": "D-002",
"title": "React for frontend framework",
"rationale": "...",
"alternatives_rejected": ["..."],
"trade_offs": "...",
"made_by_command": "blueprint",
"timestamp": "2026-04-24T14:32:15Z"
}
]
}
Each decision gets its own ID and timestamp (even if made seconds apart).
When ADRs are generated, they should reference decision IDs:
# ADR-001: Database Choice
**Decision ID:** D-001
## Status
Accepted
## Context
[Rationale from decisions[0].rationale]
## Decision
PostgreSQL
## Consequences
[Trade-offs from decisions[0].trade_offs]
## Alternatives Considered
- MongoDB: [from decisions[0].alternatives_rejected[0]]
- DynamoDB: [from decisions[0].alternatives_rejected[1]]
Users can analyze decisions via:
jq '.decisions' architecture-output/_state.json/architect:decisions-linked (Phase 1.5 command) generates markdown mapping decisions to ADRs/architect:check-state validates decision logging compliance/architect:check-state — Validates decisions array/architect:decisions-linked (Phase 1.5) — Maps decisions to ADRs/architect:generate-docs — Includes decision log in documentation{
"id": "D-001",
"title": "Next.js App Router for frontend",
"rationale": "Server components reduce client-side complexity. File-based routing matches team's experience. Excellent TypeScript support.",
"alternatives_rejected": [
"React SPA + Express (more configuration, fewer conventions)",
"Remix (smaller ecosystem, steeper learning curve)"
],
"trade_offs": "Tied to Vercel deployment for optimal performance. Vendor lock-in risk.",
"made_by_command": "blueprint",
"timestamp": "2026-04-24T10:00:00Z"
}
{
"id": "D-001",
"title": "Monolithic architecture for MVP",
"rationale": "Faster time-to-market. Simpler deployment. Team of 2 engineers. Can split to microservices later if needed.",
"alternatives_rejected": [
"Microservices (overkill complexity for MVP, ops overhead)",
"Serverless (unpredictable cold starts for user-facing APIs)"
],
"trade_offs": "Will need refactoring when scaling to 10+ services. Single point of failure. Database scaling limited.",
"made_by_command": "blueprint",
"timestamp": "2026-04-20T14:32:10Z"
}
If your command makes a tech choice but doesn't log it:
/architect:check-state may flag missing decisionsAlways log decisions. It's cheap, and it pays dividends.