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 +147 -66
- package/package.json +1 -1
- package/src/commands/5/configure.md +25 -19
- package/src/commands/5/discuss-feature.md +4 -2
- package/src/commands/5/implement-feature.md +22 -5
- package/src/commands/5/plan-feature.md +77 -38
- package/src/commands/5/plan-implementation.md +62 -29
- package/src/commands/5/quick-implement.md +2 -1
- package/src/commands/5/reconfigure.md +3 -3
- package/src/commands/5/review-code.md +7 -7
- package/src/references/configure-tables.md +1 -1
- package/src/skills/configure-docs-index/SKILL.md +35 -17
- package/src/skills/configure-skills/SKILL.md +2 -2
- package/src/skills/generate-readme/SKILL.md +1 -1
- package/src/skills/generate-readme/TEMPLATE.md +5 -5
- package/src/templates/workflow/FEATURE-SPEC.md +58 -24
- package/src/templates/workflow/PLAN.md +15 -14
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
|
-
|
|
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.
|
|
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
|
-
//
|
|
676
|
-
|
|
677
|
-
|
|
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
|
-
|
|
681
|
-
|
|
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
|
|
685
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
1367
|
-
|
|
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
|
-
|
|
1372
|
-
|
|
1373
|
-
log.info(`Available: ${versionInfo.available}`);
|
|
1432
|
+
const primaryRuntime = activeRuntime;
|
|
1433
|
+
let anyUpdateAvailable = false;
|
|
1374
1434
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
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
|
@@ -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 `
|
|
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. "
|
|
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
|
|
211
|
-
- "Generate/update
|
|
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
|
|
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
|
|
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
|
|
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
|
-
**
|
|
352
|
-
-
|
|
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
|
-
- [ ] `
|
|
392
|
-
- [ ] `
|
|
393
|
-
- [ ] `
|
|
394
|
-
- [ ]
|
|
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
|
-
-
|
|
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. **
|
|
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.
|
|
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
|
-
{
|
|
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. **
|
|
242
|
-
|
|
243
|
-
|
|
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
|