5-phase-workflow 1.8.9 → 1.9.1

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.
package/bin/install.js CHANGED
@@ -38,13 +38,17 @@ function compareVersions(v1, v2) {
38
38
  }
39
39
 
40
40
  // Get installed version from .5/version.json
41
+ // Reads per-runtime version when available (runtimes[activeRuntime].packageVersion),
42
+ // falling back to top-level packageVersion for backward compatibility.
41
43
  function getInstalledVersion(isGlobal) {
42
44
  const versionFile = path.join(getDataPath(isGlobal), 'version.json');
43
45
  if (!fs.existsSync(versionFile)) return null;
44
46
 
45
47
  try {
46
48
  const data = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
47
- return data.packageVersion;
49
+ return (data.runtimes && data.runtimes[activeRuntime] && data.runtimes[activeRuntime].packageVersion)
50
+ || data.packageVersion
51
+ || null;
48
52
  } catch (e) {
49
53
  return null; // Corrupted file, treat as missing
50
54
  }
@@ -280,8 +284,7 @@ const LEGACY_REMOVED_FILES = [
280
284
  'templates/STACK.md',
281
285
  'templates/STRUCTURE.md',
282
286
  'templates/CONVENTIONS.md',
283
- 'templates/INTEGRATIONS.md',
284
- 'skills/configure-project'
287
+ 'templates/INTEGRATIONS.md'
285
288
  ];
286
289
 
287
290
  // Get list of workflow-owned files/directories (not user-created)
@@ -298,6 +301,7 @@ function getWorkflowManagedFiles() {
298
301
  // Skills: specific skill directories
299
302
  skills: [
300
303
  'configure-docs-index',
304
+ 'configure-project',
301
305
  'configure-skills',
302
306
  'generate-readme'
303
307
  ],
@@ -624,7 +628,10 @@ function cleanupOrphanedFiles(targetPath, dataDir) {
624
628
  if (fs.existsSync(versionFile)) {
625
629
  try {
626
630
  const data = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
627
- oldManifest = data.manifest || null;
631
+ // Prefer per-runtime manifest to avoid cross-runtime orphan cleanup
632
+ oldManifest = (data.runtimes && data.runtimes[activeRuntime] && data.runtimes[activeRuntime].manifest)
633
+ || data.manifest
634
+ || null;
628
635
  } catch (e) {
629
636
  // Corrupted file, treat as no manifest
630
637
  }
@@ -651,7 +658,12 @@ function cleanupOrphanedFiles(targetPath, dataDir) {
651
658
  for (const entry of LEGACY_REMOVED_FILES) {
652
659
  const fullPath = path.join(targetPath, entry);
653
660
  if (fs.existsSync(fullPath)) {
654
- fs.unlinkSync(fullPath);
661
+ const stat = fs.statSync(fullPath);
662
+ if (stat.isDirectory()) {
663
+ removeDir(fullPath);
664
+ } else {
665
+ fs.unlinkSync(fullPath);
666
+ }
655
667
  log.info(`Removed legacy orphan: ${entry}`);
656
668
  }
657
669
  }
@@ -672,27 +684,73 @@ function ensureDotFiveGitignore(dataDir) {
672
684
  }
673
685
  }
674
686
 
675
- // Initialize version.json after successful install
676
- function initializeVersionJson(isGlobal) {
677
- const dataDir = getDataPath(isGlobal);
687
+ // Write (or update) version.json, preserving per-runtime state for other runtimes.
688
+ // - Reads existing file to preserve the other runtime's runtimes[] entry.
689
+ // - Writes runtimes[activeRuntime] with current version + manifest.
690
+ // - Top-level packageVersion = minimum across all runtime versions (so hooks
691
+ // detect an update if ANY runtime is behind).
692
+ function writeVersionJson(dataDir, isGlobal, version) {
678
693
  const versionFile = path.join(dataDir, 'version.json');
694
+ const now = new Date().toISOString();
679
695
 
680
- if (!fs.existsSync(dataDir)) {
681
- fs.mkdirSync(dataDir, { recursive: true });
696
+ let existing = {};
697
+ if (fs.existsSync(versionFile)) {
698
+ try {
699
+ existing = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
700
+ } catch (e) {
701
+ existing = {};
702
+ }
682
703
  }
683
704
 
684
- const version = getPackageVersion();
685
- const now = new Date().toISOString();
686
-
687
- const versionData = {
705
+ const runtimes = existing.runtimes || {};
706
+ runtimes[activeRuntime] = {
688
707
  packageVersion: version,
689
- installedAt: now,
690
708
  lastUpdated: now,
691
- installationType: isGlobal ? 'global' : 'local',
692
709
  manifest: getFileManifest()
693
710
  };
694
711
 
712
+ // Top-level packageVersion = min across all runtime versions
713
+ const runtimeVersions = Object.values(runtimes).map(r => r.packageVersion).filter(Boolean);
714
+ const minVersion = runtimeVersions.reduce((min, v) => compareVersions(v, min) < 0 ? v : min, version);
715
+
716
+ const versionData = {
717
+ packageVersion: minVersion,
718
+ installedAt: existing.installedAt || now,
719
+ lastUpdated: now,
720
+ installationType: existing.installationType || (isGlobal ? 'global' : 'local'),
721
+ manifest: runtimes[activeRuntime].manifest,
722
+ runtimes
723
+ };
724
+
725
+ if (!fs.existsSync(dataDir)) {
726
+ fs.mkdirSync(dataDir, { recursive: true });
727
+ }
695
728
  fs.writeFileSync(versionFile, JSON.stringify(versionData, null, 2));
729
+ }
730
+
731
+ // Detect which runtimes are actually installed by probing marker files.
732
+ function getInstalledRuntimes(isGlobal) {
733
+ const installed = [];
734
+ const saved = activeRuntime;
735
+ for (const rt of ['claude', 'codex']) {
736
+ activeRuntime = rt;
737
+ const tp = getTargetPath(isGlobal);
738
+ if (checkExistingInstallation(tp)) installed.push(rt);
739
+ }
740
+ activeRuntime = saved;
741
+ return installed;
742
+ }
743
+
744
+ // Initialize version.json after successful install
745
+ function initializeVersionJson(isGlobal) {
746
+ const dataDir = getDataPath(isGlobal);
747
+
748
+ if (!fs.existsSync(dataDir)) {
749
+ fs.mkdirSync(dataDir, { recursive: true });
750
+ }
751
+
752
+ const version = getPackageVersion();
753
+ writeVersionJson(dataDir, isGlobal, version);
696
754
  ensureDotFiveGitignore(dataDir);
697
755
  log.success('Initialized version tracking');
698
756
  }
@@ -863,25 +921,8 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
863
921
  // Merge settings (deep merge preserves user customizations)
864
922
  mergeSettings(targetPath, sourcePath);
865
923
 
866
- // Update version.json
867
- const versionFile = path.join(dataDir, 'version.json');
868
- const now = new Date().toISOString();
869
-
870
- const existing = fs.existsSync(versionFile)
871
- ? JSON.parse(fs.readFileSync(versionFile, 'utf8'))
872
- : {};
873
- const versionData = {
874
- packageVersion: versionInfo.available,
875
- installedAt: existing.installedAt || now,
876
- lastUpdated: now,
877
- installationType: existing.installationType || (isGlobal ? 'global' : 'local'),
878
- manifest: getFileManifest()
879
- };
880
-
881
- if (!fs.existsSync(dataDir)) {
882
- fs.mkdirSync(dataDir, { recursive: true });
883
- }
884
- fs.writeFileSync(versionFile, JSON.stringify(versionData, null, 2));
924
+ // Update version.json (per-runtime, preserving other runtime's state)
925
+ writeVersionJson(dataDir, isGlobal, versionInfo.available);
885
926
  ensureDotFiveGitignore(dataDir);
886
927
 
887
928
  // Create features directory if it doesn't exist
@@ -1087,24 +1128,8 @@ function performCodexUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1087
1128
  const dataDir = getDataPath(isGlobal);
1088
1129
  cleanupOrphanedFiles(targetPath, dataDir);
1089
1130
 
1090
- // Update version.json
1091
- const versionFile = path.join(dataDir, 'version.json');
1092
- const now = new Date().toISOString();
1093
- const existing = fs.existsSync(versionFile)
1094
- ? JSON.parse(fs.readFileSync(versionFile, 'utf8'))
1095
- : {};
1096
- const versionData = {
1097
- packageVersion: versionInfo.available,
1098
- installedAt: existing.installedAt || now,
1099
- lastUpdated: now,
1100
- installationType: existing.installationType || (isGlobal ? 'global' : 'local'),
1101
- manifest: getFileManifest()
1102
- };
1103
-
1104
- if (!fs.existsSync(dataDir)) {
1105
- fs.mkdirSync(dataDir, { recursive: true });
1106
- }
1107
- fs.writeFileSync(versionFile, JSON.stringify(versionData, null, 2));
1131
+ // Update version.json (per-runtime, preserving other runtime's state)
1132
+ writeVersionJson(dataDir, isGlobal, versionInfo.available);
1108
1133
  ensureDotFiveGitignore(dataDir);
1109
1134
 
1110
1135
  const featuresDir = path.join(dataDir, 'features');
@@ -1211,6 +1236,7 @@ function install(isGlobal, forceUpgrade = false) {
1211
1236
  log.warn('Detected legacy installation (no version tracking)');
1212
1237
  log.info(`Upgrading from legacy install to ${versionInfo.available}`);
1213
1238
  update(targetPath, sourcePath, isGlobal, versionInfo);
1239
+ updateOtherRuntime(isGlobal);
1214
1240
  return;
1215
1241
  } else if (versionInfo.needsUpdate) {
1216
1242
  log.info(`Installed: ${versionInfo.installed}`);
@@ -1230,11 +1256,13 @@ function install(isGlobal, forceUpgrade = false) {
1230
1256
  return;
1231
1257
  }
1232
1258
  update(targetPath, sourcePath, isGlobal, versionInfo);
1259
+ updateOtherRuntime(isGlobal);
1233
1260
  });
1234
1261
  return; // Wait for user input
1235
1262
  }
1236
1263
  // Force upgrade, no prompt
1237
1264
  update(targetPath, sourcePath, isGlobal, versionInfo);
1265
+ updateOtherRuntime(isGlobal);
1238
1266
  return;
1239
1267
  } else {
1240
1268
  // Same version
@@ -1247,6 +1275,31 @@ function install(isGlobal, forceUpgrade = false) {
1247
1275
  freshInstall(targetPath, sourcePath, isGlobal);
1248
1276
  }
1249
1277
 
1278
+ // After updating the active runtime, check if the other runtime is also installed
1279
+ // and needs an update. Updates it silently if so.
1280
+ function updateOtherRuntime(isGlobal) {
1281
+ const primaryRuntime = activeRuntime;
1282
+ const installed = getInstalledRuntimes(isGlobal);
1283
+
1284
+ for (const rt of installed) {
1285
+ if (rt === primaryRuntime) continue;
1286
+
1287
+ activeRuntime = rt;
1288
+ const tp = getTargetPath(isGlobal);
1289
+ const sp = getSourcePath();
1290
+ const vi = getVersionInfo(tp, isGlobal);
1291
+
1292
+ if (vi.exists && (vi.needsUpdate || vi.legacy)) {
1293
+ const updateFn = rt === 'codex' ? performCodexUpdate : performUpdate;
1294
+ updateFn(tp, sp, isGlobal, vi);
1295
+ } else if (vi.exists) {
1296
+ log.success(`${rt}: already at version ${vi.installed}`);
1297
+ }
1298
+ }
1299
+
1300
+ activeRuntime = primaryRuntime;
1301
+ }
1302
+
1250
1303
  // Perform uninstallation
1251
1304
  function uninstall() {
1252
1305
  if (activeRuntime === 'codex') {
@@ -1270,7 +1323,12 @@ function uninstall() {
1270
1323
  for (const entry of LEGACY_REMOVED_FILES) {
1271
1324
  const fullPath = path.join(targetPath, entry);
1272
1325
  if (fs.existsSync(fullPath)) {
1273
- fs.unlinkSync(fullPath);
1326
+ const stat = fs.statSync(fullPath);
1327
+ if (stat.isDirectory()) {
1328
+ removeDir(fullPath);
1329
+ } else {
1330
+ fs.unlinkSync(fullPath);
1331
+ }
1274
1332
  log.info(`Removed legacy orphan: ${entry}`);
1275
1333
  }
1276
1334
  }
@@ -1359,25 +1417,48 @@ function main() {
1359
1417
  }
1360
1418
 
1361
1419
  if (options.check) {
1362
- const targetPath = getTargetPath(options.global);
1363
1420
  migrateDataDir(options.global);
1364
- const versionInfo = getVersionInfo(targetPath, options.global);
1365
1421
 
1366
- if (!versionInfo.exists) {
1367
- log.info(`Not installed (${activeRuntime})`);
1422
+ // When --codex is explicitly passed, check only Codex. Otherwise check all installed runtimes.
1423
+ const runtimesToCheck = options.runtime === 'codex'
1424
+ ? ['codex']
1425
+ : getInstalledRuntimes(options.global);
1426
+
1427
+ if (runtimesToCheck.length === 0) {
1428
+ log.info('Not installed');
1368
1429
  return;
1369
1430
  }
1370
1431
 
1371
- log.info(`Runtime: ${activeRuntime}`);
1372
- log.info(`Installed: ${versionInfo.installed || 'legacy (no version)'}`);
1373
- log.info(`Available: ${versionInfo.available}`);
1432
+ const primaryRuntime = activeRuntime;
1433
+ let anyUpdateAvailable = false;
1374
1434
 
1375
- if (versionInfo.needsUpdate) {
1376
- log.warn('Update available');
1377
- log.info(`Run: npx 5-phase-workflow${activeRuntime === 'codex' ? ' --codex' : ''} --upgrade`);
1378
- } else {
1379
- log.success('Up to date');
1435
+ for (const rt of runtimesToCheck) {
1436
+ activeRuntime = rt;
1437
+ const tp = getTargetPath(options.global);
1438
+ const vi = getVersionInfo(tp, options.global);
1439
+
1440
+ if (!vi.exists) {
1441
+ log.info(`${rt}: not installed`);
1442
+ continue;
1443
+ }
1444
+
1445
+ log.info(`Runtime: ${rt}`);
1446
+ log.info(`Installed: ${vi.installed || 'legacy (no version)'}`);
1447
+ log.info(`Available: ${vi.available}`);
1448
+
1449
+ if (vi.needsUpdate) {
1450
+ log.warn(`${rt}: update available`);
1451
+ anyUpdateAvailable = true;
1452
+ } else {
1453
+ log.success(`${rt}: up to date`);
1454
+ }
1380
1455
  }
1456
+
1457
+ if (anyUpdateAvailable) {
1458
+ log.info('Run: npx 5-phase-workflow --upgrade');
1459
+ }
1460
+
1461
+ activeRuntime = primaryRuntime;
1381
1462
  return;
1382
1463
  }
1383
1464
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5-phase-workflow",
3
- "version": "1.8.9",
3
+ "version": "1.9.1",
4
4
  "description": "A 5-phase feature development workflow for Claude Code",
5
5
  "bin": {
6
6
  "5-phase-workflow": "bin/install.js"
@@ -9,7 +9,7 @@ context: fork
9
9
 
10
10
  <role>
11
11
  You are a Project Configurator. You analyze a project, gather preferences, and write config.json plus a feature spec.
12
- You do NOT generate CLAUDE.md, documentation files, or skills directly — those are Phase 3's job.
12
+ You do NOT generate AGENTS.md, CLAUDE.md, documentation files, or skills directly — those are Phase 3's job.
13
13
  You write ONLY to: .5/config.json, .5/version.json, .5/features/CONFIGURE/feature.md, and .gitignore.
14
14
  After writing config.json and the feature spec, you are DONE. Exit immediately.
15
15
  </role>
@@ -39,7 +39,7 @@ Your job in this command:
39
39
  ✅ Tell user to run /5:plan-implementation CONFIGURE
40
40
 
41
41
  Your job is NOT:
42
- ❌ Create CLAUDE.md directly (Phase 3 does this)
42
+ ❌ Create AGENTS.md or CLAUDE.md directly (Phase 3 does this)
43
43
  ❌ Generate documentation files directly (Phase 3 does this)
44
44
  ❌ Generate skills directly (Phase 3 does this)
45
45
  ❌ Skip user interaction
@@ -47,7 +47,7 @@ Your job is NOT:
47
47
 
48
48
  **After writing config.json, creating the feature spec, and informing the user, YOUR JOB IS COMPLETE. EXIT IMMEDIATELY.**
49
49
 
50
- **If you find yourself creating CLAUDE.md, documentation files, or skills, STOP IMMEDIATELY. You should only be writing config.json and the feature spec.**
50
+ **If you find yourself creating AGENTS.md, CLAUDE.md, documentation files, or skills, STOP IMMEDIATELY. You should only be writing config.json and the feature spec.**
51
51
 
52
52
  ## Configuration Process
53
53
 
@@ -92,8 +92,9 @@ fi
92
92
  # Set skill_creator_available=true if any skill-creator tool is found.
93
93
  ```
94
94
 
95
- **1e. Check CLAUDE.md:**
96
- - If `CLAUDE.md` exists, read its content
95
+ **1e. Check AGENTS.md / CLAUDE.md:**
96
+ - If `AGENTS.md` exists, read its content
97
+ - If `AGENTS.md` does not exist but `CLAUDE.md` exists with real content (not just `@AGENTS.md`), read it — this is a legacy setup that will be migrated to AGENTS.md during Phase 3
97
98
 
98
99
  **1f. Scan existing skills:**
99
100
  - Check `.claude/skills/` for existing project-specific skills
@@ -169,7 +170,7 @@ If "Cancel": Exit immediately with message "Configuration unchanged."
169
170
  **2h. Review tool preference:**
170
171
  - "Which code review tool would you like to use?"
171
172
  - Options:
172
- 1. "Claude (built-in, no setup needed)" — always available
173
+ 1. "Native (built-in agent review, no setup needed)" — always available, works with any AI coding tool
173
174
  2. "CodeRabbit CLI (requires installation)" — external tool
174
175
  3. "None (skip automated review)"
175
176
  - If user selects CodeRabbit and it was not detected in Step 1d:
@@ -207,14 +208,14 @@ The skill-creator plugin from the official Claude store helps generate higher-qu
207
208
  - If user selects "Install now": execute the install command, then set `tools.skillCreator.available = true` in the config
208
209
  - If user selects "Skip": `tools.skillCreator.available` remains `false`
209
210
 
210
- **2k. Confirm CLAUDE.md generation:**
211
- - "Generate/update CLAUDE.md? This will analyze your codebase to document structure and conventions."
211
+ **2k. Confirm AGENTS.md generation:**
212
+ - "Generate/update AGENTS.md? This will analyze your codebase to document structure and conventions. (A CLAUDE.md shim will also be created for Claude Code compatibility.)"
212
213
  - Options: "Yes (recommended)", "Skip"
213
214
 
214
215
  **2k2. Confirm rules generation:**
215
- - "Generate `.claude/rules/` files? These are scoped instruction files that automatically load when Claude works with matching file types (e.g., testing rules load only when editing test files, code-style rules load only for source files)."
216
+ - "Generate `.claude/rules/` files? These are scoped instruction files that automatically load when the agent works with matching file types (e.g., testing rules load only when editing test files, code-style rules load only for source files)."
216
217
  - Options: "Yes (recommended)", "Skip"
217
- - Note: Rules complement CLAUDE.md — they provide focused, file-type-scoped directives derived from your project's actual conventions.
218
+ - Note: Rules complement AGENTS.md — they provide focused, file-type-scoped directives derived from your project's actual conventions.
218
219
 
219
220
  **2l. Review detected patterns for skill generation:**
220
221
 
@@ -307,7 +308,7 @@ Write `.5/features/CONFIGURE/feature.md` containing all gathered data:
307
308
  # Feature: Project Configuration
308
309
 
309
310
  ## Summary
310
- Generates CLAUDE.md, a rebuildable codebase index, and project-specific skills. (config.json already written.)
311
+ Generates AGENTS.md, CLAUDE.md shim, a rebuildable codebase index, and project-specific skills. (config.json already written.)
311
312
 
312
313
  ## Requirements
313
314
 
@@ -328,7 +329,7 @@ Analyze the codebase and generate focused documentation capturing only non-deriv
328
329
  - Skip empty categories; do not create placeholder index files
329
330
  - Re-running the script should fully refresh the index in place
330
331
 
331
- **Create CLAUDE.md:**
332
+ **Create AGENTS.md** (provider-agnostic instructions file):
332
333
  - Project overview and build commands
333
334
  - Links to whichever `.5/` documentation files were created
334
335
  - Links to `.5/index/README.md`, the generated index files, and `.5/index/rebuild-index.sh`
@@ -348,8 +349,12 @@ Analyze the codebase and generate focused documentation capturing only non-deriv
348
349
  5. Respect SRP and DRY
349
350
  6. Make code maintainable and modular
350
351
 
351
- **Preserve existing content:**
352
- - If CLAUDE.md already exists, preserve user-written custom sections
352
+ **Create CLAUDE.md shim:**
353
+ - Contains only `@AGENTS.md` (Claude Code include syntax)
354
+
355
+ **Migrate and preserve existing content:**
356
+ - If AGENTS.md already exists, preserve user-written custom sections
357
+ - If CLAUDE.md exists with real content (not just `@AGENTS.md`), migrate content to AGENTS.md and replace CLAUDE.md with the shim
353
358
 
354
359
  ### Requirement 2: Generate Project-Specific Skills
355
360
  Handled by: `configure-skills`
@@ -388,13 +393,14 @@ Only generate rules for patterns that were actually detected:
388
393
  - [ ] `.5/index/README.md` exists and documents the generated index files
389
394
  - [ ] Multiple focused `.5/index/*.md` files are generated for applicable codebase concerns
390
395
  - [ ] Empty sections omitted (no "Not detected" / "None found" placeholders)
391
- - [ ] `CLAUDE.md` exists with references to created `.5/` files
392
- - [ ] `CLAUDE.md` links to the codebase index and rebuild script
393
- - [ ] `CLAUDE.md` says to regenerate the index if it is older than one day
394
- - [ ] CLAUDE.md contains 6 coding guidelines
396
+ - [ ] `AGENTS.md` exists with references to created `.5/` files
397
+ - [ ] `AGENTS.md` links to the codebase index and rebuild script
398
+ - [ ] `AGENTS.md` says to regenerate the index if it is older than one day
399
+ - [ ] `AGENTS.md` contains 6 coding guidelines
400
+ - [ ] `CLAUDE.md` exists and contains only `@AGENTS.md`
395
401
  - [ ] All specified project-specific skills are generated in `.claude/skills/`
396
402
  - [ ] Generated skills reference actual project conventions
397
- - [ ] If CLAUDE.md existed before, user-written sections are preserved
403
+ - [ ] If AGENTS.md or CLAUDE.md existed before, user-written sections are preserved in AGENTS.md
398
404
  - [ ] `.claude/rules/` directory exists with scoped rule files (if rules generation selected)
399
405
  - [ ] Generated rules use `paths:` frontmatter for scoping where applicable
400
406
  - [ ] Rules contain concise directives, not documentation
@@ -92,7 +92,7 @@ Extract current state:
92
92
  - Business rules
93
93
  - Acceptance criteria
94
94
  - Alternatives considered
95
- - Questions & Answers
95
+ - Decisions (with [DECIDED]/[FLEXIBLE]/[DEFERRED] labels)
96
96
 
97
97
  ### Step 3: Initial Discussion Prompt
98
98
 
@@ -117,6 +117,8 @@ Use `multiSelect: false` to get single focus area initially.
117
117
 
118
118
  Based on the user's focus area, explore the codebase if needed:
119
119
 
120
+ **Index shortcut:** Before spawning Explore agents or running Glob/Grep, check if `.5/index/` exists. If it does, read `.5/index/README.md` first for the generation timestamp — if fresh (under 1 day old), read the relevant index files (e.g., modules.md for scope changes, routes.md for API discussions, models.md for data model questions) to quickly gather context and skip broad scanning. If outdated, inform the user they can run `.5/index/rebuild-index.sh` to refresh it. If `.5/index/` does not exist, inform the user they can run `/5:reconfigure` to generate it. In both missing/outdated cases, fall back to Glob/Grep or Explore agents for exploration.
121
+
120
122
  **For technical constraint discussions:**
121
123
  - Search for similar implementations
122
124
  - Check existing patterns
@@ -162,7 +164,7 @@ When user indicates they're done discussing, update `.5/features/{feature-name}/
162
164
  7. **Business Rules** - If logic clarified
163
165
  8. **Acceptance Criteria** - Add/refine verification criteria
164
166
  9. **Alternatives Considered** - Document discussed alternatives
165
- 10. **Questions & Answers** - Append new Q&A from this session
167
+ 10. **Decisions** - Append new decisions from this session, tagged [DECIDED], [FLEXIBLE], or [DEFERRED] using Context/Decision format
166
168
 
167
169
  **Preserve existing content** - Only update sections that changed during discussion.
168
170
 
@@ -163,7 +163,8 @@ Before executing step N (where N > 1), verify that prior steps' outputs exist on
163
163
  - Log: `"⚠ Pre-step check: {file} from step {M} component {name} not found on disk"`
164
164
  - Move the component back from `completedComponents` to `pendingComponents`
165
165
  - STOP execution for this step. Report to user: `"Step {N} blocked: prior step output missing. Re-run step {M} or fix manually."`
166
- 3. If all files verified, proceed to 3a
166
+ 3. **Depends On check:** For each component in step N that has a `Depends On` value (not `—`), verify the named dependency component is in `completedComponents`. If a dependency is in `failedAttempts`, STOP and report: `"Step {N} component {name} blocked: dependency {dep} failed."`
167
+ 4. If all files and dependencies verified, proceed to 3a
167
168
 
168
169
  This prevents cascading failures where step N assumes step N-1's outputs exist but they don't.
169
170
 
@@ -202,11 +203,20 @@ Task tool call:
202
203
  ## Read First
203
204
  {Pattern File value(s) from plan table — executor MUST read these before writing any code}
204
205
 
206
+ ## Dependencies
207
+ {If Depends On is not "—": "This component depends on {dep-name} ({dep-file}). Read that file first to understand the exports/types you need to use."}
208
+ {If Depends On is "—": omit this section entirely}
209
+
210
+ ## Codebase Context (optional)
211
+ If you need to understand how this component relates to other modules (imports, service boundaries, data flow), check `.5/index/` for quick reference — especially modules.md and libraries.md. Only if these files exist.
212
+
205
213
  ## Verify
206
214
  {Verify command(s) from plan table — executor runs these after implementation}
207
215
 
208
216
  ## Implementation Notes
209
- {relevant notes from plan}
217
+ {ONLY notes relevant to this step/component — filter by [Step N] or [component-name] prefix.
218
+ Include untagged notes only if they are globally relevant (e.g., "all services use dependency injection").
219
+ Do NOT send all notes to every agent — this wastes context.}
210
220
  ```
211
221
 
212
222
  The agent file defines the implementation process, output format, and deviation rules. If the agent file is not found (local install), fall back to `.claude/agents/component-executor.md` relative to the project root.
@@ -238,9 +248,16 @@ Mark the current step's TaskCreate task as `completed`. Mark the next step's tas
238
248
 
239
249
  For each component that returned `STATUS: failed`:
240
250
 
241
- 1. **Assess the error:**
242
- - **Small fix** (missing import, wrong path, syntax error): Fix with Edit tool directly in main context. Mark as completed. This counts as retry 1.
243
- - **Large fix** (logic error, wrong pattern, missing context): Re-spawn the component-executor agent with the same prompt plus an `## Error Context` block describing the previous failure. This counts as retry 1.
251
+ 1. **Always re-spawn an agent** — NEVER fix code directly in the orchestrator context, not even for small fixes like missing imports or wrong paths. The orchestrator stays slim and delegates ALL code work.
252
+
253
+ Re-spawn the component-executor agent with the same prompt plus an `## Error Context` block describing the previous failure.
254
+
255
+ **Model upgrade on retry:** Bump the model one tier up from the original complexity:
256
+ - `simple` (haiku) → retry with `sonnet`
257
+ - `moderate` (haiku/sonnet) → retry with `sonnet`
258
+ - `complex` (sonnet) → retry with `sonnet` (already max)
259
+
260
+ This gives the retry agent better reasoning to solve what the first attempt couldn't.
244
261
 
245
262
  2. If the retry also fails:
246
263
  - Update `retryCount: 2` in the component's `failedAttempts` entry