5-phase-workflow 3.1.0 → 3.1.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 +50 -3
- package/package.json +1 -1
- package/src/commands/5/configure.md +2 -1
package/bin/install.js
CHANGED
|
@@ -1254,8 +1254,9 @@ function removePlanningActiveMarker(dataDir) {
|
|
|
1254
1254
|
// is shared, so performUpdate() and performCodexUpdate() both run this.
|
|
1255
1255
|
function movePlansToPlanningDir(dataDir) {
|
|
1256
1256
|
const featuresDir = path.join(dataDir, 'features');
|
|
1257
|
-
if (!fs.existsSync(featuresDir)) return;
|
|
1257
|
+
if (!fs.existsSync(featuresDir)) return 0;
|
|
1258
1258
|
const planningDir = path.join(dataDir, 'planning');
|
|
1259
|
+
let moved = 0;
|
|
1259
1260
|
try {
|
|
1260
1261
|
for (const feature of fs.readdirSync(featuresDir)) {
|
|
1261
1262
|
const planFile = path.join(featuresDir, feature, 'plan.md');
|
|
@@ -1263,9 +1264,53 @@ function movePlansToPlanningDir(dataDir) {
|
|
|
1263
1264
|
if (!fs.existsSync(planFile) || fs.existsSync(target)) continue;
|
|
1264
1265
|
fs.mkdirSync(planningDir, { recursive: true });
|
|
1265
1266
|
fs.renameSync(planFile, target);
|
|
1267
|
+
moved++;
|
|
1266
1268
|
log.info(`Moved plan: features/${feature}/plan.md → planning/${feature}.md`);
|
|
1267
1269
|
}
|
|
1268
1270
|
} catch (e) {}
|
|
1271
|
+
return moved;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// Before .5/planning/ existed, plans lived in .5/features/, so a project that git-ignored
|
|
1275
|
+
// .5/features/ also ignored its plans. Carry that choice over to .5/planning/, but only for
|
|
1276
|
+
// projects that come from that layout: plans moved by this upgrade, or an install that was
|
|
1277
|
+
// upgraded into 3.1.0 (whose migration moved them without this). A project configured on 3.1
|
|
1278
|
+
// may have chosen "Only .5/features/" on purpose; /5:configure now marks that with
|
|
1279
|
+
// `!.5/planning/`, and any .5/planning rule or plan tracked in git (checked before the move) is left alone.
|
|
1280
|
+
// Shared .5/ data, so both update paths run this.
|
|
1281
|
+
// True when git tracks any plan, in the old or the new location. Call it before plans move:
|
|
1282
|
+
// afterwards the index still lists them only under .5/features/.
|
|
1283
|
+
function hasTrackedPlans(dataDir) {
|
|
1284
|
+
try {
|
|
1285
|
+
return require('child_process')
|
|
1286
|
+
.execFileSync('git', ['ls-files', '--', '.5/features/*/plan.md', '.5/planning'],
|
|
1287
|
+
{ cwd: path.dirname(dataDir), encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
|
|
1288
|
+
.trim() !== '';
|
|
1289
|
+
} catch (e) {
|
|
1290
|
+
return false; // not a git checkout: nothing is tracked
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
function ignorePlanningLikeFeatures(dataDir, movedPlans, previousVersion, plansTracked) {
|
|
1295
|
+
const projectRoot = path.dirname(dataDir);
|
|
1296
|
+
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
1297
|
+
if (!fs.existsSync(gitignorePath)) return;
|
|
1298
|
+
try {
|
|
1299
|
+
if (!movedPlans) {
|
|
1300
|
+
if (previousVersion !== '3.1.0') return;
|
|
1301
|
+
// A fresh 3.1.0 install has installedAt === lastUpdated; an upgraded one does not
|
|
1302
|
+
const versionData = JSON.parse(fs.readFileSync(path.join(dataDir, 'version.json'), 'utf8'));
|
|
1303
|
+
if (!versionData.installedAt || versionData.installedAt === versionData.lastUpdated) return;
|
|
1304
|
+
}
|
|
1305
|
+
if (plansTracked) return;
|
|
1306
|
+
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
1307
|
+
const rules = content.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#'));
|
|
1308
|
+
const ignoresFeatures = rules.some(l => /^\/?\.5\/features\/?(\*\*?)?$/.test(l));
|
|
1309
|
+
const hasPlanningRule = rules.some(l => /^!?\/?\.5\/planning\/?(\*\*?)?$/.test(l));
|
|
1310
|
+
if (!ignoresFeatures || hasPlanningRule) return;
|
|
1311
|
+
fs.writeFileSync(gitignorePath, content.trimEnd() + '\n.5/planning/\n');
|
|
1312
|
+
log.info('Added .5/planning/ to .gitignore (plans were ignored under .5/features/)');
|
|
1313
|
+
} catch (e) {}
|
|
1269
1314
|
}
|
|
1270
1315
|
|
|
1271
1316
|
// Perform update (preserves user-created files, updates .5/ data directory)
|
|
@@ -1294,7 +1339,8 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
|
|
|
1294
1339
|
removePlanningActiveMarker(dataDir);
|
|
1295
1340
|
|
|
1296
1341
|
// Plans moved from .5/features/{name}/plan.md to .5/planning/{name}.md
|
|
1297
|
-
|
|
1342
|
+
const plansTracked = hasTrackedPlans(dataDir);
|
|
1343
|
+
ignorePlanningLikeFeatures(dataDir, movePlansToPlanningDir(dataDir), versionInfo.installed, plansTracked);
|
|
1298
1344
|
|
|
1299
1345
|
// Flag v1 → v2 major upgrade so statusline can prompt for reconfigure
|
|
1300
1346
|
const prevMajor = versionInfo.installed ? parseInt(versionInfo.installed.split('.')[0], 10) : 0;
|
|
@@ -1490,7 +1536,8 @@ function performCodexUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
|
|
|
1490
1536
|
removePlanningActiveMarker(dataDir);
|
|
1491
1537
|
|
|
1492
1538
|
// Plans moved from .5/features/{name}/plan.md to .5/planning/{name}.md
|
|
1493
|
-
|
|
1539
|
+
const plansTracked = hasTrackedPlans(dataDir);
|
|
1540
|
+
ignorePlanningLikeFeatures(dataDir, movePlansToPlanningDir(dataDir), versionInfo.installed, plansTracked);
|
|
1494
1541
|
|
|
1495
1542
|
// Flag v1 → v2 major upgrade so skills can prompt for reconfigure
|
|
1496
1543
|
const prevMajor = versionInfo.installed ? parseInt(versionInfo.installed.split('.')[0], 10) : 0;
|
package/package.json
CHANGED
|
@@ -216,7 +216,8 @@ Native plan mode must save its plans in `.5/planning/`, where `/5:implement` fin
|
|
|
216
216
|
For each folder the user chose to ignore in step 2l (`.5/planning/`, `.5/features/`):
|
|
217
217
|
1. Check if `.gitignore` exists in the project root — create it if not
|
|
218
218
|
2. Check if the folder is already listed — if not, append it on a new line
|
|
219
|
-
3.
|
|
219
|
+
3. When the user chose "Only `.5/features/`", also append `!.5/planning/`, so upgrades know the plans are shared on purpose and do not ignore them
|
|
220
|
+
4. Inform the user which folders were added to `.gitignore`
|
|
220
221
|
|
|
221
222
|
**Always gitignore `.5/.reconfig-reminder`:**
|
|
222
223
|
|