@opengsd/gsd-core 1.6.0-rc.3 → 1.7.0-rc.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/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-advisor-researcher.md +2 -0
- package/agents/gsd-ai-researcher.md +2 -0
- package/agents/gsd-assumptions-analyzer.md +2 -0
- package/agents/gsd-doc-classifier.md +2 -0
- package/agents/gsd-doc-synthesizer.md +2 -0
- package/agents/gsd-domain-researcher.md +2 -0
- package/agents/gsd-eval-auditor.md +6 -9
- package/agents/gsd-phase-researcher.md +2 -0
- package/agents/gsd-project-researcher.md +2 -0
- package/agents/gsd-research-synthesizer.md +2 -0
- package/agents/gsd-ui-researcher.md +2 -0
- package/agents/gsd-verifier.md +1 -0
- package/bin/gsd-mcp-server.js +31 -0
- package/bin/install.js +512 -1150
- package/commands/gsd/review.md +6 -0
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +127 -2
- package/gsd-core/bin/lib/adapter-declarative.cjs +35 -0
- package/gsd-core/bin/lib/adapter-imperative.cjs +52 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +231 -0
- package/gsd-core/bin/lib/capability-lifecycle.cjs +7 -7
- package/gsd-core/bin/lib/capability-loader.cjs +18 -0
- package/gsd-core/bin/lib/capability-lock.cjs +2 -2
- package/gsd-core/bin/lib/capability-registry.cjs +889 -82
- package/gsd-core/bin/lib/capability-source.cjs +4 -4
- package/gsd-core/bin/lib/capability-validator.cjs +198 -0
- package/gsd-core/bin/lib/cli-skew-check.cjs +44 -0
- package/gsd-core/bin/lib/command-aliases.cjs +18 -1
- package/gsd-core/bin/lib/config.cjs +27 -0
- package/gsd-core/bin/lib/decisions.cjs +27 -0
- package/gsd-core/bin/lib/embedding-adapter.cjs +27 -0
- package/gsd-core/bin/lib/eval-command-router.cjs +21 -0
- package/gsd-core/bin/lib/eval.cjs +60 -0
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +70 -0
- package/gsd-core/bin/lib/frontmatter.cjs +132 -13
- package/gsd-core/bin/lib/hook-bus.cjs +81 -0
- package/gsd-core/bin/lib/host-integration.cjs +408 -0
- package/gsd-core/bin/lib/init.cjs +132 -27
- package/gsd-core/bin/lib/install-engine.cjs +755 -0
- package/gsd-core/bin/lib/install-profiles.cjs +35 -4
- package/gsd-core/bin/lib/installer-migrations.cjs +1 -1
- package/gsd-core/bin/lib/io.cjs +1 -0
- package/gsd-core/bin/lib/mcp-server.cjs +194 -0
- package/gsd-core/bin/lib/milestone.cjs +27 -30
- package/gsd-core/bin/lib/model-adapter.cjs +50 -0
- package/gsd-core/bin/lib/phase.cjs +57 -74
- package/gsd-core/bin/lib/plan-scan.cjs +2 -2
- package/gsd-core/bin/lib/planning-workspace.cjs +1 -1
- package/gsd-core/bin/lib/probe-core.cjs +91 -1
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +129 -13
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +3 -2
- package/gsd-core/bin/lib/roadmap.cjs +17 -3
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +65 -9
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +54 -4
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +5 -2
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +1 -1
- package/gsd-core/bin/lib/runtime-name-policy.cjs +160 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +47 -1
- package/gsd-core/bin/lib/stale-bake-guard.cjs +254 -0
- package/gsd-core/bin/lib/state-command-router.cjs +4 -0
- package/gsd-core/bin/lib/state-io.cjs +55 -0
- package/gsd-core/bin/lib/state-transition.cjs +1588 -0
- package/gsd-core/bin/lib/state.cjs +340 -689
- package/gsd-core/bin/lib/surface.cjs +4 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +13 -6
- package/gsd-core/bin/lib/verification.cjs +67 -6
- package/gsd-core/bin/lib/verify.cjs +8 -1
- package/gsd-core/bin/lib/workstream.cjs +4 -4
- package/gsd-core/bin/shared/config-defaults.manifest.json +3 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +11 -1
- package/gsd-core/references/honest-verifier.md +105 -0
- package/gsd-core/references/reviewer-instances.md +99 -0
- package/gsd-core/references/untrusted-input-boundary.md +13 -0
- package/gsd-core/workflows/autonomous.md +61 -54
- package/gsd-core/workflows/complete-milestone.md +27 -8
- package/gsd-core/workflows/execute-phase.md +1 -1
- package/gsd-core/workflows/manager.md +30 -20
- package/gsd-core/workflows/new-project.md +78 -12
- package/gsd-core/workflows/plan-phase.md +1 -1
- package/gsd-core/workflows/profile-user.md +6 -2
- package/gsd-core/workflows/progress.md +37 -4
- package/gsd-core/workflows/quick.md +3 -1
- package/gsd-core/workflows/review.md +26 -0
- package/gsd-core/workflows/ship.md +3 -1
- package/gsd-core/workflows/spec-phase.md +3 -1
- package/gsd-core/workflows/thread.md +4 -4
- package/gsd-core/workflows/transition.md +14 -12
- package/gsd-core/workflows/ui-review.md +2 -6
- package/gsd-core/workflows/verify-phase.md +11 -4
- package/gsd-core/workflows/verify-work.md +44 -0
- package/hooks/dist/gsd-graphify-update.sh +7 -1
- package/hooks/dist/gsd-read-injection-scanner.js +49 -25
- package/hooks/gsd-graphify-update.sh +7 -1
- package/hooks/gsd-read-injection-scanner.js +49 -25
- package/hooks/hooks.json +1 -1
- package/package.json +4 -4
- package/scripts/check-alias-drift.cjs +5 -0
- package/scripts/ci-test-scope.cjs +38 -9
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -1
- package/scripts/lint-regression-test-names.allowlist.json +3 -0
- package/scripts/lint-test-file-count.allowlist.json +19 -5
- package/scripts/mutation-matrix.cjs +45 -3
- package/scripts/prompt-injection-scan.sh +13 -0
- package/scripts/lint-windows-test-portability.cjs +0 -178
|
@@ -43,6 +43,10 @@ const security_cjs_1 = require("./security.cjs");
|
|
|
43
43
|
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
44
44
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- frontmatter.cjs is an export= CommonJS module
|
|
45
45
|
const frontmatterMod = require("./frontmatter.cjs");
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- verification.cjs is an export= CommonJS module
|
|
47
|
+
const verificationMod = require("./verification.cjs");
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- uat-predicate.cjs is an export= CommonJS module
|
|
49
|
+
const uatPredicateMod = require("./uat-predicate.cjs");
|
|
46
50
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- agent-install-check.cjs is an export= CommonJS module
|
|
47
51
|
const agentInstallCheck = require("./agent-install-check.cjs");
|
|
48
52
|
const { checkAgentsInstalled } = agentInstallCheck;
|
|
@@ -61,6 +65,8 @@ const { pruneOrphanedWorktrees } = worktreeSafety;
|
|
|
61
65
|
const { planningPaths, planningDir, planningRoot, findContextMdIn, } = planningWorkspace;
|
|
62
66
|
const { determinePhaseStatus } = commandsMod;
|
|
63
67
|
const { extractFrontmatter } = frontmatterMod;
|
|
68
|
+
const { readVerificationStatus } = verificationMod;
|
|
69
|
+
const { evaluateUatPassed } = uatPredicateMod;
|
|
64
70
|
// Unused but imported for structural parity
|
|
65
71
|
void stripShippedMilestones;
|
|
66
72
|
// Accept all bold/colon variants of the Requirements header (#2769)
|
|
@@ -71,6 +77,45 @@ function listPhaseSummaryFiles(phaseDir) {
|
|
|
71
77
|
function listPhasePlanFiles(phaseDir) {
|
|
72
78
|
return scanPhasePlans(phaseDir)['planFiles'];
|
|
73
79
|
}
|
|
80
|
+
function verificationNextCommand(status, phaseNumber, slashRuntime) {
|
|
81
|
+
if (status === 'gaps_found') {
|
|
82
|
+
return `${(0, runtime_slash_cjs_1.formatGsdSlash)('plan-phase', slashRuntime)} ${phaseNumber} --gaps`;
|
|
83
|
+
}
|
|
84
|
+
if (status === 'human_needed' || status === 'stale') {
|
|
85
|
+
return `${(0, runtime_slash_cjs_1.formatGsdSlash)('verify-work', slashRuntime)} ${phaseNumber}`;
|
|
86
|
+
}
|
|
87
|
+
if (status === 'missing' || status === 'unknown') {
|
|
88
|
+
return `${(0, runtime_slash_cjs_1.formatGsdSlash)('execute-phase', slashRuntime)} ${phaseNumber}`;
|
|
89
|
+
}
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
function projectCompletionStatus(implementationComplete, verificationPassed) {
|
|
93
|
+
if (implementationComplete && verificationPassed)
|
|
94
|
+
return 'complete';
|
|
95
|
+
if (implementationComplete)
|
|
96
|
+
return 'executed';
|
|
97
|
+
return 'incomplete';
|
|
98
|
+
}
|
|
99
|
+
function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, summaryCount, slashRuntime) {
|
|
100
|
+
const implementationComplete = planCount > 0 && summaryCount >= planCount;
|
|
101
|
+
const phaseFullDir = phaseDir ? node_path_1.default.join(cwd, phaseDir) : '';
|
|
102
|
+
const verificationStatus = implementationComplete
|
|
103
|
+
? readVerificationStatus(phaseFullDir)
|
|
104
|
+
: { status: 'not_required', next_action: '', next_command: '' };
|
|
105
|
+
const projectedVerificationStatus = verificationStatus.status;
|
|
106
|
+
const projectedVerificationAction = verificationStatus.next_action;
|
|
107
|
+
const verificationPassed = projectedVerificationStatus === 'passed';
|
|
108
|
+
const phaseComplete = implementationComplete && verificationPassed;
|
|
109
|
+
return {
|
|
110
|
+
implementation_complete: implementationComplete,
|
|
111
|
+
verification_status: projectedVerificationStatus,
|
|
112
|
+
verification_passed: verificationPassed,
|
|
113
|
+
phase_complete: phaseComplete,
|
|
114
|
+
completion_status: projectCompletionStatus(implementationComplete, verificationPassed),
|
|
115
|
+
verification_next_action: projectedVerificationAction,
|
|
116
|
+
verification_next_command: verificationNextCommand(projectedVerificationStatus, phaseNumber, slashRuntime),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
74
119
|
function getLatestCompletedMilestone(cwd) {
|
|
75
120
|
const milestonesPath = node_path_1.default.join(planningRoot(cwd), 'MILESTONES.md');
|
|
76
121
|
const content = (0, shell_command_projection_cjs_1.platformReadSync)(milestonesPath);
|
|
@@ -636,6 +681,7 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
636
681
|
error('phase required for init verify-work');
|
|
637
682
|
}
|
|
638
683
|
const config = loadConfig(cwd);
|
|
684
|
+
const _slashRuntime = (0, runtime_slash_cjs_1.resolveRuntime)(cwd);
|
|
639
685
|
let phaseInfo = findPhaseInternal(cwd, phase);
|
|
640
686
|
if (phaseInfo?.['archived']) {
|
|
641
687
|
const roadmapPhase = getRoadmapPhaseInternal(cwd, phase);
|
|
@@ -664,15 +710,30 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
664
710
|
};
|
|
665
711
|
}
|
|
666
712
|
}
|
|
713
|
+
const phaseDir = phaseInfo?.['directory'] || null;
|
|
714
|
+
const planCount = phaseInfo?.['plans']?.length || 0;
|
|
715
|
+
const summaryCount = phaseInfo?.['summaries']?.length || 0;
|
|
716
|
+
const completion = buildPhaseCompletionProjection(cwd, phaseInfo?.['phase_number'] || phase, phaseDir, planCount, summaryCount, _slashRuntime);
|
|
717
|
+
const uatReport = phaseDir
|
|
718
|
+
? evaluateUatPassed(node_path_1.default.join(cwd, phaseDir), {
|
|
719
|
+
policy: { requireVerification: true },
|
|
720
|
+
})
|
|
721
|
+
: null;
|
|
667
722
|
const result = {
|
|
668
723
|
planner_model: resolveModelInternal(cwd, 'gsd-planner'),
|
|
669
724
|
checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
|
|
670
725
|
commit_docs: config.commit_docs,
|
|
671
726
|
phase_found: !!phaseInfo,
|
|
672
|
-
phase_dir:
|
|
727
|
+
phase_dir: phaseDir,
|
|
673
728
|
phase_number: phaseInfo?.['phase_number'] || null,
|
|
674
729
|
phase_name: phaseInfo?.['phase_name'] || null,
|
|
675
730
|
has_verification: phaseInfo?.['has_verification'] || false,
|
|
731
|
+
phase_completion: {
|
|
732
|
+
...completion,
|
|
733
|
+
uat_passed: uatReport?.passed ?? false,
|
|
734
|
+
uat_blockers: uatReport?.blockers ?? [],
|
|
735
|
+
ready_to_transition: completion.phase_complete && (uatReport?.passed ?? false),
|
|
736
|
+
},
|
|
676
737
|
};
|
|
677
738
|
output(withProjectRoot(cwd, result), raw);
|
|
678
739
|
}
|
|
@@ -1035,18 +1096,23 @@ function cmdInitManager(cwd, raw) {
|
|
|
1035
1096
|
let hasResearch = false;
|
|
1036
1097
|
let lastActivity = null;
|
|
1037
1098
|
let isActive = false;
|
|
1099
|
+
let completion = buildPhaseCompletionProjection(cwd, phaseNum, null, planCount, summaryCount, _slashRuntime);
|
|
1038
1100
|
try {
|
|
1039
1101
|
const dirs = _phaseDirEntries.filter(isDirInMilestone);
|
|
1040
1102
|
const dirMatch = dirs.find((d) => phaseTokenMatches(d, normalized));
|
|
1041
1103
|
if (dirMatch) {
|
|
1042
1104
|
const fullDir = node_path_1.default.join(phasesDir, dirMatch);
|
|
1105
|
+
const phaseDirRel = toPosixPath(node_path_1.default.relative(cwd, fullDir));
|
|
1043
1106
|
const phaseFiles = node_fs_1.default.readdirSync(fullDir);
|
|
1044
1107
|
planCount = listPhasePlanFiles(fullDir).length;
|
|
1045
1108
|
summaryCount = listPhaseSummaryFiles(fullDir).length;
|
|
1046
1109
|
hasContext = findContextMdIn(fullDir) !== null;
|
|
1047
1110
|
hasResearch = phaseFiles.some((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
|
|
1048
|
-
|
|
1111
|
+
completion = buildPhaseCompletionProjection(cwd, phaseNum, phaseDirRel, planCount, summaryCount, _slashRuntime);
|
|
1112
|
+
if (completion.phase_complete)
|
|
1049
1113
|
diskStatus = 'complete';
|
|
1114
|
+
else if (completion.implementation_complete)
|
|
1115
|
+
diskStatus = 'executed';
|
|
1050
1116
|
else if (summaryCount > 0)
|
|
1051
1117
|
diskStatus = 'partial';
|
|
1052
1118
|
else if (planCount > 0)
|
|
@@ -1079,7 +1145,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
1079
1145
|
/* intentionally empty */
|
|
1080
1146
|
}
|
|
1081
1147
|
const roadmapComplete = _checkboxStates.get(phaseNum) || false;
|
|
1082
|
-
if (roadmapComplete && diskStatus !== 'complete') {
|
|
1148
|
+
if (roadmapComplete && completion.phase_complete && diskStatus !== 'complete') {
|
|
1083
1149
|
diskStatus = 'complete';
|
|
1084
1150
|
}
|
|
1085
1151
|
phases.push({
|
|
@@ -1093,6 +1159,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
1093
1159
|
plan_count: planCount,
|
|
1094
1160
|
summary_count: summaryCount,
|
|
1095
1161
|
roadmap_complete: roadmapComplete,
|
|
1162
|
+
...completion,
|
|
1096
1163
|
last_activity: lastActivity,
|
|
1097
1164
|
is_active: isActive,
|
|
1098
1165
|
});
|
|
@@ -1107,22 +1174,42 @@ function cmdInitManager(cwd, raw) {
|
|
|
1107
1174
|
phase['display_name'] = name;
|
|
1108
1175
|
}
|
|
1109
1176
|
}
|
|
1110
|
-
|
|
1177
|
+
function normalizePhaseNumber(value) {
|
|
1178
|
+
return value
|
|
1179
|
+
.split('.')
|
|
1180
|
+
.map((part) => {
|
|
1181
|
+
const match = /^(\d+)([A-Z]?)$/i.exec(part);
|
|
1182
|
+
if (!match)
|
|
1183
|
+
return part;
|
|
1184
|
+
return `${Number(match[1])}${match[2].toUpperCase()}`;
|
|
1185
|
+
})
|
|
1186
|
+
.join('.');
|
|
1187
|
+
}
|
|
1188
|
+
const completedNums = new Set(phases
|
|
1189
|
+
.filter((p) => p['phase_complete'] === true)
|
|
1190
|
+
.map((p) => normalizePhaseNumber(p['number'])));
|
|
1191
|
+
const phaseMap = new Map(phases.map((p) => [normalizePhaseNumber(p['number']), p]));
|
|
1111
1192
|
const _allCompletedPattern = /-\s*\[x\]\s*.*Phase\s+(\d+[A-Z]?(?:\.\d+)*)[:\s]/gi;
|
|
1112
1193
|
let _allMatch;
|
|
1113
1194
|
while ((_allMatch = _allCompletedPattern.exec(rawContent)) !== null) {
|
|
1114
|
-
|
|
1195
|
+
const phaseNum = normalizePhaseNumber(_allMatch[1]);
|
|
1196
|
+
const phase = phaseMap.get(phaseNum);
|
|
1197
|
+
if (!phase || phase['phase_complete'] === true) {
|
|
1198
|
+
completedNums.add(phaseNum);
|
|
1199
|
+
}
|
|
1115
1200
|
}
|
|
1116
|
-
const phaseMap = new Map(phases.map((p) => [p['number'], p]));
|
|
1117
1201
|
function reaches(from, to, visited = new Set()) {
|
|
1118
|
-
|
|
1202
|
+
const normalizedFrom = normalizePhaseNumber(from);
|
|
1203
|
+
const normalizedTo = normalizePhaseNumber(to);
|
|
1204
|
+
if (visited.has(normalizedFrom))
|
|
1119
1205
|
return false;
|
|
1120
|
-
visited.add(
|
|
1121
|
-
const p = phaseMap.get(
|
|
1206
|
+
visited.add(normalizedFrom);
|
|
1207
|
+
const p = phaseMap.get(normalizedFrom);
|
|
1122
1208
|
if (!p || !p['dep_phases'] || p['dep_phases'].length === 0)
|
|
1123
1209
|
return false;
|
|
1124
|
-
if (p['dep_phases'].
|
|
1210
|
+
if (p['dep_phases'].some((dep) => normalizePhaseNumber(dep) === normalizedTo)) {
|
|
1125
1211
|
return true;
|
|
1212
|
+
}
|
|
1126
1213
|
return p['dep_phases'].some((dep) => reaches(dep, to, visited));
|
|
1127
1214
|
}
|
|
1128
1215
|
function hasDepRelationship(numA, numB) {
|
|
@@ -1134,8 +1221,8 @@ function cmdInitManager(cwd, raw) {
|
|
|
1134
1221
|
phase['deps_satisfied'] = true;
|
|
1135
1222
|
}
|
|
1136
1223
|
else {
|
|
1137
|
-
const depNums = phase['depends_on'].match(/\d+(?:\.\d+)*/
|
|
1138
|
-
phase['deps_satisfied'] = depNums.every((n) => completedNums.has(n));
|
|
1224
|
+
const depNums = phase['depends_on'].match(/\d+[A-Z]?(?:\.\d+)*/gi) || [];
|
|
1225
|
+
phase['deps_satisfied'] = depNums.every((n) => completedNums.has(normalizePhaseNumber(n)));
|
|
1139
1226
|
phase['dep_phases'] = depNums;
|
|
1140
1227
|
}
|
|
1141
1228
|
}
|
|
@@ -1167,7 +1254,16 @@ function cmdInitManager(cwd, raw) {
|
|
|
1167
1254
|
continue;
|
|
1168
1255
|
if (/^999(?:\.|$)/.test(phase['number']))
|
|
1169
1256
|
continue;
|
|
1170
|
-
if (phase['disk_status'] === '
|
|
1257
|
+
if (phase['disk_status'] === 'executed') {
|
|
1258
|
+
recommendedActions.push({
|
|
1259
|
+
phase: phase['number'],
|
|
1260
|
+
phase_name: phase['name'],
|
|
1261
|
+
action: 'verify',
|
|
1262
|
+
reason: `Implementation complete; verification ${phase['verification_status']}`,
|
|
1263
|
+
command: phase['verification_next_command'],
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
else if (phase['disk_status'] === 'planned' && phase['deps_satisfied']) {
|
|
1171
1267
|
recommendedActions.push({
|
|
1172
1268
|
phase: phase['number'],
|
|
1173
1269
|
phase_name: phase['name'],
|
|
@@ -1211,7 +1307,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
1211
1307
|
return true;
|
|
1212
1308
|
});
|
|
1213
1309
|
const nonBacklogPhases = phases.filter((p) => !/^999(?:\.|$)/.test(p['number']));
|
|
1214
|
-
const completedCount = nonBacklogPhases.filter((p) => p['
|
|
1310
|
+
const completedCount = nonBacklogPhases.filter((p) => p['phase_complete'] === true).length;
|
|
1215
1311
|
const sanitizeFlags = (rawVal) => {
|
|
1216
1312
|
const val = typeof rawVal === 'string' ? rawVal : '';
|
|
1217
1313
|
if (!val)
|
|
@@ -1238,7 +1334,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
1238
1334
|
phases,
|
|
1239
1335
|
phase_count: phases.length,
|
|
1240
1336
|
completed_count: completedCount,
|
|
1241
|
-
in_progress_count: phases.filter((p) => ['partial', 'planned', 'discussed', 'researched'].includes(p['disk_status'])).length,
|
|
1337
|
+
in_progress_count: phases.filter((p) => ['executed', 'partial', 'planned', 'discussed', 'researched'].includes(p['disk_status'])).length,
|
|
1242
1338
|
recommended_actions: filteredActions,
|
|
1243
1339
|
waiting_signal: waitingSignal,
|
|
1244
1340
|
all_complete: completedCount === nonBacklogPhases.length && nonBacklogPhases.length > 0,
|
|
@@ -1258,6 +1354,7 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1258
1354
|
}
|
|
1259
1355
|
const config = loadConfig(cwd);
|
|
1260
1356
|
const milestone = getMilestoneInfo(cwd);
|
|
1357
|
+
const _slashRuntime = (0, runtime_slash_cjs_1.resolveRuntime)(cwd);
|
|
1261
1358
|
const phasesDir = node_path_1.default.join(planningDir(cwd), 'phases');
|
|
1262
1359
|
const phases = [];
|
|
1263
1360
|
let currentPhase = null;
|
|
@@ -1307,24 +1404,29 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1307
1404
|
const plans = listPhasePlanFiles(phasePath);
|
|
1308
1405
|
const summaries = listPhaseSummaryFiles(phasePath);
|
|
1309
1406
|
const hasResearch = phaseFiles.some((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
|
|
1310
|
-
const
|
|
1407
|
+
const phaseDirRel = toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'phases', dir)));
|
|
1408
|
+
const completion = buildPhaseCompletionProjection(cwd, phaseNumber, phaseDirRel, plans.length, summaries.length, _slashRuntime);
|
|
1409
|
+
const status = completion.phase_complete
|
|
1311
1410
|
? 'complete'
|
|
1312
|
-
:
|
|
1313
|
-
? '
|
|
1314
|
-
:
|
|
1315
|
-
? '
|
|
1316
|
-
:
|
|
1411
|
+
: completion.implementation_complete
|
|
1412
|
+
? 'executed'
|
|
1413
|
+
: plans.length > 0
|
|
1414
|
+
? 'in_progress'
|
|
1415
|
+
: hasResearch
|
|
1416
|
+
? 'researched'
|
|
1417
|
+
: 'pending';
|
|
1317
1418
|
const phaseInfo = {
|
|
1318
1419
|
number: phaseNumber,
|
|
1319
1420
|
name: phaseName,
|
|
1320
|
-
directory:
|
|
1421
|
+
directory: phaseDirRel,
|
|
1321
1422
|
status,
|
|
1322
1423
|
plan_count: plans.length,
|
|
1323
1424
|
summary_count: summaries.length,
|
|
1324
1425
|
has_research: hasResearch,
|
|
1426
|
+
...completion,
|
|
1325
1427
|
};
|
|
1326
1428
|
phases.push(phaseInfo);
|
|
1327
|
-
if (!currentPhase && (status === 'in_progress' || status === 'researched')) {
|
|
1429
|
+
if (!currentPhase && (status === 'executed' || status === 'in_progress' || status === 'researched')) {
|
|
1328
1430
|
currentPhase = phaseInfo;
|
|
1329
1431
|
}
|
|
1330
1432
|
if (!nextPhase && status === 'pending') {
|
|
@@ -1340,7 +1442,8 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1340
1442
|
if (!seenPhaseNums.has(stripped)) {
|
|
1341
1443
|
const checkboxComplete = roadmapCheckboxStates.get(num) === true ||
|
|
1342
1444
|
roadmapCheckboxStates.get(stripped) === true;
|
|
1343
|
-
const
|
|
1445
|
+
const completion = buildPhaseCompletionProjection(cwd, num, null, 0, 0, _slashRuntime);
|
|
1446
|
+
const status = 'not_started';
|
|
1344
1447
|
const phaseInfo = {
|
|
1345
1448
|
number: num,
|
|
1346
1449
|
name: name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''),
|
|
@@ -1349,9 +1452,11 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1349
1452
|
plan_count: 0,
|
|
1350
1453
|
summary_count: 0,
|
|
1351
1454
|
has_research: false,
|
|
1455
|
+
roadmap_complete: checkboxComplete,
|
|
1456
|
+
...completion,
|
|
1352
1457
|
};
|
|
1353
1458
|
phases.push(phaseInfo);
|
|
1354
|
-
if (!nextPhase && !currentPhase &&
|
|
1459
|
+
if (!nextPhase && !currentPhase && !checkboxComplete) {
|
|
1355
1460
|
nextPhase = phaseInfo;
|
|
1356
1461
|
}
|
|
1357
1462
|
}
|
|
@@ -1373,7 +1478,7 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1373
1478
|
phases,
|
|
1374
1479
|
phase_count: phases.length,
|
|
1375
1480
|
completed_count: phases.filter((p) => p['status'] === 'complete').length,
|
|
1376
|
-
in_progress_count: phases.filter((p) =>
|
|
1481
|
+
in_progress_count: phases.filter((p) => ['executed', 'in_progress'].includes(p['status'])).length,
|
|
1377
1482
|
current_phase: currentPhase,
|
|
1378
1483
|
next_phase: nextPhase,
|
|
1379
1484
|
paused_at: pausedAt,
|
|
@@ -1651,7 +1756,7 @@ function buildAgentSkillsBlock(config, agentType, projectRoot, diagnostics) {
|
|
|
1651
1756
|
if (entry.kind === 'directive') {
|
|
1652
1757
|
return `- Load the \`${entry.name}\` skill via the Skill tool before proceeding (plugin-provided).`;
|
|
1653
1758
|
}
|
|
1654
|
-
return `- @${entry.ref}`;
|
|
1759
|
+
return `- @${String(entry.ref).replace(/\\/g, '/')}`;
|
|
1655
1760
|
}).join('\n');
|
|
1656
1761
|
return `<agent_skills>\nRead these user-configured skills:\n${lines}\n</agent_skills>`;
|
|
1657
1762
|
}
|