@ahmed118glitch/get-shit-done-codex 1.18.3 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -1
- package/README.md +101 -85
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-roadmapper.md +39 -5
- package/agents/gsd-verifier.md +2 -2
- package/bin/install-codex.js +100 -100
- package/bin/install.js +65 -8
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/reapply-patches.md +3 -3
- package/commands/gsd/verify-work.md +1 -1
- package/get-shit-done/bin/gsd-tools.js +106 -19
- package/get-shit-done/bin/gsd-tools.test.js +44 -0
- package/get-shit-done/references/model-profile-resolution.md +4 -2
- package/get-shit-done/references/model-profiles.md +3 -0
- package/get-shit-done/references/questioning.md +1 -0
- package/get-shit-done/templates/UAT.md +1 -1
- package/get-shit-done/templates/context.md +2 -2
- package/get-shit-done/templates/planner-subagent-prompt.md +4 -4
- package/get-shit-done/templates/research.md +2 -2
- package/get-shit-done/templates/verification-report.md +1 -1
- package/get-shit-done/workflows/diagnose-issues.md +1 -1
- package/get-shit-done/workflows/discovery-phase.md +1 -1
- package/get-shit-done/workflows/discuss-phase.md +3 -3
- package/get-shit-done/workflows/execute-phase.md +51 -2
- package/get-shit-done/workflows/help.md +4 -4
- package/get-shit-done/workflows/new-milestone.md +1 -1
- package/get-shit-done/workflows/new-project.md +3 -3
- package/get-shit-done/workflows/plan-phase.md +1 -1
- package/get-shit-done/workflows/progress.md +2 -2
- package/get-shit-done/workflows/update.md +14 -12
- package/get-shit-done/workflows/verify-work.md +3 -3
- package/package.json +1 -1
|
@@ -835,14 +835,33 @@ function cmdRoadmapGetPhase(cwd, phaseNum, raw) {
|
|
|
835
835
|
// Escape special regex chars in phase number, handle decimal
|
|
836
836
|
const escapedPhase = phaseNum.replace(/\./g, '\\.');
|
|
837
837
|
|
|
838
|
-
// Match "
|
|
838
|
+
// Match "## Phase X:" or "### Phase X:" with optional name
|
|
839
839
|
const phasePattern = new RegExp(
|
|
840
|
-
|
|
840
|
+
`#{2,3}\\s*Phase\\s+${escapedPhase}:\\s*([^\\n]+)`,
|
|
841
841
|
'i'
|
|
842
842
|
);
|
|
843
843
|
const headerMatch = content.match(phasePattern);
|
|
844
844
|
|
|
845
845
|
if (!headerMatch) {
|
|
846
|
+
// Fallback: check if phase exists in summary list but missing detail section
|
|
847
|
+
const checklistPattern = new RegExp(
|
|
848
|
+
`-\\s*\\[[ x]\\]\\s*\\*\\*Phase\\s+${escapedPhase}:\\s*([^*]+)\\*\\*`,
|
|
849
|
+
'i'
|
|
850
|
+
);
|
|
851
|
+
const checklistMatch = content.match(checklistPattern);
|
|
852
|
+
|
|
853
|
+
if (checklistMatch) {
|
|
854
|
+
// Phase exists in summary but missing detail section - malformed ROADMAP
|
|
855
|
+
output({
|
|
856
|
+
found: false,
|
|
857
|
+
phase_number: phaseNum,
|
|
858
|
+
phase_name: checklistMatch[1].trim(),
|
|
859
|
+
error: 'malformed_roadmap',
|
|
860
|
+
message: `Phase ${phaseNum} exists in summary list but missing "### Phase ${phaseNum}:" detail section. ROADMAP.md needs both formats.`
|
|
861
|
+
}, raw, '');
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
|
|
846
865
|
output({ found: false, phase_number: phaseNum }, raw, '');
|
|
847
866
|
return;
|
|
848
867
|
}
|
|
@@ -850,9 +869,9 @@ function cmdRoadmapGetPhase(cwd, phaseNum, raw) {
|
|
|
850
869
|
const phaseName = headerMatch[1].trim();
|
|
851
870
|
const headerIndex = headerMatch.index;
|
|
852
871
|
|
|
853
|
-
// Find the end of this section (next ### or end of file)
|
|
872
|
+
// Find the end of this section (next ## or ### phase header, or end of file)
|
|
854
873
|
const restOfContent = content.slice(headerIndex);
|
|
855
|
-
const nextHeaderMatch = restOfContent.match(/\n
|
|
874
|
+
const nextHeaderMatch = restOfContent.match(/\n#{2,3}\s+Phase\s+\d/i);
|
|
856
875
|
const sectionEnd = nextHeaderMatch
|
|
857
876
|
? headerIndex + nextHeaderMatch.index
|
|
858
877
|
: content.length;
|
|
@@ -1328,7 +1347,8 @@ function cmdResolveModel(cwd, agentType, raw) {
|
|
|
1328
1347
|
return;
|
|
1329
1348
|
}
|
|
1330
1349
|
|
|
1331
|
-
const
|
|
1350
|
+
const resolved = agentModels[profile] || agentModels['balanced'] || 'sonnet';
|
|
1351
|
+
const model = resolved === 'opus' ? 'inherit' : resolved;
|
|
1332
1352
|
const result = { model, profile };
|
|
1333
1353
|
output(result, raw, model);
|
|
1334
1354
|
}
|
|
@@ -2430,8 +2450,8 @@ function cmdRoadmapAnalyze(cwd, raw) {
|
|
|
2430
2450
|
const content = fs.readFileSync(roadmapPath, 'utf-8');
|
|
2431
2451
|
const phasesDir = path.join(cwd, '.planning', 'phases');
|
|
2432
2452
|
|
|
2433
|
-
// Extract all phase headings: ### Phase N: Name
|
|
2434
|
-
const phasePattern =
|
|
2453
|
+
// Extract all phase headings: ## Phase N: Name or ### Phase N: Name
|
|
2454
|
+
const phasePattern = /#{2,3}\s*Phase\s+(\d+(?:\.\d+)?)\s*:\s*([^\n]+)/gi;
|
|
2435
2455
|
const phases = [];
|
|
2436
2456
|
let match;
|
|
2437
2457
|
|
|
@@ -2442,7 +2462,7 @@ function cmdRoadmapAnalyze(cwd, raw) {
|
|
|
2442
2462
|
// Extract goal from the section
|
|
2443
2463
|
const sectionStart = match.index;
|
|
2444
2464
|
const restOfContent = content.slice(sectionStart);
|
|
2445
|
-
const nextHeader = restOfContent.match(/\n
|
|
2465
|
+
const nextHeader = restOfContent.match(/\n#{2,3}\s+Phase\s+\d/i);
|
|
2446
2466
|
const sectionEnd = nextHeader ? sectionStart + nextHeader.index : content.length;
|
|
2447
2467
|
const section = content.slice(sectionStart, sectionEnd);
|
|
2448
2468
|
|
|
@@ -2520,6 +2540,16 @@ function cmdRoadmapAnalyze(cwd, raw) {
|
|
|
2520
2540
|
const totalSummaries = phases.reduce((sum, p) => sum + p.summary_count, 0);
|
|
2521
2541
|
const completedPhases = phases.filter(p => p.disk_status === 'complete').length;
|
|
2522
2542
|
|
|
2543
|
+
// Detect phases in summary list without detail sections (malformed ROADMAP)
|
|
2544
|
+
const checklistPattern = /-\s*\[[ x]\]\s*\*\*Phase\s+(\d+(?:\.\d+)?)/gi;
|
|
2545
|
+
const checklistPhases = new Set();
|
|
2546
|
+
let checklistMatch;
|
|
2547
|
+
while ((checklistMatch = checklistPattern.exec(content)) !== null) {
|
|
2548
|
+
checklistPhases.add(checklistMatch[1]);
|
|
2549
|
+
}
|
|
2550
|
+
const detailPhases = new Set(phases.map(p => p.number));
|
|
2551
|
+
const missingDetails = [...checklistPhases].filter(p => !detailPhases.has(p));
|
|
2552
|
+
|
|
2523
2553
|
const result = {
|
|
2524
2554
|
milestones,
|
|
2525
2555
|
phases,
|
|
@@ -2530,6 +2560,7 @@ function cmdRoadmapAnalyze(cwd, raw) {
|
|
|
2530
2560
|
progress_percent: totalPlans > 0 ? Math.round((totalSummaries / totalPlans) * 100) : 0,
|
|
2531
2561
|
current_phase: currentPhase ? currentPhase.number : null,
|
|
2532
2562
|
next_phase: nextPhase ? nextPhase.number : null,
|
|
2563
|
+
missing_phase_details: missingDetails.length > 0 ? missingDetails : null,
|
|
2533
2564
|
};
|
|
2534
2565
|
|
|
2535
2566
|
output(result, raw);
|
|
@@ -2551,7 +2582,7 @@ function cmdPhaseAdd(cwd, description, raw) {
|
|
|
2551
2582
|
const slug = generateSlugInternal(description);
|
|
2552
2583
|
|
|
2553
2584
|
// Find highest integer phase number
|
|
2554
|
-
const phasePattern =
|
|
2585
|
+
const phasePattern = /#{2,3}\s*Phase\s+(\d+)(?:\.\d+)?:/gi;
|
|
2555
2586
|
let maxPhase = 0;
|
|
2556
2587
|
let m;
|
|
2557
2588
|
while ((m = phasePattern.exec(content)) !== null) {
|
|
@@ -2609,7 +2640,7 @@ function cmdPhaseInsert(cwd, afterPhase, description, raw) {
|
|
|
2609
2640
|
|
|
2610
2641
|
// Verify target phase exists
|
|
2611
2642
|
const afterPhaseEscaped = afterPhase.replace(/\./g, '\\.');
|
|
2612
|
-
const targetPattern = new RegExp(
|
|
2643
|
+
const targetPattern = new RegExp(`#{2,3}\\s*Phase\\s+${afterPhaseEscaped}:`, 'i');
|
|
2613
2644
|
if (!targetPattern.test(content)) {
|
|
2614
2645
|
error(`Phase ${afterPhase} not found in ROADMAP.md`);
|
|
2615
2646
|
}
|
|
@@ -2641,7 +2672,7 @@ function cmdPhaseInsert(cwd, afterPhase, description, raw) {
|
|
|
2641
2672
|
const phaseEntry = `\n### Phase ${decimalPhase}: ${description} (INSERTED)\n\n**Goal:** [Urgent work - to be planned]\n**Depends on:** Phase ${afterPhase}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run /gsd:plan-phase ${decimalPhase} to break down)\n`;
|
|
2642
2673
|
|
|
2643
2674
|
// Insert after the target phase section
|
|
2644
|
-
const headerPattern = new RegExp(`(
|
|
2675
|
+
const headerPattern = new RegExp(`(#{2,3}\\s*Phase\\s+${afterPhaseEscaped}:[^\\n]*\\n)`, 'i');
|
|
2645
2676
|
const headerMatch = content.match(headerPattern);
|
|
2646
2677
|
if (!headerMatch) {
|
|
2647
2678
|
error(`Could not find Phase ${afterPhase} header`);
|
|
@@ -2649,7 +2680,7 @@ function cmdPhaseInsert(cwd, afterPhase, description, raw) {
|
|
|
2649
2680
|
|
|
2650
2681
|
const headerIdx = content.indexOf(headerMatch[0]);
|
|
2651
2682
|
const afterHeader = content.slice(headerIdx + headerMatch[0].length);
|
|
2652
|
-
const nextPhaseMatch = afterHeader.match(/\n
|
|
2683
|
+
const nextPhaseMatch = afterHeader.match(/\n#{2,3}\s+Phase\s+\d/i);
|
|
2653
2684
|
|
|
2654
2685
|
let insertIdx;
|
|
2655
2686
|
if (nextPhaseMatch) {
|
|
@@ -2832,7 +2863,7 @@ function cmdPhaseRemove(cwd, targetPhase, options, raw) {
|
|
|
2832
2863
|
// Remove the target phase section
|
|
2833
2864
|
const targetEscaped = targetPhase.replace(/\./g, '\\.');
|
|
2834
2865
|
const sectionPattern = new RegExp(
|
|
2835
|
-
`\\n
|
|
2866
|
+
`\\n?#{2,3}\\s*Phase\\s+${targetEscaped}\\s*:[\\s\\S]*?(?=\\n#{2,3}\\s+Phase\\s+\\d|$)`,
|
|
2836
2867
|
'i'
|
|
2837
2868
|
);
|
|
2838
2869
|
roadmapContent = roadmapContent.replace(sectionPattern, '');
|
|
@@ -2858,9 +2889,9 @@ function cmdPhaseRemove(cwd, targetPhase, options, raw) {
|
|
|
2858
2889
|
const oldPad = oldStr.padStart(2, '0');
|
|
2859
2890
|
const newPad = newStr.padStart(2, '0');
|
|
2860
2891
|
|
|
2861
|
-
// Phase headings: ### Phase 18: → ### Phase 17:
|
|
2892
|
+
// Phase headings: ## Phase 18: or ### Phase 18: → ## Phase 17: or ### Phase 17:
|
|
2862
2893
|
roadmapContent = roadmapContent.replace(
|
|
2863
|
-
new RegExp(`(
|
|
2894
|
+
new RegExp(`(#{2,3}\\s*Phase\\s+)${oldStr}(\\s*:)`, 'gi'),
|
|
2864
2895
|
`$1${newStr}$2`
|
|
2865
2896
|
);
|
|
2866
2897
|
|
|
@@ -2971,7 +3002,7 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
|
|
2971
3002
|
|
|
2972
3003
|
// Update plan count in phase section
|
|
2973
3004
|
const planCountPattern = new RegExp(
|
|
2974
|
-
`(
|
|
3005
|
+
`(#{2,3}\\s*Phase\\s+${phaseEscaped}[\\s\\S]*?\\*\\*Plans:\\*\\*\\s*)[^\\n]+`,
|
|
2975
3006
|
'i'
|
|
2976
3007
|
);
|
|
2977
3008
|
roadmapContent = roadmapContent.replace(
|
|
@@ -3206,7 +3237,7 @@ function cmdValidateConsistency(cwd, raw) {
|
|
|
3206
3237
|
|
|
3207
3238
|
// Extract phases from ROADMAP
|
|
3208
3239
|
const roadmapPhases = new Set();
|
|
3209
|
-
const phasePattern =
|
|
3240
|
+
const phasePattern = /#{2,3}\s*Phase\s+(\d+(?:\.\d+)?)\s*:/gi;
|
|
3210
3241
|
let m;
|
|
3211
3242
|
while ((m = phasePattern.exec(roadmapContent)) !== null) {
|
|
3212
3243
|
roadmapPhases.add(m[1]);
|
|
@@ -3479,7 +3510,8 @@ function resolveModelInternal(cwd, agentType) {
|
|
|
3479
3510
|
const profile = config.model_profile || 'balanced';
|
|
3480
3511
|
const agentModels = MODEL_PROFILES[agentType];
|
|
3481
3512
|
if (!agentModels) return 'sonnet';
|
|
3482
|
-
|
|
3513
|
+
const resolved = agentModels[profile] || agentModels['balanced'] || 'sonnet';
|
|
3514
|
+
return resolved === 'opus' ? 'inherit' : resolved;
|
|
3483
3515
|
}
|
|
3484
3516
|
|
|
3485
3517
|
function findPhaseInternal(cwd, phase) {
|
|
@@ -3533,6 +3565,40 @@ function findPhaseInternal(cwd, phase) {
|
|
|
3533
3565
|
}
|
|
3534
3566
|
}
|
|
3535
3567
|
|
|
3568
|
+
function getRoadmapPhaseInternal(cwd, phaseNum) {
|
|
3569
|
+
if (!phaseNum) return null;
|
|
3570
|
+
const roadmapPath = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
3571
|
+
if (!fs.existsSync(roadmapPath)) return null;
|
|
3572
|
+
|
|
3573
|
+
try {
|
|
3574
|
+
const content = fs.readFileSync(roadmapPath, 'utf-8');
|
|
3575
|
+
const escapedPhase = phaseNum.toString().replace(/\./g, '\\.');
|
|
3576
|
+
const phasePattern = new RegExp(`#{2,3}\\s*Phase\\s+${escapedPhase}:\\s*([^\\n]+)`, 'i');
|
|
3577
|
+
const headerMatch = content.match(phasePattern);
|
|
3578
|
+
if (!headerMatch) return null;
|
|
3579
|
+
|
|
3580
|
+
const phaseName = headerMatch[1].trim();
|
|
3581
|
+
const headerIndex = headerMatch.index;
|
|
3582
|
+
const restOfContent = content.slice(headerIndex);
|
|
3583
|
+
const nextHeaderMatch = restOfContent.match(/\n#{2,3}\s+Phase\s+\d/i);
|
|
3584
|
+
const sectionEnd = nextHeaderMatch ? headerIndex + nextHeaderMatch.index : content.length;
|
|
3585
|
+
const section = content.slice(headerIndex, sectionEnd).trim();
|
|
3586
|
+
|
|
3587
|
+
const goalMatch = section.match(/\*\*Goal:\*\*\s*([^\n]+)/i);
|
|
3588
|
+
const goal = goalMatch ? goalMatch[1].trim() : null;
|
|
3589
|
+
|
|
3590
|
+
return {
|
|
3591
|
+
found: true,
|
|
3592
|
+
phase_number: phaseNum.toString(),
|
|
3593
|
+
phase_name: phaseName,
|
|
3594
|
+
goal,
|
|
3595
|
+
section,
|
|
3596
|
+
};
|
|
3597
|
+
} catch {
|
|
3598
|
+
return null;
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3536
3602
|
function pathExistsInternal(cwd, targetPath) {
|
|
3537
3603
|
const fullPath = path.isAbsolute(targetPath) ? targetPath : path.join(cwd, targetPath);
|
|
3538
3604
|
try {
|
|
@@ -3918,7 +3984,28 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
3918
3984
|
|
|
3919
3985
|
function cmdInitPhaseOp(cwd, phase, raw) {
|
|
3920
3986
|
const config = loadConfig(cwd);
|
|
3921
|
-
|
|
3987
|
+
let phaseInfo = findPhaseInternal(cwd, phase);
|
|
3988
|
+
|
|
3989
|
+
// Fallback to ROADMAP.md if no directory exists (e.g., Plans: TBD)
|
|
3990
|
+
if (!phaseInfo) {
|
|
3991
|
+
const roadmapPhase = getRoadmapPhaseInternal(cwd, phase);
|
|
3992
|
+
if (roadmapPhase?.found) {
|
|
3993
|
+
const phaseName = roadmapPhase.phase_name;
|
|
3994
|
+
phaseInfo = {
|
|
3995
|
+
found: true,
|
|
3996
|
+
directory: null,
|
|
3997
|
+
phase_number: roadmapPhase.phase_number,
|
|
3998
|
+
phase_name: phaseName,
|
|
3999
|
+
phase_slug: phaseName ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') : null,
|
|
4000
|
+
plans: [],
|
|
4001
|
+
summaries: [],
|
|
4002
|
+
incomplete_plans: [],
|
|
4003
|
+
has_research: false,
|
|
4004
|
+
has_context: false,
|
|
4005
|
+
has_verification: false,
|
|
4006
|
+
};
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
3922
4009
|
|
|
3923
4010
|
const result = {
|
|
3924
4011
|
// Config
|
|
@@ -520,6 +520,50 @@ This phase covers:
|
|
|
520
520
|
assert.strictEqual(output.found, false, 'should return not found');
|
|
521
521
|
assert.strictEqual(output.error, 'ROADMAP.md not found', 'should explain why');
|
|
522
522
|
});
|
|
523
|
+
|
|
524
|
+
test('accepts ## phase headers (two hashes)', () => {
|
|
525
|
+
fs.writeFileSync(
|
|
526
|
+
path.join(tmpDir, '.planning', 'ROADMAP.md'),
|
|
527
|
+
`# Roadmap v1.0
|
|
528
|
+
|
|
529
|
+
## Phase 1: Foundation
|
|
530
|
+
**Goal:** Set up project infrastructure
|
|
531
|
+
**Plans:** 2 plans
|
|
532
|
+
|
|
533
|
+
## Phase 2: API
|
|
534
|
+
**Goal:** Build REST API
|
|
535
|
+
`
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
const result = runGsdTools('roadmap get-phase 1', tmpDir);
|
|
539
|
+
assert.ok(result.success, `Command failed: ${result.error}`);
|
|
540
|
+
|
|
541
|
+
const output = JSON.parse(result.output);
|
|
542
|
+
assert.strictEqual(output.found, true, 'phase with ## header should be found');
|
|
543
|
+
assert.strictEqual(output.phase_name, 'Foundation', 'phase name extracted');
|
|
544
|
+
assert.strictEqual(output.goal, 'Set up project infrastructure', 'goal extracted');
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
test('detects malformed ROADMAP with summary list but no detail sections', () => {
|
|
548
|
+
fs.writeFileSync(
|
|
549
|
+
path.join(tmpDir, '.planning', 'ROADMAP.md'),
|
|
550
|
+
`# Roadmap v1.0
|
|
551
|
+
|
|
552
|
+
## Phases
|
|
553
|
+
|
|
554
|
+
- [ ] **Phase 1: Foundation** - Set up project
|
|
555
|
+
- [ ] **Phase 2: API** - Build REST API
|
|
556
|
+
`
|
|
557
|
+
);
|
|
558
|
+
|
|
559
|
+
const result = runGsdTools('roadmap get-phase 1', tmpDir);
|
|
560
|
+
assert.ok(result.success, `Command failed: ${result.error}`);
|
|
561
|
+
|
|
562
|
+
const output = JSON.parse(result.output);
|
|
563
|
+
assert.strictEqual(output.found, false, 'phase should not be found');
|
|
564
|
+
assert.strictEqual(output.error, 'malformed_roadmap', 'should identify malformed roadmap');
|
|
565
|
+
assert.ok(output.message.includes('missing'), 'should explain the issue');
|
|
566
|
+
});
|
|
523
567
|
});
|
|
524
568
|
|
|
525
569
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -20,13 +20,15 @@ Look up the agent in the table for the resolved profile. Pass the model paramete
|
|
|
20
20
|
Task(
|
|
21
21
|
prompt="...",
|
|
22
22
|
subagent_type="gsd-planner",
|
|
23
|
-
model="{resolved_model}" #
|
|
23
|
+
model="{resolved_model}" # "inherit", "sonnet", or "haiku"
|
|
24
24
|
)
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
**Note:** Opus-tier agents resolve to `"inherit"` (not `"opus"`). This causes the agent to use the parent session's model, avoiding conflicts with organization policies that may block specific opus versions.
|
|
28
|
+
|
|
27
29
|
## Usage
|
|
28
30
|
|
|
29
31
|
1. Resolve once at orchestration start
|
|
30
32
|
2. Store the profile value
|
|
31
33
|
3. Look up each agent's model from the table when spawning
|
|
32
|
-
4. Pass model parameter to each Task call
|
|
34
|
+
4. Pass model parameter to each Task call (values: `"inherit"`, `"sonnet"`, `"haiku"`)
|
|
@@ -71,3 +71,6 @@ Verification requires goal-backward reasoning - checking if code *delivers* what
|
|
|
71
71
|
|
|
72
72
|
**Why Haiku for gsd-codebase-mapper?**
|
|
73
73
|
Read-only exploration and pattern extraction. No reasoning required, just structured output from file contents.
|
|
74
|
+
|
|
75
|
+
**Why `inherit` instead of passing `opus` directly?**
|
|
76
|
+
Claude Code's `"opus"` alias maps to a specific model version. Organizations may block older opus versions while allowing newer ones. GSD returns `"inherit"` for opus-tier agents, causing them to use whatever opus version the user has configured in their session. This avoids version conflicts and silent fallbacks to Sonnet.
|
|
@@ -79,6 +79,7 @@ Use AskUserQuestion to help users think by presenting concrete options to react
|
|
|
79
79
|
- Generic categories ("Technical", "Business", "Other")
|
|
80
80
|
- Leading options that presume an answer
|
|
81
81
|
- Too many options (2-4 is ideal)
|
|
82
|
+
- Headers longer than 12 characters (hard limit — validation will reject them)
|
|
82
83
|
|
|
83
84
|
**Example — vague answer:**
|
|
84
85
|
User says "it should be fast"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Phase Context Template
|
|
2
2
|
|
|
3
|
-
Template for `.planning/phases/XX-name/{
|
|
3
|
+
Template for `.planning/phases/XX-name/{phase_num}-CONTEXT.md` - captures implementation decisions for a phase.
|
|
4
4
|
|
|
5
5
|
**Purpose:** Document decisions that downstream agents need. Researcher uses this to know WHAT to investigate. Planner uses this to know WHAT choices are locked vs flexible.
|
|
6
6
|
|
|
@@ -276,7 +276,7 @@ The output should answer: "What does the researcher need to investigate? What ch
|
|
|
276
276
|
- "Easy to use"
|
|
277
277
|
|
|
278
278
|
**After creation:**
|
|
279
|
-
- File lives in phase directory: `.planning/phases/XX-name/{
|
|
279
|
+
- File lives in phase directory: `.planning/phases/XX-name/{phase_num}-CONTEXT.md`
|
|
280
280
|
- `gsd-phase-researcher` uses decisions to focus investigation
|
|
281
281
|
- `gsd-planner` uses decisions + research to create executable tasks
|
|
282
282
|
- Downstream agents should NOT need to ask the user again about captured decisions
|
|
@@ -22,14 +22,14 @@ Template for spawning gsd-planner agent. The agent contains all planning experti
|
|
|
22
22
|
@.planning/REQUIREMENTS.md
|
|
23
23
|
|
|
24
24
|
**Phase Context (if exists):**
|
|
25
|
-
@.planning/phases/{phase_dir}/{
|
|
25
|
+
@.planning/phases/{phase_dir}/{phase_num}-CONTEXT.md
|
|
26
26
|
|
|
27
27
|
**Research (if exists):**
|
|
28
|
-
@.planning/phases/{phase_dir}/{
|
|
28
|
+
@.planning/phases/{phase_dir}/{phase_num}-RESEARCH.md
|
|
29
29
|
|
|
30
30
|
**Gap Closure (if --gaps mode):**
|
|
31
|
-
@.planning/phases/{phase_dir}/{
|
|
32
|
-
@.planning/phases/{phase_dir}/{
|
|
31
|
+
@.planning/phases/{phase_dir}/{phase_num}-VERIFICATION.md
|
|
32
|
+
@.planning/phases/{phase_dir}/{phase_num}-UAT.md
|
|
33
33
|
|
|
34
34
|
</planning_context>
|
|
35
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Research Template
|
|
2
2
|
|
|
3
|
-
Template for `.planning/phases/XX-name/{
|
|
3
|
+
Template for `.planning/phases/XX-name/{phase_num}-RESEARCH.md` - comprehensive ecosystem research before planning.
|
|
4
4
|
|
|
5
5
|
**Purpose:** Document what Claude needs to know to implement a phase well - not just "which library" but "how do experts build this."
|
|
6
6
|
|
|
@@ -547,6 +547,6 @@ function useVehicleControls(rigidBodyRef) {
|
|
|
547
547
|
- Code examples can be referenced in task actions
|
|
548
548
|
|
|
549
549
|
**After creation:**
|
|
550
|
-
- File lives in phase directory: `.planning/phases/XX-name/{
|
|
550
|
+
- File lives in phase directory: `.planning/phases/XX-name/{phase_num}-RESEARCH.md`
|
|
551
551
|
- Referenced during planning workflow
|
|
552
552
|
- plan-phase loads it automatically when present
|
|
@@ -158,7 +158,7 @@ Update status in frontmatter to "diagnosed".
|
|
|
158
158
|
|
|
159
159
|
Commit the updated UAT.md:
|
|
160
160
|
```bash
|
|
161
|
-
node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs({
|
|
161
|
+
node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs({phase_num}): add root causes from diagnosis" --files ".planning/phases/XX-name/{phase_num}-UAT.md"
|
|
162
162
|
```
|
|
163
163
|
</step>
|
|
164
164
|
|
|
@@ -216,7 +216,7 @@ After creating DISCOVERY.md, check confidence level.
|
|
|
216
216
|
If confidence is LOW:
|
|
217
217
|
Use AskUserQuestion:
|
|
218
218
|
|
|
219
|
-
- header: "Low
|
|
219
|
+
- header: "Low Conf."
|
|
220
220
|
- question: "Discovery confidence is LOW: [reason]. How would you like to proceed?"
|
|
221
221
|
- options:
|
|
222
222
|
- "Dig deeper" - Do more research before planning
|
|
@@ -136,7 +136,7 @@ ls ${phase_dir}/*-CONTEXT.md 2>/dev/null
|
|
|
136
136
|
|
|
137
137
|
**If exists:**
|
|
138
138
|
Use AskUserQuestion:
|
|
139
|
-
- header: "
|
|
139
|
+
- header: "Context"
|
|
140
140
|
- question: "Phase [X] already has context. What do you want to do?"
|
|
141
141
|
- options:
|
|
142
142
|
- "Update it" — Review and revise existing context
|
|
@@ -240,13 +240,13 @@ Ask 4 questions per area before offering to continue or move on. Each answer oft
|
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
2. **Ask 4 questions using AskUserQuestion:**
|
|
243
|
-
- header: "[Area]"
|
|
243
|
+
- header: "[Area]" (max 12 chars — abbreviate if needed)
|
|
244
244
|
- question: Specific decision for this area
|
|
245
245
|
- options: 2-3 concrete choices (AskUserQuestion adds "Other" automatically)
|
|
246
246
|
- Include "You decide" as an option when reasonable — captures Claude discretion
|
|
247
247
|
|
|
248
248
|
3. **After 4 questions, check:**
|
|
249
|
-
- header: "[Area]"
|
|
249
|
+
- header: "[Area]" (max 12 chars)
|
|
250
250
|
- question: "More questions about [area], or move to next?"
|
|
251
251
|
- options: "More questions" / "Next area"
|
|
252
252
|
|
|
@@ -226,6 +226,55 @@ After all waves:
|
|
|
226
226
|
```
|
|
227
227
|
</step>
|
|
228
228
|
|
|
229
|
+
<step name="close_parent_artifacts">
|
|
230
|
+
**For decimal/polish phases only (X.Y pattern):** Close the feedback loop by resolving parent UAT and debug artifacts.
|
|
231
|
+
|
|
232
|
+
**Skip if** phase number has no decimal (e.g., `3`, `04`) — only applies to gap-closure phases like `4.1`, `03.1`.
|
|
233
|
+
|
|
234
|
+
**1. Detect decimal phase and derive parent:**
|
|
235
|
+
```bash
|
|
236
|
+
# Check if phase_number contains a decimal
|
|
237
|
+
if [[ "$PHASE_NUMBER" == *.* ]]; then
|
|
238
|
+
PARENT_PHASE="${PHASE_NUMBER%%.*}"
|
|
239
|
+
fi
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**2. Find parent UAT file:**
|
|
243
|
+
```bash
|
|
244
|
+
find .planning/phases -path "*${PARENT_PHASE}*/*-UAT.md" -type f 2>/dev/null
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**If no parent UAT found:** Skip this step (gap-closure may have been triggered by VERIFICATION.md instead).
|
|
248
|
+
|
|
249
|
+
**3. Update UAT gap statuses:**
|
|
250
|
+
|
|
251
|
+
Read the parent UAT file's `## Gaps` section. For each gap entry with `status: failed`:
|
|
252
|
+
- Update to `status: resolved`
|
|
253
|
+
|
|
254
|
+
**4. Update UAT frontmatter:**
|
|
255
|
+
|
|
256
|
+
If all gaps now have `status: resolved`:
|
|
257
|
+
- Update frontmatter `status: diagnosed` → `status: resolved`
|
|
258
|
+
- Update frontmatter `updated:` timestamp
|
|
259
|
+
|
|
260
|
+
**5. Resolve referenced debug sessions:**
|
|
261
|
+
|
|
262
|
+
For each gap that has a `debug_session:` field:
|
|
263
|
+
- Read the debug session file
|
|
264
|
+
- Update frontmatter `status:` → `resolved`
|
|
265
|
+
- Update frontmatter `updated:` timestamp
|
|
266
|
+
- Move to resolved directory:
|
|
267
|
+
```bash
|
|
268
|
+
mkdir -p .planning/debug/resolved
|
|
269
|
+
mv .planning/debug/{slug}.md .planning/debug/resolved/
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**6. Commit updated artifacts:**
|
|
273
|
+
```bash
|
|
274
|
+
node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs(phase-${PARENT_PHASE}): resolve UAT gaps and debug sessions after ${PHASE_NUMBER} gap closure" --files .planning/phases/*${PARENT_PHASE}*/*-UAT.md .planning/debug/resolved/*.md
|
|
275
|
+
```
|
|
276
|
+
</step>
|
|
277
|
+
|
|
229
278
|
<step name="verify_phase_goal">
|
|
230
279
|
Verify phase achieved its GOAL, not just completed tasks.
|
|
231
280
|
|
|
@@ -267,7 +316,7 @@ All automated checks passed. {N} items need human testing:
|
|
|
267
316
|
## ⚠ Phase {X}: {Name} — Gaps Found
|
|
268
317
|
|
|
269
318
|
**Score:** {N}/{M} must-haves verified
|
|
270
|
-
**Report:** {phase_dir}/{
|
|
319
|
+
**Report:** {phase_dir}/{phase_num}-VERIFICATION.md
|
|
271
320
|
|
|
272
321
|
### What's Missing
|
|
273
322
|
{Gap summaries from VERIFICATION.md}
|
|
@@ -279,7 +328,7 @@ All automated checks passed. {N} items need human testing:
|
|
|
279
328
|
|
|
280
329
|
<sub>`/clear` first → fresh context window</sub>
|
|
281
330
|
|
|
282
|
-
Also: `cat {phase_dir}/{
|
|
331
|
+
Also: `cat {phase_dir}/{phase_num}-VERIFICATION.md` — full report
|
|
283
332
|
Also: `/gsd:verify-work {X}` — manual testing first
|
|
284
333
|
```
|
|
285
334
|
|
|
@@ -17,9 +17,9 @@ Display the complete GSD command reference. Output ONLY the reference content. D
|
|
|
17
17
|
|
|
18
18
|
GSD evolves fast. Update periodically:
|
|
19
19
|
|
|
20
|
-
```bash
|
|
21
|
-
npx --yes --package=@ahmed118glitch/get-shit-done-codex@latest get-shit-done-cc
|
|
22
|
-
```
|
|
20
|
+
```bash
|
|
21
|
+
npx --yes --package=@ahmed118glitch/get-shit-done-codex@latest get-shit-done-cc
|
|
22
|
+
```
|
|
23
23
|
|
|
24
24
|
## Core Workflow
|
|
25
25
|
|
|
@@ -322,7 +322,7 @@ Update GSD to latest version with changelog preview.
|
|
|
322
322
|
- Displays changelog entries for versions you've missed
|
|
323
323
|
- Highlights breaking changes
|
|
324
324
|
- Confirms before running install
|
|
325
|
-
- Better than raw `npx --yes --package=@ahmed118glitch/get-shit-done-codex@latest get-shit-done-cc`
|
|
325
|
+
- Better than raw `npx --yes --package=@ahmed118glitch/get-shit-done-codex@latest get-shit-done-cc`
|
|
326
326
|
|
|
327
327
|
Usage: `/gsd:update`
|
|
328
328
|
|
|
@@ -200,7 +200,7 @@ Present features by category:
|
|
|
200
200
|
|
|
201
201
|
**If no research:** Gather requirements through conversation. Ask: "What are the main things users need to do with [new features]?" Clarify, probe for related capabilities, group into categories.
|
|
202
202
|
|
|
203
|
-
**Scope each category** via AskUserQuestion (multiSelect: true):
|
|
203
|
+
**Scope each category** via AskUserQuestion (multiSelect: true, header max 12 chars):
|
|
204
204
|
- "[Feature 1]" — [brief description]
|
|
205
205
|
- "[Feature 2]" — [brief description]
|
|
206
206
|
- "None for this milestone" — Defer entire category
|
|
@@ -59,7 +59,7 @@ git init
|
|
|
59
59
|
**If `needs_codebase_map` is true** (from init — existing code detected but no codebase map):
|
|
60
60
|
|
|
61
61
|
Use AskUserQuestion:
|
|
62
|
-
- header: "
|
|
62
|
+
- header: "Codebase"
|
|
63
63
|
- question: "I detected existing code in this directory. Would you like to map the codebase first?"
|
|
64
64
|
- options:
|
|
65
65
|
- "Map codebase first" — Run /gsd:map-codebase to understand existing architecture (Recommended)
|
|
@@ -303,7 +303,7 @@ questions: [
|
|
|
303
303
|
]
|
|
304
304
|
},
|
|
305
305
|
{
|
|
306
|
-
header: "
|
|
306
|
+
header: "AI Models",
|
|
307
307
|
question: "Which AI models for planning agents?",
|
|
308
308
|
multiSelect: false,
|
|
309
309
|
options: [
|
|
@@ -663,7 +663,7 @@ For each capability mentioned:
|
|
|
663
663
|
|
|
664
664
|
For each category, use AskUserQuestion:
|
|
665
665
|
|
|
666
|
-
- header: "[Category
|
|
666
|
+
- header: "[Category]" (max 12 chars)
|
|
667
667
|
- question: "Which [category] features are in v1?"
|
|
668
668
|
- multiSelect: true
|
|
669
669
|
- options:
|
|
@@ -194,7 +194,7 @@ Read its `<objective>` section.
|
|
|
194
194
|
|
|
195
195
|
**Route B: Phase needs planning**
|
|
196
196
|
|
|
197
|
-
Check if `{
|
|
197
|
+
Check if `{phase_num}-CONTEXT.md` exists in phase directory.
|
|
198
198
|
|
|
199
199
|
**If CONTEXT.md exists:**
|
|
200
200
|
|
|
@@ -246,7 +246,7 @@ UAT.md exists with gaps (diagnosed issues). User needs to plan fixes.
|
|
|
246
246
|
|
|
247
247
|
## ⚠ UAT Gaps Found
|
|
248
248
|
|
|
249
|
-
**{
|
|
249
|
+
**{phase_num}-UAT.md** has {N} gaps requiring fixes.
|
|
250
250
|
|
|
251
251
|
`/gsd:plan-phase {phase} --gaps`
|
|
252
252
|
|