@undeemed/get-shit-done-codex 1.24.1 → 1.24.3
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/README.md +72 -12
- package/get-shit-done/AGENTS.md +59 -23
- package/get-shit-done/bin/gsd-tools.cjs +293 -124
- package/get-shit-done/bin/lib/core.cjs +16 -16
- package/get-shit-done/references/model-profile-resolution.md +2 -2
- package/get-shit-done/references/model-profiles.md +29 -29
- package/get-shit-done/workflows/help.md +3 -3
- package/get-shit-done/workflows/new-project.md +6 -6
- package/get-shit-done/workflows/set-profile.md +3 -3
- package/get-shit-done/workflows/settings.md +3 -3
- package/package.json +3 -2
- package/scripts/run-tests.cjs +38 -24
|
@@ -122,25 +122,35 @@
|
|
|
122
122
|
const fs = require('fs');
|
|
123
123
|
const path = require('path');
|
|
124
124
|
const { execSync } = require('child_process');
|
|
125
|
+
const stateLib = require('./lib/state.cjs');
|
|
126
|
+
const phaseLib = require('./lib/phase.cjs');
|
|
127
|
+
const milestoneLib = require('./lib/milestone.cjs');
|
|
128
|
+
const initLib = require('./lib/init.cjs');
|
|
129
|
+
const commandsLib = require('./lib/commands.cjs');
|
|
130
|
+
const configLib = require('./lib/config.cjs');
|
|
131
|
+
const roadmapLib = require('./lib/roadmap.cjs');
|
|
132
|
+
const templateLib = require('./lib/template.cjs');
|
|
133
|
+
const frontmatterLib = require('./lib/frontmatter.cjs');
|
|
134
|
+
const verifyLib = require('./lib/verify.cjs');
|
|
125
135
|
|
|
126
136
|
// ─── Model Profile Table ─────────────────────────────────────────────────────
|
|
127
137
|
|
|
128
138
|
const MODEL_PROFILES = {
|
|
129
|
-
// quality
|
|
130
|
-
'gsd-planner': { quality: { m: 'gpt-5.3-codex', t: '
|
|
131
|
-
'gsd-roadmapper': { quality: { m: 'gpt-5.3-codex', t: '
|
|
132
|
-
'gsd-executor': { quality: { m: 'gpt-5.3-codex', t: '
|
|
133
|
-
'gsd-phase-researcher': { quality: { m: 'gpt-5.3-codex', t: '
|
|
134
|
-
'gsd-project-researcher': { quality: { m: 'gpt-5.3-codex', t: '
|
|
135
|
-
'gsd-research-synthesizer': { quality: { m: 'gpt-5.3-codex', t: '
|
|
136
|
-
'gsd-debugger': { quality: { m: 'gpt-5.3-codex', t: '
|
|
137
|
-
'gsd-codebase-mapper': { quality: { m: 'gpt-5.3-codex', t: '
|
|
138
|
-
'gsd-verifier': { quality: { m: 'gpt-5.3-codex', t: '
|
|
139
|
-
'gsd-plan-checker': { quality: { m: 'gpt-5.3-codex', t: '
|
|
140
|
-
'gsd-integration-checker': { quality: { m: 'gpt-5.3-codex', t: '
|
|
139
|
+
// quality balanced budget
|
|
140
|
+
'gsd-planner': { quality: { m: 'gpt-5.3-codex', t: 'xhigh' }, balanced: { m: 'gpt-5.3-codex', t: 'xhigh' }, budget: { m: 'gpt-5.3-codex', t: 'high' } },
|
|
141
|
+
'gsd-roadmapper': { quality: { m: 'gpt-5.3-codex', t: 'xhigh' }, balanced: { m: 'gpt-5.3-codex', t: 'high' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
142
|
+
'gsd-executor': { quality: { m: 'gpt-5.3-codex', t: 'xhigh' }, balanced: { m: 'gpt-5.3-codex', t: 'high' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
143
|
+
'gsd-phase-researcher': { quality: { m: 'gpt-5.3-codex', t: 'high' }, balanced: { m: 'gpt-5.3-codex', t: 'medium' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
144
|
+
'gsd-project-researcher': { quality: { m: 'gpt-5.3-codex', t: 'high' }, balanced: { m: 'gpt-5.3-codex', t: 'medium' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
145
|
+
'gsd-research-synthesizer': { quality: { m: 'gpt-5.3-codex', t: 'high' }, balanced: { m: 'gpt-5.3-codex', t: 'medium' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
146
|
+
'gsd-debugger': { quality: { m: 'gpt-5.3-codex', t: 'xhigh' }, balanced: { m: 'gpt-5.3-codex', t: 'xhigh' }, budget: { m: 'gpt-5.3-codex', t: 'high' } },
|
|
147
|
+
'gsd-codebase-mapper': { quality: { m: 'gpt-5.3-codex', t: 'medium' }, balanced: { m: 'gpt-5.3-codex', t: 'medium' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
148
|
+
'gsd-verifier': { quality: { m: 'gpt-5.3-codex', t: 'high' }, balanced: { m: 'gpt-5.3-codex', t: 'high' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
149
|
+
'gsd-plan-checker': { quality: { m: 'gpt-5.3-codex', t: 'high' }, balanced: { m: 'gpt-5.3-codex', t: 'medium' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
150
|
+
'gsd-integration-checker': { quality: { m: 'gpt-5.3-codex', t: 'high' }, balanced: { m: 'gpt-5.3-codex', t: 'medium' }, budget: { m: 'gpt-5.3-codex', t: 'medium' } },
|
|
141
151
|
};
|
|
142
152
|
|
|
143
|
-
const DEFAULT_ENTRY = { m: 'gpt-5.3-codex', t: '
|
|
153
|
+
const DEFAULT_ENTRY = { m: 'gpt-5.3-codex', t: 'high' };
|
|
144
154
|
|
|
145
155
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
146
156
|
|
|
@@ -247,12 +257,80 @@ function execGit(cwd, args) {
|
|
|
247
257
|
}
|
|
248
258
|
|
|
249
259
|
function normalizePhaseName(phase) {
|
|
250
|
-
const match = phase.match(/^(\d+(?:\.\d+)
|
|
260
|
+
const match = String(phase).match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
|
|
251
261
|
if (!match) return phase;
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
return
|
|
262
|
+
const padded = match[1].padStart(2, '0');
|
|
263
|
+
const letter = match[2] ? match[2].toUpperCase() : '';
|
|
264
|
+
const decimal = match[3] || '';
|
|
265
|
+
return padded + letter + decimal;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function escapeRegex(value) {
|
|
269
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function comparePhaseNum(a, b) {
|
|
273
|
+
const pa = String(a).match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
|
|
274
|
+
const pb = String(b).match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
|
|
275
|
+
if (!pa || !pb) return String(a).localeCompare(String(b));
|
|
276
|
+
|
|
277
|
+
const intDiff = parseInt(pa[1], 10) - parseInt(pb[1], 10);
|
|
278
|
+
if (intDiff !== 0) return intDiff;
|
|
279
|
+
|
|
280
|
+
const la = (pa[2] || '').toUpperCase();
|
|
281
|
+
const lb = (pb[2] || '').toUpperCase();
|
|
282
|
+
if (la !== lb) {
|
|
283
|
+
if (!la) return -1;
|
|
284
|
+
if (!lb) return 1;
|
|
285
|
+
return la < lb ? -1 : 1;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const aDecParts = pa[3] ? pa[3].slice(1).split('.').map(p => parseInt(p, 10)) : [];
|
|
289
|
+
const bDecParts = pb[3] ? pb[3].slice(1).split('.').map(p => parseInt(p, 10)) : [];
|
|
290
|
+
const maxLen = Math.max(aDecParts.length, bDecParts.length);
|
|
291
|
+
|
|
292
|
+
if (aDecParts.length === 0 && bDecParts.length > 0) return -1;
|
|
293
|
+
if (bDecParts.length === 0 && aDecParts.length > 0) return 1;
|
|
294
|
+
|
|
295
|
+
for (let i = 0; i < maxLen; i++) {
|
|
296
|
+
const av = Number.isFinite(aDecParts[i]) ? aDecParts[i] : 0;
|
|
297
|
+
const bv = Number.isFinite(bDecParts[i]) ? bDecParts[i] : 0;
|
|
298
|
+
if (av !== bv) return av - bv;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function getMilestonePhaseFilter(cwd) {
|
|
305
|
+
const milestonePhaseNums = new Set();
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
const roadmap = fs.readFileSync(path.join(cwd, '.planning', 'ROADMAP.md'), 'utf-8');
|
|
309
|
+
const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
|
|
310
|
+
let m;
|
|
311
|
+
while ((m = phasePattern.exec(roadmap)) !== null) {
|
|
312
|
+
milestonePhaseNums.add(m[1]);
|
|
313
|
+
}
|
|
314
|
+
} catch {}
|
|
315
|
+
|
|
316
|
+
if (milestonePhaseNums.size === 0) {
|
|
317
|
+
const passAll = () => true;
|
|
318
|
+
passAll.phaseCount = 0;
|
|
319
|
+
return passAll;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const normalized = new Set(
|
|
323
|
+
[...milestonePhaseNums].map(n => (n.replace(/^0+/, '') || '0').toLowerCase())
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
function isDirInMilestone(dirName) {
|
|
327
|
+
const m = dirName.match(/^0*(\d+[A-Za-z]?(?:\.\d+)*)/);
|
|
328
|
+
if (!m) return false;
|
|
329
|
+
return normalized.has(m[1].toLowerCase());
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
isDirInMilestone.phaseCount = milestonePhaseNums.size;
|
|
333
|
+
return isDirInMilestone;
|
|
256
334
|
}
|
|
257
335
|
|
|
258
336
|
function extractFrontmatter(content) {
|
|
@@ -859,12 +937,8 @@ function cmdPhasesList(cwd, options, raw) {
|
|
|
859
937
|
}
|
|
860
938
|
}
|
|
861
939
|
|
|
862
|
-
// Sort
|
|
863
|
-
dirs.sort((a, b) =>
|
|
864
|
-
const aNum = parseFloat(a.match(/^(\d+(?:\.\d+)?)/)?.[1] || '0');
|
|
865
|
-
const bNum = parseFloat(b.match(/^(\d+(?:\.\d+)?)/)?.[1] || '0');
|
|
866
|
-
return aNum - bNum;
|
|
867
|
-
});
|
|
940
|
+
// Sort by canonical phase ordering (integers, decimals, letter suffixes)
|
|
941
|
+
dirs.sort((a, b) => comparePhaseNum(a, b));
|
|
868
942
|
|
|
869
943
|
// If filtering by phase number
|
|
870
944
|
if (phase) {
|
|
@@ -899,7 +973,7 @@ function cmdPhasesList(cwd, options, raw) {
|
|
|
899
973
|
const result = {
|
|
900
974
|
files,
|
|
901
975
|
count: files.length,
|
|
902
|
-
phase_dir: phase ? dirs[0].replace(/^\d+(?:\.\d+)
|
|
976
|
+
phase_dir: phase ? dirs[0].replace(/^\d+[A-Za-z]?(?:\.\d+)*-?/, '') : null,
|
|
903
977
|
};
|
|
904
978
|
output(result, raw, files.join('\n'));
|
|
905
979
|
return;
|
|
@@ -1863,7 +1937,7 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
1863
1937
|
let phaseDirName = null;
|
|
1864
1938
|
try {
|
|
1865
1939
|
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
1866
|
-
const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort();
|
|
1940
|
+
const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort((a, b) => comparePhaseNum(a, b));
|
|
1867
1941
|
const match = dirs.find(d => d.startsWith(normalized));
|
|
1868
1942
|
if (match) {
|
|
1869
1943
|
phaseDir = path.join(phasesDir, match);
|
|
@@ -1899,9 +1973,10 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
1899
1973
|
const content = fs.readFileSync(planPath, 'utf-8');
|
|
1900
1974
|
const fm = extractFrontmatter(content);
|
|
1901
1975
|
|
|
1902
|
-
// Count tasks
|
|
1903
|
-
const
|
|
1904
|
-
const
|
|
1976
|
+
// Count tasks from canonical XML first, fallback to markdown task headings.
|
|
1977
|
+
const xmlTaskMatches = content.match(/<task\b[^>]*>/gi) || [];
|
|
1978
|
+
const markdownTaskMatches = content.match(/##\s*Task\s*\d+/gi) || [];
|
|
1979
|
+
const taskCount = xmlTaskMatches.length > 0 ? xmlTaskMatches.length : markdownTaskMatches.length;
|
|
1905
1980
|
|
|
1906
1981
|
// Parse wave as integer
|
|
1907
1982
|
const wave = parseInt(fm.wave, 10) || 1;
|
|
@@ -1916,10 +1991,24 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
1916
1991
|
hasCheckpoints = true;
|
|
1917
1992
|
}
|
|
1918
1993
|
|
|
1919
|
-
// Parse files-modified
|
|
1994
|
+
// Parse files-modified/files_modified (both accepted).
|
|
1920
1995
|
let filesModified = [];
|
|
1921
|
-
|
|
1922
|
-
|
|
1996
|
+
const filesModifiedField = fm.files_modified ?? fm['files-modified'];
|
|
1997
|
+
if (filesModifiedField) {
|
|
1998
|
+
filesModified = Array.isArray(filesModifiedField) ? filesModifiedField : [filesModifiedField];
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// Objective: canonical <objective> block first line overrides frontmatter objective.
|
|
2002
|
+
let objective = fm.objective || null;
|
|
2003
|
+
const objectiveTagMatch = content.match(/<objective>\s*([\s\S]*?)<\/objective>/i);
|
|
2004
|
+
if (objectiveTagMatch) {
|
|
2005
|
+
const firstLine = objectiveTagMatch[1]
|
|
2006
|
+
.split('\n')
|
|
2007
|
+
.map(line => line.trim())
|
|
2008
|
+
.find(Boolean);
|
|
2009
|
+
if (firstLine) {
|
|
2010
|
+
objective = firstLine;
|
|
2011
|
+
}
|
|
1923
2012
|
}
|
|
1924
2013
|
|
|
1925
2014
|
const hasSummary = completedPlanIds.has(planId);
|
|
@@ -1931,7 +2020,7 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
1931
2020
|
id: planId,
|
|
1932
2021
|
wave,
|
|
1933
2022
|
autonomous,
|
|
1934
|
-
objective
|
|
2023
|
+
objective,
|
|
1935
2024
|
files_modified: filesModified,
|
|
1936
2025
|
task_count: taskCount,
|
|
1937
2026
|
has_summary: hasSummary,
|
|
@@ -3158,16 +3247,16 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
3158
3247
|
// Update ROADMAP.md: mark phase complete
|
|
3159
3248
|
if (fs.existsSync(roadmapPath)) {
|
|
3160
3249
|
let roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
|
|
3250
|
+
const phaseEscaped = escapeRegex(phaseNum);
|
|
3161
3251
|
|
|
3162
3252
|
// Checkbox: - [ ] Phase N: → - [x] Phase N: (...completed DATE)
|
|
3163
3253
|
const checkboxPattern = new RegExp(
|
|
3164
|
-
`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${
|
|
3254
|
+
`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${phaseEscaped}[:\\s][^\\n]*)`,
|
|
3165
3255
|
'i'
|
|
3166
3256
|
);
|
|
3167
3257
|
roadmapContent = roadmapContent.replace(checkboxPattern, `$1x$2 (completed ${today})`);
|
|
3168
3258
|
|
|
3169
3259
|
// Progress table: update Status to Complete, add date
|
|
3170
|
-
const phaseEscaped = phaseNum.replace('.', '\\.');
|
|
3171
3260
|
const tablePattern = new RegExp(
|
|
3172
3261
|
`(\\|\\s*${phaseEscaped}\\.?\\s[^|]*\\|[^|]*\\|)\\s*[^|]*(\\|)\\s*[^|]*(\\|)`,
|
|
3173
3262
|
'i'
|
|
@@ -3192,24 +3281,26 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
3192
3281
|
// Update REQUIREMENTS.md traceability for this phase's requirements
|
|
3193
3282
|
const reqPath = path.join(cwd, '.planning', 'REQUIREMENTS.md');
|
|
3194
3283
|
if (fs.existsSync(reqPath)) {
|
|
3195
|
-
// Extract
|
|
3196
|
-
const
|
|
3197
|
-
new RegExp(
|
|
3284
|
+
// Extract only this phase's section to avoid leaking into later phases.
|
|
3285
|
+
const sectionMatch = roadmapContent.match(
|
|
3286
|
+
new RegExp(`#{2,4}\\s*Phase\\s+${phaseEscaped}\\s*:[\\s\\S]*?(?=\\n#{2,4}\\s*Phase\\s+\\d|$)`, 'i')
|
|
3198
3287
|
);
|
|
3199
3288
|
|
|
3200
|
-
if (
|
|
3201
|
-
const
|
|
3289
|
+
if (sectionMatch) {
|
|
3290
|
+
const reqMatch = sectionMatch[0].match(/\*\*Requirements:\*\*\s*([^\n]+)/i);
|
|
3291
|
+
const reqIds = reqMatch ? (reqMatch[1].match(/\b[A-Z][A-Z0-9_-]*-\d+\b/g) || []) : [];
|
|
3202
3292
|
let reqContent = fs.readFileSync(reqPath, 'utf-8');
|
|
3203
3293
|
|
|
3204
3294
|
for (const reqId of reqIds) {
|
|
3295
|
+
const escapedReqId = escapeRegex(reqId);
|
|
3205
3296
|
// Update checkbox: - [ ] **REQ-ID** → - [x] **REQ-ID**
|
|
3206
3297
|
reqContent = reqContent.replace(
|
|
3207
|
-
new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${
|
|
3298
|
+
new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${escapedReqId}\\*\\*)`, 'gi'),
|
|
3208
3299
|
'$1x$2'
|
|
3209
3300
|
);
|
|
3210
3301
|
// Update traceability table: | REQ-ID | Phase N | Pending | → | REQ-ID | Phase N | Complete |
|
|
3211
3302
|
reqContent = reqContent.replace(
|
|
3212
|
-
new RegExp(`(\\|\\s*${
|
|
3303
|
+
new RegExp(`(\\|\\s*${escapedReqId}\\s*\\|[^|]+\\|)\\s*Pending\\s*(\\|)`, 'gi'),
|
|
3213
3304
|
'$1 Complete $2'
|
|
3214
3305
|
);
|
|
3215
3306
|
}
|
|
@@ -3225,16 +3316,20 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
3225
3316
|
let isLastPhase = true;
|
|
3226
3317
|
|
|
3227
3318
|
try {
|
|
3319
|
+
const isMilestonePhase = getMilestonePhaseFilter(cwd);
|
|
3228
3320
|
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
3229
|
-
const dirs = entries
|
|
3230
|
-
|
|
3321
|
+
const dirs = entries
|
|
3322
|
+
.filter(e => e.isDirectory())
|
|
3323
|
+
.map(e => e.name)
|
|
3324
|
+
.filter(d => isMilestonePhase(d))
|
|
3325
|
+
.sort((a, b) => comparePhaseNum(a, b));
|
|
3326
|
+
const currentPhase = normalizePhaseName(phaseNum);
|
|
3231
3327
|
|
|
3232
3328
|
// Find the next phase directory after current
|
|
3233
3329
|
for (const dir of dirs) {
|
|
3234
|
-
const dm = dir.match(/^(\d+(?:\.\d+)
|
|
3330
|
+
const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i);
|
|
3235
3331
|
if (dm) {
|
|
3236
|
-
|
|
3237
|
-
if (dirFloat > currentFloat) {
|
|
3332
|
+
if (comparePhaseNum(dm[1], currentPhase) > 0) {
|
|
3238
3333
|
nextPhaseNum = dm[1];
|
|
3239
3334
|
nextPhaseName = dm[2] || null;
|
|
3240
3335
|
isLastPhase = false;
|
|
@@ -3328,10 +3423,15 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
|
|
|
3328
3423
|
let totalPlans = 0;
|
|
3329
3424
|
let totalTasks = 0;
|
|
3330
3425
|
const accomplishments = [];
|
|
3426
|
+
const isMilestonePhase = getMilestonePhaseFilter(cwd);
|
|
3331
3427
|
|
|
3332
3428
|
try {
|
|
3333
3429
|
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
3334
|
-
const dirs = entries
|
|
3430
|
+
const dirs = entries
|
|
3431
|
+
.filter(e => e.isDirectory())
|
|
3432
|
+
.map(e => e.name)
|
|
3433
|
+
.filter(d => isMilestonePhase(d))
|
|
3434
|
+
.sort((a, b) => comparePhaseNum(a, b));
|
|
3335
3435
|
|
|
3336
3436
|
for (const dir of dirs) {
|
|
3337
3437
|
phaseCount++;
|
|
@@ -3375,13 +3475,16 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
|
|
|
3375
3475
|
fs.renameSync(auditFile, path.join(archiveDir, `${version}-MILESTONE-AUDIT.md`));
|
|
3376
3476
|
}
|
|
3377
3477
|
|
|
3378
|
-
// Create/
|
|
3478
|
+
// Create/prepend MILESTONES.md entry (reverse chronological order)
|
|
3379
3479
|
const accomplishmentsList = accomplishments.map(a => `- ${a}`).join('\n');
|
|
3380
3480
|
const milestoneEntry = `## ${version} ${milestoneName} (Shipped: ${today})\n\n**Phases completed:** ${phaseCount} phases, ${totalPlans} plans, ${totalTasks} tasks\n\n**Key accomplishments:**\n${accomplishmentsList || '- (none recorded)'}\n\n---\n\n`;
|
|
3381
3481
|
|
|
3382
3482
|
if (fs.existsSync(milestonesPath)) {
|
|
3383
3483
|
const existing = fs.readFileSync(milestonesPath, 'utf-8');
|
|
3384
|
-
|
|
3484
|
+
const existingBody = existing
|
|
3485
|
+
.replace(/^#\s*Milestones[^\n]*\n*/i, '')
|
|
3486
|
+
.trimStart();
|
|
3487
|
+
fs.writeFileSync(milestonesPath, `# Milestones\n\n${milestoneEntry}${existingBody}`, 'utf-8');
|
|
3385
3488
|
} else {
|
|
3386
3489
|
fs.writeFileSync(milestonesPath, `# Milestones\n\n${milestoneEntry}`, 'utf-8');
|
|
3387
3490
|
}
|
|
@@ -3412,7 +3515,11 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
|
|
|
3412
3515
|
fs.mkdirSync(phaseArchiveDir, { recursive: true });
|
|
3413
3516
|
|
|
3414
3517
|
const phaseEntries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
3415
|
-
const phaseDirNames = phaseEntries
|
|
3518
|
+
const phaseDirNames = phaseEntries
|
|
3519
|
+
.filter(e => e.isDirectory())
|
|
3520
|
+
.map(e => e.name)
|
|
3521
|
+
.filter(d => isMilestonePhase(d))
|
|
3522
|
+
.sort((a, b) => comparePhaseNum(a, b));
|
|
3416
3523
|
for (const dir of phaseDirNames) {
|
|
3417
3524
|
fs.renameSync(path.join(phasesDir, dir), path.join(phaseArchiveDir, dir));
|
|
3418
3525
|
}
|
|
@@ -3977,15 +4084,15 @@ function resolveModelInternal(cwd, agentType) {
|
|
|
3977
4084
|
if (override) {
|
|
3978
4085
|
// Override can be a string (legacy) or { m, t } object
|
|
3979
4086
|
if (typeof override === 'string') {
|
|
3980
|
-
return { model: 'inherit', thinking: override === 'high' || override === 'medium' || override === 'low' ? override : '
|
|
4087
|
+
return { model: 'inherit', thinking: override === 'xhigh' || override === 'high' || override === 'medium' || override === 'low' ? override : 'high' };
|
|
3981
4088
|
}
|
|
3982
|
-
return { model: 'inherit', thinking: override.t || '
|
|
4089
|
+
return { model: 'inherit', thinking: override.t || 'high' };
|
|
3983
4090
|
}
|
|
3984
4091
|
|
|
3985
4092
|
// Fall back to profile lookup
|
|
3986
4093
|
const profile = config.model_profile || 'balanced';
|
|
3987
4094
|
const agentModels = MODEL_PROFILES[agentType];
|
|
3988
|
-
if (!agentModels) return { model: 'inherit', thinking: '
|
|
4095
|
+
if (!agentModels) return { model: 'inherit', thinking: 'high' };
|
|
3989
4096
|
const entry = agentModels[profile] || agentModels['balanced'] || DEFAULT_ENTRY;
|
|
3990
4097
|
return { model: 'inherit', thinking: entry.t };
|
|
3991
4098
|
}
|
|
@@ -4844,12 +4951,54 @@ function cmdInitProgress(cwd, includes, raw) {
|
|
|
4844
4951
|
|
|
4845
4952
|
async function main() {
|
|
4846
4953
|
const args = process.argv.slice(2);
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4954
|
+
let raw = false;
|
|
4955
|
+
let cwd = process.cwd();
|
|
4956
|
+
|
|
4957
|
+
const setCwd = (value) => {
|
|
4958
|
+
if (!value) {
|
|
4959
|
+
error('Missing value for --cwd');
|
|
4960
|
+
}
|
|
4961
|
+
const resolved = path.resolve(process.cwd(), value);
|
|
4962
|
+
try {
|
|
4963
|
+
const stat = fs.statSync(resolved);
|
|
4964
|
+
if (!stat.isDirectory()) {
|
|
4965
|
+
throw new Error('not-a-dir');
|
|
4966
|
+
}
|
|
4967
|
+
} catch {
|
|
4968
|
+
error(`Invalid --cwd: ${value}`);
|
|
4969
|
+
}
|
|
4970
|
+
cwd = resolved;
|
|
4971
|
+
};
|
|
4972
|
+
|
|
4973
|
+
for (let i = 0; i < args.length;) {
|
|
4974
|
+
const arg = args[i];
|
|
4975
|
+
if (arg === '--raw') {
|
|
4976
|
+
raw = true;
|
|
4977
|
+
args.splice(i, 1);
|
|
4978
|
+
continue;
|
|
4979
|
+
}
|
|
4980
|
+
if (arg === '--cwd') {
|
|
4981
|
+
const value = args[i + 1];
|
|
4982
|
+
if (!value || value.startsWith('--')) {
|
|
4983
|
+
error('Missing value for --cwd');
|
|
4984
|
+
}
|
|
4985
|
+
setCwd(value);
|
|
4986
|
+
args.splice(i, 2);
|
|
4987
|
+
continue;
|
|
4988
|
+
}
|
|
4989
|
+
if (arg.startsWith('--cwd=')) {
|
|
4990
|
+
const value = arg.slice('--cwd='.length);
|
|
4991
|
+
if (!value) {
|
|
4992
|
+
error('Missing value for --cwd');
|
|
4993
|
+
}
|
|
4994
|
+
setCwd(value);
|
|
4995
|
+
args.splice(i, 1);
|
|
4996
|
+
continue;
|
|
4997
|
+
}
|
|
4998
|
+
i++;
|
|
4999
|
+
}
|
|
4850
5000
|
|
|
4851
5001
|
const command = args[0];
|
|
4852
|
-
const cwd = process.cwd();
|
|
4853
5002
|
|
|
4854
5003
|
if (!command) {
|
|
4855
5004
|
error('Usage: gsd-tools <command> [args] [--raw]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, init');
|
|
@@ -4859,9 +5008,9 @@ async function main() {
|
|
|
4859
5008
|
case 'state': {
|
|
4860
5009
|
const subcommand = args[1];
|
|
4861
5010
|
if (subcommand === 'update') {
|
|
4862
|
-
cmdStateUpdate(cwd, args[2], args[3]);
|
|
5011
|
+
stateLib.cmdStateUpdate(cwd, args[2], args[3]);
|
|
4863
5012
|
} else if (subcommand === 'get') {
|
|
4864
|
-
cmdStateGet(cwd, args[2], raw);
|
|
5013
|
+
stateLib.cmdStateGet(cwd, args[2], raw);
|
|
4865
5014
|
} else if (subcommand === 'patch') {
|
|
4866
5015
|
const patches = {};
|
|
4867
5016
|
for (let i = 2; i < args.length; i += 2) {
|
|
@@ -4871,16 +5020,18 @@ async function main() {
|
|
|
4871
5020
|
patches[key] = value;
|
|
4872
5021
|
}
|
|
4873
5022
|
}
|
|
4874
|
-
cmdStatePatch(cwd, patches, raw);
|
|
5023
|
+
stateLib.cmdStatePatch(cwd, patches, raw);
|
|
5024
|
+
} else if (subcommand === 'json') {
|
|
5025
|
+
stateLib.cmdStateJson(cwd, raw);
|
|
4875
5026
|
} else if (subcommand === 'advance-plan') {
|
|
4876
|
-
cmdStateAdvancePlan(cwd, raw);
|
|
5027
|
+
stateLib.cmdStateAdvancePlan(cwd, raw);
|
|
4877
5028
|
} else if (subcommand === 'record-metric') {
|
|
4878
5029
|
const phaseIdx = args.indexOf('--phase');
|
|
4879
5030
|
const planIdx = args.indexOf('--plan');
|
|
4880
5031
|
const durationIdx = args.indexOf('--duration');
|
|
4881
5032
|
const tasksIdx = args.indexOf('--tasks');
|
|
4882
5033
|
const filesIdx = args.indexOf('--files');
|
|
4883
|
-
cmdStateRecordMetric(cwd, {
|
|
5034
|
+
stateLib.cmdStateRecordMetric(cwd, {
|
|
4884
5035
|
phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
|
|
4885
5036
|
plan: planIdx !== -1 ? args[planIdx + 1] : null,
|
|
4886
5037
|
duration: durationIdx !== -1 ? args[durationIdx + 1] : null,
|
|
@@ -4888,42 +5039,50 @@ async function main() {
|
|
|
4888
5039
|
files: filesIdx !== -1 ? args[filesIdx + 1] : null,
|
|
4889
5040
|
}, raw);
|
|
4890
5041
|
} else if (subcommand === 'update-progress') {
|
|
4891
|
-
cmdStateUpdateProgress(cwd, raw);
|
|
5042
|
+
stateLib.cmdStateUpdateProgress(cwd, raw);
|
|
4892
5043
|
} else if (subcommand === 'add-decision') {
|
|
4893
5044
|
const phaseIdx = args.indexOf('--phase');
|
|
4894
5045
|
const summaryIdx = args.indexOf('--summary');
|
|
5046
|
+
const summaryFileIdx = args.indexOf('--summary-file');
|
|
4895
5047
|
const rationaleIdx = args.indexOf('--rationale');
|
|
4896
|
-
|
|
5048
|
+
const rationaleFileIdx = args.indexOf('--rationale-file');
|
|
5049
|
+
stateLib.cmdStateAddDecision(cwd, {
|
|
4897
5050
|
phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
|
|
4898
5051
|
summary: summaryIdx !== -1 ? args[summaryIdx + 1] : null,
|
|
5052
|
+
summary_file: summaryFileIdx !== -1 ? args[summaryFileIdx + 1] : null,
|
|
4899
5053
|
rationale: rationaleIdx !== -1 ? args[rationaleIdx + 1] : '',
|
|
5054
|
+
rationale_file: rationaleFileIdx !== -1 ? args[rationaleFileIdx + 1] : null,
|
|
4900
5055
|
}, raw);
|
|
4901
5056
|
} else if (subcommand === 'add-blocker') {
|
|
4902
5057
|
const textIdx = args.indexOf('--text');
|
|
4903
|
-
|
|
5058
|
+
const textFileIdx = args.indexOf('--text-file');
|
|
5059
|
+
stateLib.cmdStateAddBlocker(cwd, {
|
|
5060
|
+
text: textIdx !== -1 ? args[textIdx + 1] : null,
|
|
5061
|
+
text_file: textFileIdx !== -1 ? args[textFileIdx + 1] : null,
|
|
5062
|
+
}, raw);
|
|
4904
5063
|
} else if (subcommand === 'resolve-blocker') {
|
|
4905
5064
|
const textIdx = args.indexOf('--text');
|
|
4906
|
-
cmdStateResolveBlocker(cwd, textIdx !== -1 ? args[textIdx + 1] : null, raw);
|
|
5065
|
+
stateLib.cmdStateResolveBlocker(cwd, textIdx !== -1 ? args[textIdx + 1] : null, raw);
|
|
4907
5066
|
} else if (subcommand === 'record-session') {
|
|
4908
5067
|
const stoppedIdx = args.indexOf('--stopped-at');
|
|
4909
5068
|
const resumeIdx = args.indexOf('--resume-file');
|
|
4910
|
-
cmdStateRecordSession(cwd, {
|
|
5069
|
+
stateLib.cmdStateRecordSession(cwd, {
|
|
4911
5070
|
stopped_at: stoppedIdx !== -1 ? args[stoppedIdx + 1] : null,
|
|
4912
5071
|
resume_file: resumeIdx !== -1 ? args[resumeIdx + 1] : 'None',
|
|
4913
5072
|
}, raw);
|
|
4914
5073
|
} else {
|
|
4915
|
-
cmdStateLoad(cwd, raw);
|
|
5074
|
+
stateLib.cmdStateLoad(cwd, raw);
|
|
4916
5075
|
}
|
|
4917
5076
|
break;
|
|
4918
5077
|
}
|
|
4919
5078
|
|
|
4920
5079
|
case 'resolve-model': {
|
|
4921
|
-
cmdResolveModel(cwd, args[1], raw);
|
|
5080
|
+
commandsLib.cmdResolveModel(cwd, args[1], raw);
|
|
4922
5081
|
break;
|
|
4923
5082
|
}
|
|
4924
5083
|
|
|
4925
5084
|
case 'find-phase': {
|
|
4926
|
-
cmdFindPhase(cwd, args[1], raw);
|
|
5085
|
+
phaseLib.cmdFindPhase(cwd, args[1], raw);
|
|
4927
5086
|
break;
|
|
4928
5087
|
}
|
|
4929
5088
|
|
|
@@ -4933,7 +5092,7 @@ async function main() {
|
|
|
4933
5092
|
// Parse --files flag (collect args after --files, stopping at other flags)
|
|
4934
5093
|
const filesIndex = args.indexOf('--files');
|
|
4935
5094
|
const files = filesIndex !== -1 ? args.slice(filesIndex + 1).filter(a => !a.startsWith('--')) : [];
|
|
4936
|
-
cmdCommit(cwd, message, files, raw, amend);
|
|
5095
|
+
commandsLib.cmdCommit(cwd, message, files, raw, amend);
|
|
4937
5096
|
break;
|
|
4938
5097
|
}
|
|
4939
5098
|
|
|
@@ -4941,14 +5100,14 @@ async function main() {
|
|
|
4941
5100
|
const summaryPath = args[1];
|
|
4942
5101
|
const countIndex = args.indexOf('--check-count');
|
|
4943
5102
|
const checkCount = countIndex !== -1 ? parseInt(args[countIndex + 1], 10) : 2;
|
|
4944
|
-
cmdVerifySummary(cwd, summaryPath, checkCount, raw);
|
|
5103
|
+
verifyLib.cmdVerifySummary(cwd, summaryPath, checkCount, raw);
|
|
4945
5104
|
break;
|
|
4946
5105
|
}
|
|
4947
5106
|
|
|
4948
5107
|
case 'template': {
|
|
4949
5108
|
const subcommand = args[1];
|
|
4950
5109
|
if (subcommand === 'select') {
|
|
4951
|
-
cmdTemplateSelect(cwd, args[2], raw);
|
|
5110
|
+
templateLib.cmdTemplateSelect(cwd, args[2], raw);
|
|
4952
5111
|
} else if (subcommand === 'fill') {
|
|
4953
5112
|
const templateType = args[2];
|
|
4954
5113
|
const phaseIdx = args.indexOf('--phase');
|
|
@@ -4957,7 +5116,7 @@ async function main() {
|
|
|
4957
5116
|
const typeIdx = args.indexOf('--type');
|
|
4958
5117
|
const waveIdx = args.indexOf('--wave');
|
|
4959
5118
|
const fieldsIdx = args.indexOf('--fields');
|
|
4960
|
-
cmdTemplateFill(cwd, templateType, {
|
|
5119
|
+
templateLib.cmdTemplateFill(cwd, templateType, {
|
|
4961
5120
|
phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
|
|
4962
5121
|
plan: planIdx !== -1 ? args[planIdx + 1] : null,
|
|
4963
5122
|
name: nameIdx !== -1 ? args[nameIdx + 1] : null,
|
|
@@ -4976,17 +5135,17 @@ async function main() {
|
|
|
4976
5135
|
const file = args[2];
|
|
4977
5136
|
if (subcommand === 'get') {
|
|
4978
5137
|
const fieldIdx = args.indexOf('--field');
|
|
4979
|
-
cmdFrontmatterGet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, raw);
|
|
5138
|
+
frontmatterLib.cmdFrontmatterGet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, raw);
|
|
4980
5139
|
} else if (subcommand === 'set') {
|
|
4981
5140
|
const fieldIdx = args.indexOf('--field');
|
|
4982
5141
|
const valueIdx = args.indexOf('--value');
|
|
4983
|
-
cmdFrontmatterSet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, valueIdx !== -1 ? args[valueIdx + 1] : undefined, raw);
|
|
5142
|
+
frontmatterLib.cmdFrontmatterSet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, valueIdx !== -1 ? args[valueIdx + 1] : undefined, raw);
|
|
4984
5143
|
} else if (subcommand === 'merge') {
|
|
4985
5144
|
const dataIdx = args.indexOf('--data');
|
|
4986
|
-
cmdFrontmatterMerge(cwd, file, dataIdx !== -1 ? args[dataIdx + 1] : null, raw);
|
|
5145
|
+
frontmatterLib.cmdFrontmatterMerge(cwd, file, dataIdx !== -1 ? args[dataIdx + 1] : null, raw);
|
|
4987
5146
|
} else if (subcommand === 'validate') {
|
|
4988
5147
|
const schemaIdx = args.indexOf('--schema');
|
|
4989
|
-
cmdFrontmatterValidate(cwd, file, schemaIdx !== -1 ? args[schemaIdx + 1] : null, raw);
|
|
5148
|
+
frontmatterLib.cmdFrontmatterValidate(cwd, file, schemaIdx !== -1 ? args[schemaIdx + 1] : null, raw);
|
|
4990
5149
|
} else {
|
|
4991
5150
|
error('Unknown frontmatter subcommand. Available: get, set, merge, validate');
|
|
4992
5151
|
}
|
|
@@ -4996,17 +5155,17 @@ async function main() {
|
|
|
4996
5155
|
case 'verify': {
|
|
4997
5156
|
const subcommand = args[1];
|
|
4998
5157
|
if (subcommand === 'plan-structure') {
|
|
4999
|
-
cmdVerifyPlanStructure(cwd, args[2], raw);
|
|
5158
|
+
verifyLib.cmdVerifyPlanStructure(cwd, args[2], raw);
|
|
5000
5159
|
} else if (subcommand === 'phase-completeness') {
|
|
5001
|
-
cmdVerifyPhaseCompleteness(cwd, args[2], raw);
|
|
5160
|
+
verifyLib.cmdVerifyPhaseCompleteness(cwd, args[2], raw);
|
|
5002
5161
|
} else if (subcommand === 'references') {
|
|
5003
|
-
cmdVerifyReferences(cwd, args[2], raw);
|
|
5162
|
+
verifyLib.cmdVerifyReferences(cwd, args[2], raw);
|
|
5004
5163
|
} else if (subcommand === 'commits') {
|
|
5005
|
-
cmdVerifyCommits(cwd, args.slice(2), raw);
|
|
5164
|
+
verifyLib.cmdVerifyCommits(cwd, args.slice(2), raw);
|
|
5006
5165
|
} else if (subcommand === 'artifacts') {
|
|
5007
|
-
cmdVerifyArtifacts(cwd, args[2], raw);
|
|
5166
|
+
verifyLib.cmdVerifyArtifacts(cwd, args[2], raw);
|
|
5008
5167
|
} else if (subcommand === 'key-links') {
|
|
5009
|
-
cmdVerifyKeyLinks(cwd, args[2], raw);
|
|
5168
|
+
verifyLib.cmdVerifyKeyLinks(cwd, args[2], raw);
|
|
5010
5169
|
} else {
|
|
5011
5170
|
error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links');
|
|
5012
5171
|
}
|
|
@@ -5014,42 +5173,42 @@ async function main() {
|
|
|
5014
5173
|
}
|
|
5015
5174
|
|
|
5016
5175
|
case 'generate-slug': {
|
|
5017
|
-
cmdGenerateSlug(args[1], raw);
|
|
5176
|
+
commandsLib.cmdGenerateSlug(args[1], raw);
|
|
5018
5177
|
break;
|
|
5019
5178
|
}
|
|
5020
5179
|
|
|
5021
5180
|
case 'current-timestamp': {
|
|
5022
|
-
cmdCurrentTimestamp(args[1] || 'full', raw);
|
|
5181
|
+
commandsLib.cmdCurrentTimestamp(args[1] || 'full', raw);
|
|
5023
5182
|
break;
|
|
5024
5183
|
}
|
|
5025
5184
|
|
|
5026
5185
|
case 'list-todos': {
|
|
5027
|
-
cmdListTodos(cwd, args[1], raw);
|
|
5186
|
+
commandsLib.cmdListTodos(cwd, args[1], raw);
|
|
5028
5187
|
break;
|
|
5029
5188
|
}
|
|
5030
5189
|
|
|
5031
5190
|
case 'verify-path-exists': {
|
|
5032
|
-
cmdVerifyPathExists(cwd, args[1], raw);
|
|
5191
|
+
commandsLib.cmdVerifyPathExists(cwd, args[1], raw);
|
|
5033
5192
|
break;
|
|
5034
5193
|
}
|
|
5035
5194
|
|
|
5036
5195
|
case 'config-ensure-section': {
|
|
5037
|
-
cmdConfigEnsureSection(cwd, raw);
|
|
5196
|
+
configLib.cmdConfigEnsureSection(cwd, raw);
|
|
5038
5197
|
break;
|
|
5039
5198
|
}
|
|
5040
5199
|
|
|
5041
5200
|
case 'config-set': {
|
|
5042
|
-
cmdConfigSet(cwd, args[1], args[2], raw);
|
|
5201
|
+
configLib.cmdConfigSet(cwd, args[1], args[2], raw);
|
|
5043
5202
|
break;
|
|
5044
5203
|
}
|
|
5045
5204
|
|
|
5046
5205
|
case 'config-get': {
|
|
5047
|
-
cmdConfigGet(cwd, args[1], raw);
|
|
5206
|
+
configLib.cmdConfigGet(cwd, args[1], raw);
|
|
5048
5207
|
break;
|
|
5049
5208
|
}
|
|
5050
5209
|
|
|
5051
5210
|
case 'history-digest': {
|
|
5052
|
-
cmdHistoryDigest(cwd, raw);
|
|
5211
|
+
commandsLib.cmdHistoryDigest(cwd, raw);
|
|
5053
5212
|
break;
|
|
5054
5213
|
}
|
|
5055
5214
|
|
|
@@ -5063,7 +5222,7 @@ async function main() {
|
|
|
5063
5222
|
phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null,
|
|
5064
5223
|
includeArchived: args.includes('--include-archived'),
|
|
5065
5224
|
};
|
|
5066
|
-
cmdPhasesList(cwd, options, raw);
|
|
5225
|
+
phaseLib.cmdPhasesList(cwd, options, raw);
|
|
5067
5226
|
} else {
|
|
5068
5227
|
error('Unknown phases subcommand. Available: list');
|
|
5069
5228
|
}
|
|
@@ -5073,11 +5232,11 @@ async function main() {
|
|
|
5073
5232
|
case 'roadmap': {
|
|
5074
5233
|
const subcommand = args[1];
|
|
5075
5234
|
if (subcommand === 'get-phase') {
|
|
5076
|
-
cmdRoadmapGetPhase(cwd, args[2], raw);
|
|
5235
|
+
roadmapLib.cmdRoadmapGetPhase(cwd, args[2], raw);
|
|
5077
5236
|
} else if (subcommand === 'analyze') {
|
|
5078
|
-
cmdRoadmapAnalyze(cwd, raw);
|
|
5237
|
+
roadmapLib.cmdRoadmapAnalyze(cwd, raw);
|
|
5079
5238
|
} else if (subcommand === 'update-plan-progress') {
|
|
5080
|
-
cmdRoadmapUpdatePlanProgress(cwd, args[2], raw);
|
|
5239
|
+
roadmapLib.cmdRoadmapUpdatePlanProgress(cwd, args[2], raw);
|
|
5081
5240
|
} else {
|
|
5082
5241
|
error('Unknown roadmap subcommand. Available: get-phase, analyze, update-plan-progress');
|
|
5083
5242
|
}
|
|
@@ -5087,22 +5246,32 @@ async function main() {
|
|
|
5087
5246
|
case 'phase': {
|
|
5088
5247
|
const subcommand = args[1];
|
|
5089
5248
|
if (subcommand === 'next-decimal') {
|
|
5090
|
-
cmdPhaseNextDecimal(cwd, args[2], raw);
|
|
5249
|
+
phaseLib.cmdPhaseNextDecimal(cwd, args[2], raw);
|
|
5091
5250
|
} else if (subcommand === 'add') {
|
|
5092
|
-
cmdPhaseAdd(cwd, args.slice(2).join(' '), raw);
|
|
5251
|
+
phaseLib.cmdPhaseAdd(cwd, args.slice(2).join(' '), raw);
|
|
5093
5252
|
} else if (subcommand === 'insert') {
|
|
5094
|
-
cmdPhaseInsert(cwd, args[2], args.slice(3).join(' '), raw);
|
|
5253
|
+
phaseLib.cmdPhaseInsert(cwd, args[2], args.slice(3).join(' '), raw);
|
|
5095
5254
|
} else if (subcommand === 'remove') {
|
|
5096
5255
|
const forceFlag = args.includes('--force');
|
|
5097
|
-
cmdPhaseRemove(cwd, args[2], { force: forceFlag }, raw);
|
|
5256
|
+
phaseLib.cmdPhaseRemove(cwd, args[2], { force: forceFlag }, raw);
|
|
5098
5257
|
} else if (subcommand === 'complete') {
|
|
5099
|
-
cmdPhaseComplete(cwd, args[2], raw);
|
|
5258
|
+
phaseLib.cmdPhaseComplete(cwd, args[2], raw);
|
|
5100
5259
|
} else {
|
|
5101
5260
|
error('Unknown phase subcommand. Available: next-decimal, add, insert, remove, complete');
|
|
5102
5261
|
}
|
|
5103
5262
|
break;
|
|
5104
5263
|
}
|
|
5105
5264
|
|
|
5265
|
+
case 'requirements': {
|
|
5266
|
+
const subcommand = args[1];
|
|
5267
|
+
if (subcommand === 'mark-complete') {
|
|
5268
|
+
milestoneLib.cmdRequirementsMarkComplete(cwd, args.slice(2), raw);
|
|
5269
|
+
} else {
|
|
5270
|
+
error('Unknown requirements subcommand. Available: mark-complete');
|
|
5271
|
+
}
|
|
5272
|
+
break;
|
|
5273
|
+
}
|
|
5274
|
+
|
|
5106
5275
|
case 'milestone': {
|
|
5107
5276
|
const subcommand = args[1];
|
|
5108
5277
|
if (subcommand === 'complete') {
|
|
@@ -5118,7 +5287,7 @@ async function main() {
|
|
|
5118
5287
|
}
|
|
5119
5288
|
milestoneName = nameArgs.join(' ') || null;
|
|
5120
5289
|
}
|
|
5121
|
-
cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases }, raw);
|
|
5290
|
+
milestoneLib.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases }, raw);
|
|
5122
5291
|
} else {
|
|
5123
5292
|
error('Unknown milestone subcommand. Available: complete');
|
|
5124
5293
|
}
|
|
@@ -5128,10 +5297,10 @@ async function main() {
|
|
|
5128
5297
|
case 'validate': {
|
|
5129
5298
|
const subcommand = args[1];
|
|
5130
5299
|
if (subcommand === 'consistency') {
|
|
5131
|
-
cmdValidateConsistency(cwd, raw);
|
|
5300
|
+
verifyLib.cmdValidateConsistency(cwd, raw);
|
|
5132
5301
|
} else if (subcommand === 'health') {
|
|
5133
5302
|
const repairFlag = args.includes('--repair');
|
|
5134
|
-
cmdValidateHealth(cwd, { repair: repairFlag }, raw);
|
|
5303
|
+
verifyLib.cmdValidateHealth(cwd, { repair: repairFlag }, raw);
|
|
5135
5304
|
} else {
|
|
5136
5305
|
error('Unknown validate subcommand. Available: consistency, health');
|
|
5137
5306
|
}
|
|
@@ -5140,14 +5309,14 @@ async function main() {
|
|
|
5140
5309
|
|
|
5141
5310
|
case 'progress': {
|
|
5142
5311
|
const subcommand = args[1] || 'json';
|
|
5143
|
-
cmdProgressRender(cwd, subcommand, raw);
|
|
5312
|
+
commandsLib.cmdProgressRender(cwd, subcommand, raw);
|
|
5144
5313
|
break;
|
|
5145
5314
|
}
|
|
5146
5315
|
|
|
5147
5316
|
case 'todo': {
|
|
5148
5317
|
const subcommand = args[1];
|
|
5149
5318
|
if (subcommand === 'complete') {
|
|
5150
|
-
cmdTodoComplete(cwd, args[2], raw);
|
|
5319
|
+
commandsLib.cmdTodoComplete(cwd, args[2], raw);
|
|
5151
5320
|
} else {
|
|
5152
5321
|
error('Unknown todo subcommand. Available: complete');
|
|
5153
5322
|
}
|
|
@@ -5162,7 +5331,7 @@ async function main() {
|
|
|
5162
5331
|
phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null,
|
|
5163
5332
|
name: nameIndex !== -1 ? args.slice(nameIndex + 1).join(' ') : null,
|
|
5164
5333
|
};
|
|
5165
|
-
cmdScaffold(cwd, scaffoldType, scaffoldOptions, raw);
|
|
5334
|
+
commandsLib.cmdScaffold(cwd, scaffoldType, scaffoldOptions, raw);
|
|
5166
5335
|
break;
|
|
5167
5336
|
}
|
|
5168
5337
|
|
|
@@ -5171,40 +5340,40 @@ async function main() {
|
|
|
5171
5340
|
const includes = parseIncludeFlag(args);
|
|
5172
5341
|
switch (workflow) {
|
|
5173
5342
|
case 'execute-phase':
|
|
5174
|
-
cmdInitExecutePhase(cwd, args[2],
|
|
5343
|
+
initLib.cmdInitExecutePhase(cwd, args[2], raw);
|
|
5175
5344
|
break;
|
|
5176
5345
|
case 'plan-phase':
|
|
5177
|
-
cmdInitPlanPhase(cwd, args[2],
|
|
5346
|
+
initLib.cmdInitPlanPhase(cwd, args[2], raw);
|
|
5178
5347
|
break;
|
|
5179
5348
|
case 'new-project':
|
|
5180
|
-
cmdInitNewProject(cwd, raw);
|
|
5349
|
+
initLib.cmdInitNewProject(cwd, raw);
|
|
5181
5350
|
break;
|
|
5182
5351
|
case 'new-milestone':
|
|
5183
|
-
cmdInitNewMilestone(cwd, raw);
|
|
5352
|
+
initLib.cmdInitNewMilestone(cwd, raw);
|
|
5184
5353
|
break;
|
|
5185
5354
|
case 'quick':
|
|
5186
|
-
cmdInitQuick(cwd, args.slice(2).join(' '), raw);
|
|
5355
|
+
initLib.cmdInitQuick(cwd, args.slice(2).join(' '), raw);
|
|
5187
5356
|
break;
|
|
5188
5357
|
case 'resume':
|
|
5189
|
-
cmdInitResume(cwd, raw);
|
|
5358
|
+
initLib.cmdInitResume(cwd, raw);
|
|
5190
5359
|
break;
|
|
5191
5360
|
case 'verify-work':
|
|
5192
|
-
cmdInitVerifyWork(cwd, args[2], raw);
|
|
5361
|
+
initLib.cmdInitVerifyWork(cwd, args[2], raw);
|
|
5193
5362
|
break;
|
|
5194
5363
|
case 'phase-op':
|
|
5195
|
-
cmdInitPhaseOp(cwd, args[2], raw);
|
|
5364
|
+
initLib.cmdInitPhaseOp(cwd, args[2], raw);
|
|
5196
5365
|
break;
|
|
5197
5366
|
case 'todos':
|
|
5198
|
-
cmdInitTodos(cwd, args[2], raw);
|
|
5367
|
+
initLib.cmdInitTodos(cwd, args[2], raw);
|
|
5199
5368
|
break;
|
|
5200
5369
|
case 'milestone-op':
|
|
5201
|
-
cmdInitMilestoneOp(cwd, raw);
|
|
5370
|
+
initLib.cmdInitMilestoneOp(cwd, raw);
|
|
5202
5371
|
break;
|
|
5203
5372
|
case 'map-codebase':
|
|
5204
|
-
cmdInitMapCodebase(cwd, raw);
|
|
5373
|
+
initLib.cmdInitMapCodebase(cwd, raw);
|
|
5205
5374
|
break;
|
|
5206
5375
|
case 'progress':
|
|
5207
|
-
cmdInitProgress(cwd, includes, raw);
|
|
5376
|
+
initLib.cmdInitProgress(cwd, includes, raw);
|
|
5208
5377
|
break;
|
|
5209
5378
|
default:
|
|
5210
5379
|
error(`Unknown init workflow: ${workflow}\nAvailable: execute-phase, plan-phase, new-project, new-milestone, quick, resume, verify-work, phase-op, todos, milestone-op, map-codebase, progress`);
|
|
@@ -5213,12 +5382,12 @@ async function main() {
|
|
|
5213
5382
|
}
|
|
5214
5383
|
|
|
5215
5384
|
case 'phase-plan-index': {
|
|
5216
|
-
cmdPhasePlanIndex(cwd, args[1], raw);
|
|
5385
|
+
phaseLib.cmdPhasePlanIndex(cwd, args[1], raw);
|
|
5217
5386
|
break;
|
|
5218
5387
|
}
|
|
5219
5388
|
|
|
5220
5389
|
case 'state-snapshot': {
|
|
5221
|
-
cmdStateSnapshot(cwd, raw);
|
|
5390
|
+
stateLib.cmdStateSnapshot(cwd, raw);
|
|
5222
5391
|
break;
|
|
5223
5392
|
}
|
|
5224
5393
|
|
|
@@ -5226,7 +5395,7 @@ async function main() {
|
|
|
5226
5395
|
const summaryPath = args[1];
|
|
5227
5396
|
const fieldsIndex = args.indexOf('--fields');
|
|
5228
5397
|
const fields = fieldsIndex !== -1 ? args[fieldsIndex + 1].split(',') : null;
|
|
5229
|
-
cmdSummaryExtract(cwd, summaryPath, fields, raw);
|
|
5398
|
+
commandsLib.cmdSummaryExtract(cwd, summaryPath, fields, raw);
|
|
5230
5399
|
break;
|
|
5231
5400
|
}
|
|
5232
5401
|
|
|
@@ -5234,7 +5403,7 @@ async function main() {
|
|
|
5234
5403
|
const query = args[1];
|
|
5235
5404
|
const limitIdx = args.indexOf('--limit');
|
|
5236
5405
|
const freshnessIdx = args.indexOf('--freshness');
|
|
5237
|
-
await cmdWebsearch(query, {
|
|
5406
|
+
await commandsLib.cmdWebsearch(query, {
|
|
5238
5407
|
limit: limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : 10,
|
|
5239
5408
|
freshness: freshnessIdx !== -1 ? args[freshnessIdx + 1] : null,
|
|
5240
5409
|
}, raw);
|