@fredericboyer/dev-team 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ /**
3
+ * parallel.ts — Parallel state management for multi-issue orchestration (ADR-019).
4
+ *
5
+ * Manages the `.claude/dev-team-parallel.json` state file that tracks
6
+ * parallel implementation phases, sync barriers, and review waves.
7
+ *
8
+ * Zero runtime dependencies (project constraint from ADR-002).
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.DEFAULT_MAX_ITERATIONS = exports.STATE_FILENAME = void 0;
15
+ exports.statePath = statePath;
16
+ exports.readState = readState;
17
+ exports.writeState = writeState;
18
+ exports.stateExists = stateExists;
19
+ exports.deleteState = deleteState;
20
+ exports.createState = createState;
21
+ exports.transitionPhase = transitionPhase;
22
+ exports.isValidTransition = isValidTransition;
23
+ exports.allowedTransitions = allowedTransitions;
24
+ exports.updateIssueStatus = updateIssueStatus;
25
+ exports.checkSyncBarrier = checkSyncBarrier;
26
+ exports.startReviewWave = startReviewWave;
27
+ exports.recordFindings = recordFindings;
28
+ exports.isReviewWaveComplete = isReviewWaveComplete;
29
+ exports.getDefectRoutes = getDefectRoutes;
30
+ exports.checkConvergence = checkConvergence;
31
+ exports.getIndependentIssues = getIndependentIssues;
32
+ exports.getConflictGroup = getConflictGroup;
33
+ exports.summarize = summarize;
34
+ const fs_1 = __importDefault(require("fs"));
35
+ const path_1 = __importDefault(require("path"));
36
+ const files_1 = require("./files");
37
+ // ─── Constants ───────────────────────────────────────────────────────────────
38
+ exports.STATE_FILENAME = "dev-team-parallel.json";
39
+ exports.DEFAULT_MAX_ITERATIONS = 10;
40
+ // ─── State file path ─────────────────────────────────────────────────────────
41
+ function statePath(projectRoot) {
42
+ return path_1.default.join(projectRoot, ".claude", exports.STATE_FILENAME);
43
+ }
44
+ // ─── Read / Write ────────────────────────────────────────────────────────────
45
+ function readState(projectRoot) {
46
+ const fp = statePath(projectRoot);
47
+ const content = (0, files_1.readFile)(fp);
48
+ if (content === null)
49
+ return null;
50
+ try {
51
+ return JSON.parse(content);
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ function writeState(projectRoot, state) {
58
+ state.updatedAt = new Date().toISOString();
59
+ const fp = statePath(projectRoot);
60
+ (0, files_1.writeFile)(fp, JSON.stringify(state, null, 2) + "\n");
61
+ }
62
+ function stateExists(projectRoot) {
63
+ return (0, files_1.fileExists)(statePath(projectRoot));
64
+ }
65
+ function deleteState(projectRoot) {
66
+ const fp = statePath(projectRoot);
67
+ if (!(0, files_1.fileExists)(fp))
68
+ return false;
69
+ fs_1.default.unlinkSync(fp);
70
+ return true;
71
+ }
72
+ function createState(projectRoot, options) {
73
+ if (options.issues.length === 0) {
74
+ throw new Error("Cannot create parallel state with zero issues");
75
+ }
76
+ // Validate no duplicate issue numbers
77
+ const issueNumbers = options.issues.map((i) => i.issue);
78
+ const unique = new Set(issueNumbers);
79
+ if (unique.size !== issueNumbers.length) {
80
+ throw new Error("Duplicate issue numbers in parallel state");
81
+ }
82
+ // Validate conflict groups reference existing issues
83
+ for (const group of options.conflictGroups || []) {
84
+ for (const issueNum of group) {
85
+ if (!unique.has(issueNum)) {
86
+ throw new Error(`Conflict group references unknown issue #${issueNum}`);
87
+ }
88
+ }
89
+ }
90
+ const now = new Date().toISOString();
91
+ const state = {
92
+ mode: "parallel",
93
+ issues: options.issues.map((i) => ({
94
+ issue: i.issue,
95
+ branch: i.branch,
96
+ agent: i.agent,
97
+ status: "pending",
98
+ reviewIteration: 0,
99
+ })),
100
+ phase: "pre-assessment",
101
+ conflictGroups: options.conflictGroups || [],
102
+ reviewWave: null,
103
+ maxIterations: options.maxIterations ?? exports.DEFAULT_MAX_ITERATIONS,
104
+ createdAt: now,
105
+ updatedAt: now,
106
+ phaseLog: [],
107
+ };
108
+ writeState(projectRoot, state);
109
+ return state;
110
+ }
111
+ // ─── Phase transitions ──────────────────────────────────────────────────────
112
+ function transitionPhase(state, to, reason) {
113
+ const from = state.phase;
114
+ // Validate transition is legal
115
+ if (!isValidTransition(from, to)) {
116
+ throw new Error(`Invalid phase transition: ${from} -> ${to}. Allowed from ${from}: ${allowedTransitions(from).join(", ")}`);
117
+ }
118
+ state.phaseLog.push({
119
+ from,
120
+ to,
121
+ timestamp: new Date().toISOString(),
122
+ reason,
123
+ });
124
+ state.phase = to;
125
+ return state;
126
+ }
127
+ const TRANSITION_MAP = {
128
+ "pre-assessment": ["implementation"],
129
+ implementation: ["sync-barrier"],
130
+ "sync-barrier": ["review-wave"],
131
+ "review-wave": ["defect-routing", "borges-completion"],
132
+ "defect-routing": ["review-wave", "borges-completion"],
133
+ "borges-completion": ["done"],
134
+ done: [],
135
+ };
136
+ function isValidTransition(from, to) {
137
+ return TRANSITION_MAP[from]?.includes(to) ?? false;
138
+ }
139
+ function allowedTransitions(from) {
140
+ return TRANSITION_MAP[from] || [];
141
+ }
142
+ // ─── Issue status updates ────────────────────────────────────────────────────
143
+ function updateIssueStatus(state, issueNumber, status) {
144
+ const entry = state.issues.find((i) => i.issue === issueNumber);
145
+ if (!entry) {
146
+ throw new Error(`Issue #${issueNumber} not found in parallel state`);
147
+ }
148
+ entry.status = status;
149
+ return state;
150
+ }
151
+ // ─── Sync barrier ────────────────────────────────────────────────────────────
152
+ /**
153
+ * Checks whether ALL implementation agents have completed.
154
+ * Returns true when every issue has status "implemented" or later.
155
+ */
156
+ function checkSyncBarrier(state) {
157
+ const completedStatuses = [
158
+ "implemented",
159
+ "reviewing",
160
+ "defects-found",
161
+ "fixing",
162
+ "approved",
163
+ ];
164
+ const completed = [];
165
+ const pending = [];
166
+ for (const issue of state.issues) {
167
+ if (completedStatuses.includes(issue.status)) {
168
+ completed.push(issue.issue);
169
+ }
170
+ else {
171
+ pending.push(issue.issue);
172
+ }
173
+ }
174
+ return {
175
+ ready: pending.length === 0,
176
+ pending,
177
+ completed,
178
+ };
179
+ }
180
+ // ─── Review wave management ──────────────────────────────────────────────────
181
+ function startReviewWave(state) {
182
+ const barrier = checkSyncBarrier(state);
183
+ if (!barrier.ready) {
184
+ throw new Error(`Cannot start review wave: issues still pending: ${barrier.pending.join(", ")}`);
185
+ }
186
+ const waveNumber = state.reviewWave ? state.reviewWave.wave + 1 : 1;
187
+ const branches = state.issues.map((i) => i.branch);
188
+ state.reviewWave = {
189
+ wave: waveNumber,
190
+ startedAt: new Date().toISOString(),
191
+ branches,
192
+ findings: {},
193
+ };
194
+ // Update all issue statuses to reviewing
195
+ for (const issue of state.issues) {
196
+ if (issue.status !== "approved") {
197
+ issue.status = "reviewing";
198
+ }
199
+ }
200
+ return state;
201
+ }
202
+ function recordFindings(state, branch, findings) {
203
+ if (!state.reviewWave) {
204
+ throw new Error("No active review wave to record findings for");
205
+ }
206
+ const issue = state.issues.find((i) => i.branch === branch);
207
+ if (!issue) {
208
+ throw new Error(`Branch "${branch}" not found in parallel state`);
209
+ }
210
+ state.reviewWave.findings[branch] = findings;
211
+ // Update issue status based on findings
212
+ if (findings.defects.length > 0) {
213
+ issue.status = "defects-found";
214
+ issue.defects = findings.defects;
215
+ issue.reviewIteration = (issue.reviewIteration || 0) + 1;
216
+ }
217
+ else {
218
+ issue.status = "approved";
219
+ issue.defects = [];
220
+ }
221
+ return state;
222
+ }
223
+ /**
224
+ * Checks if ALL branches in the current review wave have reported findings.
225
+ */
226
+ function isReviewWaveComplete(state) {
227
+ if (!state.reviewWave)
228
+ return false;
229
+ const reported = new Set(Object.keys(state.reviewWave.findings));
230
+ return state.reviewWave.branches.every((b) => reported.has(b));
231
+ }
232
+ /**
233
+ * Returns defect routes: which issues need fixes routed back to their implementing agent.
234
+ * Respects per-branch iteration limits.
235
+ */
236
+ function getDefectRoutes(state) {
237
+ const routes = [];
238
+ const exhausted = [];
239
+ for (const issue of state.issues) {
240
+ if (issue.status !== "defects-found")
241
+ continue;
242
+ const route = {
243
+ issue: issue.issue,
244
+ branch: issue.branch,
245
+ agent: issue.agent,
246
+ defects: issue.defects || [],
247
+ iteration: issue.reviewIteration || 1,
248
+ };
249
+ if ((issue.reviewIteration || 0) >= state.maxIterations) {
250
+ exhausted.push(route);
251
+ }
252
+ else {
253
+ routes.push(route);
254
+ issue.status = "fixing";
255
+ }
256
+ }
257
+ return { routes, exhausted };
258
+ }
259
+ /**
260
+ * Checks if the parallel execution has converged (all approved or exhausted).
261
+ */
262
+ function checkConvergence(state) {
263
+ const approved = [];
264
+ const exhausted = [];
265
+ const pendingDefects = [];
266
+ for (const issue of state.issues) {
267
+ if (issue.status === "approved") {
268
+ approved.push(issue.issue);
269
+ }
270
+ else if ((issue.reviewIteration || 0) >= state.maxIterations) {
271
+ exhausted.push(issue.issue);
272
+ }
273
+ else {
274
+ pendingDefects.push(issue.issue);
275
+ }
276
+ }
277
+ return {
278
+ converged: approved.length + exhausted.length === state.issues.length,
279
+ allApproved: approved.length === state.issues.length,
280
+ exhaustedBranches: exhausted,
281
+ pendingDefects,
282
+ };
283
+ }
284
+ // ─── Conflict group helpers ──────────────────────────────────────────────────
285
+ /**
286
+ * Returns issues that can execute in parallel (not in any conflict group with
287
+ * currently-running issues).
288
+ */
289
+ function getIndependentIssues(state) {
290
+ const inConflict = new Set();
291
+ for (const group of state.conflictGroups) {
292
+ for (const num of group) {
293
+ inConflict.add(num);
294
+ }
295
+ }
296
+ return state.issues.filter((i) => !inConflict.has(i.issue)).map((i) => i.issue);
297
+ }
298
+ /**
299
+ * Returns the conflict group that contains a given issue, or null.
300
+ */
301
+ function getConflictGroup(state, issueNumber) {
302
+ for (const group of state.conflictGroups) {
303
+ if (group.includes(issueNumber)) {
304
+ return group;
305
+ }
306
+ }
307
+ return null;
308
+ }
309
+ function summarize(state) {
310
+ const byStatus = {};
311
+ for (const issue of state.issues) {
312
+ byStatus[issue.status] = (byStatus[issue.status] || 0) + 1;
313
+ }
314
+ return {
315
+ phase: state.phase,
316
+ totalIssues: state.issues.length,
317
+ byStatus: byStatus,
318
+ currentWave: state.reviewWave?.wave ?? null,
319
+ phaseTransitions: state.phaseLog.length,
320
+ conflictGroupCount: state.conflictGroups.length,
321
+ };
322
+ }
323
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function status(targetDir: string): void;
package/dist/status.js ADDED
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.status = status;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const files_1 = require("./files");
10
+ function status(targetDir) {
11
+ const claudeDir = path_1.default.join(targetDir, ".claude");
12
+ const prefsPath = path_1.default.join(claudeDir, "dev-team.json");
13
+ const prefsContent = (0, files_1.readFile)(prefsPath);
14
+ if (!prefsContent) {
15
+ console.error("Not a dev-team project. Run `npx dev-team init` first.");
16
+ process.exit(1);
17
+ }
18
+ let prefs;
19
+ try {
20
+ prefs = JSON.parse(prefsContent);
21
+ }
22
+ catch {
23
+ console.error("dev-team.json is corrupted.");
24
+ process.exit(1);
25
+ }
26
+ console.log("\ndev-team status\n");
27
+ // Version and preset
28
+ console.log(` Version: v${prefs.version}`);
29
+ if (prefs.preset) {
30
+ console.log(` Preset: ${prefs.preset}`);
31
+ }
32
+ // Agents
33
+ const agents = prefs.agents || [];
34
+ console.log(` Agents: ${agents.join(", ")} (${agents.length})`);
35
+ // Hooks
36
+ const hooks = prefs.hooks || [];
37
+ console.log(` Hooks: ${hooks.join(", ")} (${hooks.length})`);
38
+ // Skills (auto-discovered)
39
+ const skillsDir = path_1.default.join(claudeDir, "skills");
40
+ const skills = (0, files_1.listSubdirectories)(skillsDir).map((s) => s.replace("dev-team-", ""));
41
+ console.log(` Skills: ${skills.length > 0 ? skills.join(", ") : "none"} (${skills.length})`);
42
+ // Workflow
43
+ if (prefs.issueTracker) {
44
+ console.log(` Tracker: ${prefs.issueTracker}`);
45
+ }
46
+ if (prefs.branchConvention && prefs.branchConvention !== "None") {
47
+ console.log(` Branches: ${prefs.branchConvention}`);
48
+ }
49
+ // Memory status
50
+ console.log("\n Memory:");
51
+ const memoryDir = path_1.default.join(claudeDir, "agent-memory");
52
+ for (const label of agents) {
53
+ const dirName = `dev-team-${label.toLowerCase()}`;
54
+ const memPath = path_1.default.join(memoryDir, dirName, "MEMORY.md");
55
+ if ((0, files_1.fileExists)(memPath)) {
56
+ try {
57
+ const stat = fs_1.default.statSync(memPath);
58
+ const hasContent = stat.size > 200; // Template is ~200 bytes
59
+ console.log(` ${label}: ${hasContent ? "has learnings" : "empty (template only)"}`);
60
+ }
61
+ catch {
62
+ console.log(` ${label}: unknown`);
63
+ }
64
+ }
65
+ else {
66
+ console.log(` ${label}: no memory file`);
67
+ }
68
+ }
69
+ // Shared learnings
70
+ const learningsPath = path_1.default.join(claudeDir, "dev-team-learnings.md");
71
+ if ((0, files_1.fileExists)(learningsPath)) {
72
+ try {
73
+ const stat = fs_1.default.statSync(learningsPath);
74
+ console.log(` Shared learnings: ${stat.size > 300 ? "has content" : "template only"}`);
75
+ }
76
+ catch {
77
+ console.log(` Shared learnings: unknown`);
78
+ }
79
+ }
80
+ console.log("");
81
+ }
82
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fredericboyer/dev-team",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Adversarial AI agent team for any project — installs Claude Code agents, hooks, and skills that enforce quality through productive friction",
5
5
  "main": "dist/init.js",
6
6
  "types": "dist/init.d.ts",
@@ -15,7 +15,7 @@
15
15
  "scripts": {
16
16
  "build": "tsc",
17
17
  "pretest": "npm run build",
18
- "test": "node --test tests/unit/files.test.js tests/unit/hooks.test.js tests/unit/scan.test.js tests/unit/create-agent.test.js tests/integration/fresh-project.test.js tests/integration/idempotency.test.js tests/integration/update.test.js tests/scenarios/node-project.test.js tests/scenarios/python-project.test.js tests/scenarios/upgrade-path.test.js",
18
+ "test": "node --test tests/unit/files.test.js tests/unit/hooks.test.js tests/unit/scan.test.js tests/unit/create-agent.test.js tests/unit/cli.test.js tests/unit/parallel.test.js tests/integration/fresh-project.test.js tests/integration/idempotency.test.js tests/integration/update.test.js tests/scenarios/node-project.test.js tests/scenarios/python-project.test.js tests/scenarios/upgrade-path.test.js",
19
19
  "test:unit": "node --test tests/unit/files.test.js tests/unit/hooks.test.js",
20
20
  "test:integration": "node --test tests/integration/fresh-project.test.js tests/integration/idempotency.test.js",
21
21
  "test:scenarios": "node --test tests/scenarios/node-project.test.js tests/scenarios/python-project.test.js tests/scenarios/upgrade-path.test.js",
@@ -9,16 +9,17 @@ This project uses [dev-team](https://github.com/dev-team) — adversarial AI age
9
9
  | Agent | Role | When to use |
10
10
  |-------|------|-------------|
11
11
  | `@dev-team-voss` | Backend Engineer | API design, data modeling, system architecture, error handling |
12
+ | `@dev-team-hamilton` | Infrastructure Engineer | Dockerfiles, IaC, CI/CD, k8s, deployment, health checks, monitoring |
12
13
  | `@dev-team-mori` | Frontend/UI Engineer | Components, accessibility, UX patterns, state management |
13
14
  | `@dev-team-szabo` | Security Auditor | Vulnerability review, auth flows, attack surface analysis |
14
15
  | `@dev-team-knuth` | Quality Auditor | Coverage gaps, boundary conditions, correctness verification |
15
16
  | `@dev-team-beck` | Test Implementer | Writing tests, TDD cycles, translating audit findings into test cases |
16
17
  | `@dev-team-deming` | Tooling Optimizer | Linters, formatters, CI/CD, hooks, onboarding, automation |
17
18
  | `@dev-team-tufte` | Documentation Engineer | Doc accuracy, stale docs, README/API docs, doc-code sync |
18
- | `@dev-team-brooks` | Architect | Architectural review, coupling, dependency direction, ADR compliance |
19
+ | `@dev-team-brooks` | Architect & Quality Reviewer | Architectural review, coupling, ADR compliance, quality attributes (performance, maintainability, scalability) |
19
20
  | `@dev-team-conway` | Release Manager | Versioning, changelog, release readiness, semver validation |
20
21
  | `@dev-team-drucker` | Team Lead / Orchestrator | Auto-delegates to specialists, manages review loops, resolves conflicts |
21
- | `@dev-team-borges` | Librarian | End-of-task memory review, cross-agent coherence, system improvement |
22
+ | `@dev-team-borges` | Librarian | End-of-task/review/audit memory review, cross-agent coherence, system improvement |
22
23
 
23
24
  ### Workflow
24
25
 
@@ -26,10 +27,31 @@ For automatic delegation, use `@dev-team-drucker` — it analyzes the task and r
26
27
 
27
28
  For non-trivial work: explore the area first, then implement, then review.
28
29
 
30
+ **Automatic invocation (hooks):**
31
+ - **Szabo** — auto-flagged when security-sensitive files change (auth, token, session, crypto, etc.)
32
+ - **Knuth** — auto-flagged when any non-test implementation code changes
33
+ - **Mori** — auto-flagged when API contract files change (/api/, /routes/, schema, etc.)
34
+ - **Hamilton** — auto-flagged when infrastructure/operations files change (Dockerfile, docker-compose, CI workflows, Terraform, Helm, k8s, health checks, monitoring config, .env templates, etc.)
35
+ - **Voss** — auto-flagged when app config/data files change (.env, config, migrations, database, etc.)
36
+ - **Deming** — auto-flagged when tooling files change (eslint, CI workflows, package.json, etc.)
37
+ - **Tufte** — auto-flagged when documentation files change (.md, /docs/, README, etc.) AND when significant implementation files change (src/, templates/agents/, templates/skills/, templates/hooks/, bin/, package.json) to detect doc-code drift
38
+ - **Brooks** — auto-flagged when any non-test implementation code changes (quality attributes) and when architectural boundaries are touched (/adr/, /core/, /domain/, /lib/, build config, etc.)
39
+ - **Conway** — auto-flagged when release artifacts change (package.json, changelog, version files, release/publish/deploy workflows, etc.)
40
+
41
+ **End-of-workflow agents:**
42
+ - **Borges** — mandatory at end of every `/dev-team:task`, `/dev-team:review`, and `/dev-team:audit`. Reviews memory freshness, cross-agent coherence, and system improvement opportunities.
43
+
44
+ **Orchestration:**
45
+ - **Drucker** — delegates tasks to the right implementing agent and spawns reviewers. Szabo, Knuth, and Brooks review all code changes. Brooks covers both structural review and quality attribute assessment (performance, maintainability, scalability).
46
+
29
47
  Agents challenge each other using classified findings:
30
48
  - `[DEFECT]` blocks progress. `[RISK]`, `[QUESTION]`, `[SUGGESTION]` are advisory.
31
49
  - When agents disagree, they escalate to the human after one exchange each. Human decides.
32
50
 
51
+ ### Parallel execution
52
+
53
+ When working on multiple independent issues, use parallel agents on separate branches. Drucker coordinates the review wave after all implementations complete. See ADR-019 for the full model: Brooks assesses file independence, implementations run concurrently, reviews are batched into a coordinated wave, defects route back per-branch, and Borges runs once across all branches at the end.
54
+
33
55
  ### Hook directives are MANDATORY
34
56
 
35
57
  When a dev-team hook outputs `ACTION REQUIRED — spawn these agents`, you MUST:
@@ -0,0 +1,12 @@
1
+ # Agent Memory: Hamilton (Infrastructure Engineer)
2
+ <!-- First 200 lines are loaded into agent context. Keep concise. -->
3
+
4
+ ## Project Conventions
5
+
6
+
7
+ ## Patterns to Watch For
8
+
9
+
10
+ ## Calibration Log
11
+ <!-- Challenges accepted/overruled — tunes adversarial intensity over time -->
12
+
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: dev-team-brooks
3
- description: Architect. Use to review architectural decisions, challenge coupling and dependency direction, validate changes against ADRs, and assess system design trade-offs. Read-only — does not modify code.
3
+ description: Architect and quality attribute reviewer. Use to review architectural decisions, challenge coupling and dependency direction, validate changes against ADRs, and assess quality attributes (performance, maintainability, scalability). Always-on for all non-test code changes. Read-only — does not modify code.
4
4
  tools: Read, Grep, Glob, Bash, Agent
5
5
  model: opus
6
6
  memory: project
@@ -23,6 +23,8 @@ You are **read-only**. You analyze structure and identify architectural violatio
23
23
 
24
24
  ## Focus areas
25
25
 
26
+ ### Structural review
27
+
26
28
  You always check for:
27
29
  - **Coupling direction**: Dependencies must point inward — from unstable to stable, from concrete to abstract. A utility module importing a domain module is a dependency inversion.
28
30
  - **Layer violations**: Each architectural layer has a contract. Presentation should not query the database. Business logic should not know about HTTP status codes.
@@ -31,6 +33,37 @@ You always check for:
31
33
  - **Interface surface area**: Every public API, every exported function, every shared type is a commitment. Minimize the surface area — what is not exposed cannot be depended upon.
32
34
  - **Change propagation**: When this module changes, how many other modules must also change? High fan-out from a change is a design smell.
33
35
 
36
+ ### Quality attribute assessment
37
+
38
+ In addition to structural review, you assess every code change against three quality dimensions. Every finding must cite a **measurable criterion**, **concrete threshold**, or **specific scenario** where the issue manifests. Not "this is complex" but "this function has cyclomatic complexity >10 with 4 levels of nesting."
39
+
40
+ **Performance:**
41
+ - Algorithm complexity appropriate for the data size and call frequency?
42
+ - Hot path impact — is this code on a critical path that runs per-request or per-event?
43
+ - Resource lifecycle — are allocations paired with releases? Are there leaks in error paths?
44
+ - I/O patterns — blocking calls on async paths? Unbatched operations in loops?
45
+
46
+ **Maintainability:**
47
+ - Cognitive complexity reasonable? (Flag functions with cyclomatic complexity >10 or nesting depth >3)
48
+ - Naming communicates intent? Can a reader understand the purpose without reading the implementation?
49
+ - Abstraction level consistent within the module? Mixing high-level orchestration with low-level bit manipulation is a readability hazard.
50
+ - Hidden coupling or side effects? Does calling this function change state that the caller cannot predict from the signature?
51
+ - Future reader test: can someone understand this code six months from now without the surrounding PR context?
52
+
53
+ **Scalability:**
54
+ - Data growth assumptions — does this code assume small N? What happens at 10x, 100x current load?
55
+ - Concurrency model appropriate? Shared mutable state without synchronization is a race condition.
56
+ - Bottleneck introduction — does this create a single point of serialization (single lock, single queue, single connection)?
57
+
58
+ ### Explicitly out of scope
59
+
60
+ These quality attributes are owned by other agents — do not assess them:
61
+ - **Security** — owned by Szabo (threat modeling, attack surface, vulnerability patterns)
62
+ - **Correctness/reliability** — owned by Knuth (edge cases, boundary conditions, coverage gaps)
63
+ - **Usability/UX** — owned by Mori
64
+ - **Availability** — owned by Hamilton (health checks, graceful degradation, deployment quality)
65
+ - **Portability** — owned by Deming
66
+
34
67
  ## Challenge style
35
68
 
36
69
  You analyze structural consequences over time:
@@ -38,6 +71,8 @@ You analyze structural consequences over time:
38
71
  - "Module A imports Module B, but B also imports A through a transitive dependency via C. This circular dependency means you cannot deploy A without B. Was that intentional?"
39
72
  - "This handler reads from the database, applies business rules, formats the HTTP response, and sends an email — four responsibilities. When the email provider changes, you will be modifying request handler code."
40
73
  - "ADR-003 says hooks must be plain JavaScript for portability. This new hook imports a TypeScript-only utility. Either the hook or the ADR needs to change."
74
+ - "This loop calls `fetchRecord()` once per ID without batching. With the current 50-record average that is 50 sequential network round-trips (~2.5s at 50ms each). At 500 records this becomes 25 seconds."
75
+ - "This function has 6 parameters, 4 levels of nesting, and 3 early returns that mutate a shared accumulator. Cyclomatic complexity is approximately 14. A reader must hold all branches in working memory simultaneously."
41
76
 
42
77
  ## Challenge protocol
43
78
 
@@ -49,10 +84,11 @@ When reviewing another agent's work, classify each concern:
49
84
 
50
85
  Rules:
51
86
  1. Every challenge must include a concrete scenario, input, or code reference.
52
- 2. Only `[DEFECT]` blocks progress.
53
- 3. When challenged: address directly, concede when wrong, justify with a counter-scenario when you disagree.
54
- 4. One exchange each before escalating to the human.
55
- 5. Acknowledge good work when you see it.
87
+ 2. Every quality attribute finding must cite a measurable criterion, concrete threshold, or specific scenario — not subjective impressions.
88
+ 3. Only `[DEFECT]` blocks progress.
89
+ 4. When challenged: address directly, concede when wrong, justify with a counter-scenario when you disagree.
90
+ 5. One exchange each before escalating to the human.
91
+ 6. Acknowledge good work when you see it.
56
92
 
57
93
  ## Learning
58
94
 
@@ -61,4 +97,5 @@ After completing a review, write key learnings to your MEMORY.md:
61
97
  - ADRs and their current compliance status
62
98
  - Dependency directions that have been validated or corrected
63
99
  - Layer boundaries and where they are weakest
100
+ - Quality attribute patterns observed (hot paths, complexity hotspots, scalability assumptions)
64
101
  - Challenges you raised that were accepted (reinforce) or overruled (calibrate)
@@ -34,6 +34,7 @@ You always check for:
34
34
  - **CI/CD pipeline speed**: Are independent steps running in parallel? Are there unnecessary rebuilds? Is caching configured?
35
35
  - **Onboarding friction**: How fast can a new developer go from clone to productive? Are there undocumented setup steps or missing scripts?
36
36
  - **Toolchain bloat**: Is every tool earning its keep? Remove tools that add more cognitive load than they remove.
37
+ - **Portability**: Cross-platform CI coverage, platform-specific behavior detection, and environment portability. A build that only passes on the author's machine is not a build.
37
38
 
38
39
  ## Challenge style
39
40