@bhargavvc/sdd-cc 1.30.1 → 1.35.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/README.ja-JP.md +144 -110
- package/README.ko-KR.md +143 -107
- package/README.md +183 -112
- package/README.pt-BR.md +90 -52
- package/README.zh-CN.md +141 -101
- package/agents/sdd-advisor-researcher.md +23 -0
- package/agents/sdd-ai-researcher.md +133 -0
- package/agents/sdd-code-fixer.md +516 -0
- package/agents/sdd-code-reviewer.md +355 -0
- package/agents/sdd-codebase-mapper.md +3 -3
- package/agents/sdd-debugger.md +17 -5
- package/agents/sdd-doc-verifier.md +201 -0
- package/agents/sdd-doc-writer.md +602 -0
- package/agents/sdd-domain-researcher.md +153 -0
- package/agents/sdd-eval-auditor.md +164 -0
- package/agents/sdd-eval-planner.md +154 -0
- package/agents/sdd-executor.md +87 -4
- package/agents/sdd-framework-selector.md +160 -0
- package/agents/sdd-intel-updater.md +314 -0
- package/agents/sdd-nyquist-auditor.md +1 -1
- package/agents/sdd-phase-researcher.md +71 -4
- package/agents/sdd-plan-checker.md +100 -6
- package/agents/sdd-planner.md +145 -206
- package/agents/sdd-project-researcher.md +25 -2
- package/agents/sdd-research-synthesizer.md +3 -3
- package/agents/sdd-roadmapper.md +6 -6
- package/agents/sdd-security-auditor.md +128 -0
- package/agents/sdd-ui-auditor.md +43 -3
- package/agents/sdd-ui-checker.md +5 -5
- package/agents/sdd-ui-researcher.md +27 -4
- package/agents/sdd-user-profiler.md +2 -2
- package/agents/sdd-verifier.md +142 -22
- package/bin/install.js +2145 -545
- package/commands/sdd/add-backlog.md +5 -5
- package/commands/sdd/add-tests.md +2 -2
- package/commands/sdd/ai-integration-phase.md +36 -0
- package/commands/sdd/analyze-dependencies.md +34 -0
- package/commands/sdd/audit-fix.md +33 -0
- package/commands/sdd/autonomous.md +7 -2
- package/commands/sdd/cleanup.md +5 -0
- package/commands/sdd/code-review-fix.md +52 -0
- package/commands/sdd/code-review.md +55 -0
- package/commands/sdd/complete-milestone.md +6 -6
- package/commands/sdd/debug.md +22 -9
- package/commands/sdd/discuss-phase.md +7 -2
- package/commands/sdd/do.md +1 -1
- package/commands/sdd/docs-update.md +48 -0
- package/commands/sdd/eval-review.md +32 -0
- package/commands/sdd/execute-phase.md +4 -0
- package/commands/sdd/explore.md +27 -0
- package/commands/sdd/fast.md +2 -2
- package/commands/sdd/from-sdd2.md +45 -0
- package/commands/sdd/help.md +2 -0
- package/commands/sdd/import.md +36 -0
- package/commands/sdd/intel.md +179 -0
- package/commands/sdd/join-discord.md +2 -1
- package/commands/sdd/manager.md +1 -0
- package/commands/sdd/map-codebase.md +3 -3
- package/commands/sdd/new-milestone.md +1 -1
- package/commands/sdd/new-project.md +5 -1
- package/commands/sdd/new-workspace.md +1 -1
- package/commands/sdd/next.md +2 -0
- package/commands/sdd/plan-milestone-gaps.md +2 -2
- package/commands/sdd/plan-phase.md +6 -1
- package/commands/sdd/plant-seed.md +1 -1
- package/commands/sdd/profile-user.md +1 -1
- package/commands/sdd/quick.md +5 -3
- package/commands/sdd/reapply-patches.md +230 -42
- package/commands/sdd/research-phase.md +3 -3
- package/commands/sdd/review-backlog.md +1 -0
- package/commands/sdd/review.md +6 -3
- package/commands/sdd/scan.md +26 -0
- package/commands/sdd/secure-phase.md +35 -0
- package/commands/sdd/ship.md +1 -1
- package/commands/sdd/thread.md +5 -5
- package/commands/sdd/undo.md +34 -0
- package/commands/sdd/verify-work.md +1 -1
- package/commands/sdd/workstreams.md +17 -11
- package/hooks/dist/sdd-check-update.js +33 -8
- package/hooks/dist/sdd-context-monitor.js +17 -8
- package/hooks/dist/sdd-phase-boundary.sh +27 -0
- package/hooks/dist/sdd-prompt-guard.js +1 -0
- package/hooks/dist/sdd-read-guard.js +82 -0
- package/hooks/dist/sdd-session-state.sh +33 -0
- package/hooks/dist/sdd-statusline.js +137 -15
- package/hooks/dist/sdd-validate-commit.sh +47 -0
- package/hooks/dist/sdd-workflow-guard.js +4 -4
- package/hooks/sdd-check-update.js +139 -0
- package/hooks/sdd-context-monitor.js +165 -0
- package/hooks/sdd-phase-boundary.sh +27 -0
- package/hooks/sdd-prompt-guard.js +97 -0
- package/hooks/sdd-read-guard.js +82 -0
- package/hooks/sdd-session-state.sh +33 -0
- package/hooks/sdd-statusline.js +241 -0
- package/hooks/sdd-validate-commit.sh +47 -0
- package/hooks/sdd-workflow-guard.js +94 -0
- package/package.json +3 -3
- package/scripts/build-hooks.js +18 -7
- package/scripts/prompt-injection-scan.sh +1 -0
- package/scripts/rebrand-gsd-to-sdd.sh +221 -220
- package/scripts/run-tests.cjs +5 -1
- package/scripts/sync-upstream.sh +1 -1
- package/sdd/bin/lib/commands.cjs +79 -17
- package/sdd/bin/lib/config.cjs +90 -48
- package/sdd/bin/lib/core.cjs +452 -87
- package/sdd/bin/lib/docs.cjs +267 -0
- package/sdd/bin/lib/frontmatter.cjs +381 -336
- package/sdd/bin/lib/init.cjs +110 -16
- package/sdd/bin/lib/intel.cjs +660 -0
- package/sdd/bin/lib/learnings.cjs +378 -0
- package/sdd/bin/lib/milestone.cjs +42 -11
- package/sdd/bin/lib/model-profiles.cjs +17 -15
- package/sdd/bin/lib/phase.cjs +367 -288
- package/sdd/bin/lib/profile-output.cjs +106 -10
- package/sdd/bin/lib/roadmap.cjs +146 -115
- package/sdd/bin/lib/schema-detect.cjs +238 -0
- package/sdd/bin/lib/sdd2-import.cjs +511 -0
- package/sdd/bin/lib/security.cjs +124 -3
- package/sdd/bin/lib/state.cjs +648 -264
- package/sdd/bin/lib/template.cjs +8 -4
- package/sdd/bin/lib/verify.cjs +209 -28
- package/sdd/bin/lib/workstream.cjs +7 -3
- package/sdd/bin/sdd-tools.cjs +184 -12
- package/sdd/contexts/dev.md +21 -0
- package/sdd/contexts/research.md +22 -0
- package/sdd/contexts/review.md +22 -0
- package/sdd/references/agent-contracts.md +79 -0
- package/sdd/references/ai-evals.md +156 -0
- package/sdd/references/ai-frameworks.md +186 -0
- package/sdd/references/artifact-types.md +113 -0
- package/sdd/references/common-bug-patterns.md +114 -0
- package/sdd/references/context-budget.md +49 -0
- package/sdd/references/continuation-format.md +25 -25
- package/sdd/references/domain-probes.md +125 -0
- package/sdd/references/few-shot-examples/plan-checker.md +73 -0
- package/sdd/references/few-shot-examples/verifier.md +109 -0
- package/sdd/references/gate-prompts.md +100 -0
- package/sdd/references/gates.md +70 -0
- package/sdd/references/git-integration.md +1 -1
- package/sdd/references/ios-scaffold.md +123 -0
- package/sdd/references/model-profile-resolution.md +2 -0
- package/sdd/references/model-profiles.md +24 -18
- package/sdd/references/planner-gap-closure.md +62 -0
- package/sdd/references/planner-reviews.md +39 -0
- package/sdd/references/planner-revision.md +87 -0
- package/sdd/references/planning-config.md +252 -0
- package/sdd/references/revision-loop.md +97 -0
- package/sdd/references/thinking-models-debug.md +44 -0
- package/sdd/references/thinking-models-execution.md +50 -0
- package/sdd/references/thinking-models-planning.md +62 -0
- package/sdd/references/thinking-models-research.md +50 -0
- package/sdd/references/thinking-models-verification.md +55 -0
- package/sdd/references/thinking-partner.md +96 -0
- package/sdd/references/ui-brand.md +4 -4
- package/sdd/references/universal-anti-patterns.md +63 -0
- package/sdd/references/verification-overrides.md +227 -0
- package/sdd/references/workstream-flag.md +56 -3
- package/sdd/templates/AI-SPEC.md +246 -0
- package/sdd/templates/DEBUG.md +1 -1
- package/sdd/templates/SECURITY.md +61 -0
- package/sdd/templates/UAT.md +4 -4
- package/sdd/templates/VALIDATION.md +4 -4
- package/sdd/templates/claude-md.md +32 -9
- package/sdd/templates/config.json +4 -0
- package/sdd/templates/debug-subagent-prompt.md +1 -1
- package/sdd/templates/dev-preferences.md +1 -1
- package/sdd/templates/discovery.md +2 -2
- package/sdd/templates/phase-prompt.md +1 -1
- package/sdd/templates/planner-subagent-prompt.md +3 -3
- package/sdd/templates/project.md +1 -1
- package/sdd/templates/research.md +1 -1
- package/sdd/templates/state.md +2 -2
- package/sdd/workflows/add-phase.md +8 -8
- package/sdd/workflows/add-tests.md +12 -9
- package/sdd/workflows/add-todo.md +5 -3
- package/sdd/workflows/ai-integration-phase.md +284 -0
- package/sdd/workflows/analyze-dependencies.md +96 -0
- package/sdd/workflows/audit-fix.md +157 -0
- package/sdd/workflows/audit-milestone.md +11 -11
- package/sdd/workflows/audit-uat.md +2 -2
- package/sdd/workflows/autonomous.md +195 -27
- package/sdd/workflows/check-todos.md +12 -10
- package/sdd/workflows/cleanup.md +2 -0
- package/sdd/workflows/code-review-fix.md +497 -0
- package/sdd/workflows/code-review.md +515 -0
- package/sdd/workflows/complete-milestone.md +56 -22
- package/sdd/workflows/diagnose-issues.md +10 -3
- package/sdd/workflows/discovery-phase.md +5 -3
- package/sdd/workflows/discuss-phase-assumptions.md +24 -6
- package/sdd/workflows/discuss-phase-power.md +291 -0
- package/sdd/workflows/discuss-phase.md +173 -21
- package/sdd/workflows/do.md +23 -21
- package/sdd/workflows/docs-update.md +1155 -0
- package/sdd/workflows/eval-review.md +155 -0
- package/sdd/workflows/execute-phase.md +594 -38
- package/sdd/workflows/execute-plan.md +67 -96
- package/sdd/workflows/explore.md +139 -0
- package/sdd/workflows/fast.md +5 -5
- package/sdd/workflows/forensics.md +2 -2
- package/sdd/workflows/health.md +4 -4
- package/sdd/workflows/help.md +122 -119
- package/sdd/workflows/import.md +276 -0
- package/sdd/workflows/inbox.md +387 -0
- package/sdd/workflows/insert-phase.md +7 -7
- package/sdd/workflows/list-phase-assumptions.md +4 -4
- package/sdd/workflows/list-workspaces.md +2 -2
- package/sdd/workflows/manager.md +35 -32
- package/sdd/workflows/map-codebase.md +7 -5
- package/sdd/workflows/milestone-summary.md +2 -2
- package/sdd/workflows/new-milestone.md +17 -9
- package/sdd/workflows/new-project.md +50 -25
- package/sdd/workflows/new-workspace.md +7 -5
- package/sdd/workflows/next.md +67 -11
- package/sdd/workflows/note.md +9 -7
- package/sdd/workflows/pause-work.md +75 -12
- package/sdd/workflows/plan-milestone-gaps.md +8 -8
- package/sdd/workflows/plan-phase.md +294 -42
- package/sdd/workflows/plant-seed.md +6 -3
- package/sdd/workflows/pr-branch.md +42 -14
- package/sdd/workflows/profile-user.md +9 -7
- package/sdd/workflows/progress.md +45 -45
- package/sdd/workflows/quick.md +195 -47
- package/sdd/workflows/remove-phase.md +6 -6
- package/sdd/workflows/remove-workspace.md +3 -1
- package/sdd/workflows/research-phase.md +2 -2
- package/sdd/workflows/resume-project.md +12 -12
- package/sdd/workflows/review.md +109 -9
- package/sdd/workflows/scan.md +102 -0
- package/sdd/workflows/secure-phase.md +166 -0
- package/sdd/workflows/session-report.md +2 -2
- package/sdd/workflows/settings.md +38 -12
- package/sdd/workflows/ship.md +21 -9
- package/sdd/workflows/stats.md +1 -1
- package/sdd/workflows/transition.md +23 -23
- package/sdd/workflows/ui-phase.md +15 -7
- package/sdd/workflows/ui-review.md +29 -4
- package/sdd/workflows/undo.md +314 -0
- package/sdd/workflows/update.md +171 -20
- package/sdd/workflows/validate-phase.md +6 -4
- package/sdd/workflows/verify-phase.md +210 -6
- package/sdd/workflows/verify-work.md +83 -9
- package/sdd/commands/sdd/workstreams.md +0 -63
package/sdd/bin/lib/init.cjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const { execSync } = require('child_process');
|
|
8
|
-
const { loadConfig, resolveModelInternal, findPhaseInternal, getRoadmapPhaseInternal, pathExistsInternal, generateSlugInternal, getMilestoneInfo, getMilestonePhaseFilter, stripShippedMilestones, extractCurrentMilestone, normalizePhaseName, planningPaths, planningDir, planningRoot, toPosixPath, output, error, checkAgentsInstalled } = require('./core.cjs');
|
|
8
|
+
const { loadConfig, resolveModelInternal, findPhaseInternal, getRoadmapPhaseInternal, pathExistsInternal, generateSlugInternal, getMilestoneInfo, getMilestonePhaseFilter, stripShippedMilestones, extractCurrentMilestone, normalizePhaseName, planningPaths, planningDir, planningRoot, toPosixPath, output, error, checkAgentsInstalled, phaseTokenMatches } = require('./core.cjs');
|
|
9
9
|
|
|
10
10
|
function getLatestCompletedMilestone(cwd) {
|
|
11
11
|
const milestonesPath = path.join(planningRoot(cwd), 'MILESTONES.md');
|
|
@@ -37,10 +37,17 @@ function withProjectRoot(cwd, result) {
|
|
|
37
37
|
const agentStatus = checkAgentsInstalled();
|
|
38
38
|
result.agents_installed = agentStatus.agents_installed;
|
|
39
39
|
result.missing_agents = agentStatus.missing_agents;
|
|
40
|
+
// Inject response_language into all init outputs (#1399).
|
|
41
|
+
// Workflows propagate this to subagent prompts so user-facing questions
|
|
42
|
+
// stay in the configured language across phase boundaries.
|
|
43
|
+
const config = loadConfig(cwd);
|
|
44
|
+
if (config.response_language) {
|
|
45
|
+
result.response_language = config.response_language;
|
|
46
|
+
}
|
|
40
47
|
return result;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
|
-
function cmdInitExecutePhase(cwd, phase, raw) {
|
|
50
|
+
function cmdInitExecutePhase(cwd, phase, raw, options = {}) {
|
|
44
51
|
if (!phase) {
|
|
45
52
|
error('phase required for init execute-phase');
|
|
46
53
|
}
|
|
@@ -108,6 +115,7 @@ function cmdInitExecutePhase(cwd, phase, raw) {
|
|
|
108
115
|
// Branch name (pre-computed)
|
|
109
116
|
branch_name: config.branching_strategy === 'phase' && phaseInfo
|
|
110
117
|
? config.phase_branch_template
|
|
118
|
+
.replace('{project}', config.project_code || '')
|
|
111
119
|
.replace('{phase}', phaseInfo.phase_number)
|
|
112
120
|
.replace('{slug}', phaseInfo.phase_slug || 'phase')
|
|
113
121
|
: config.branching_strategy === 'milestone'
|
|
@@ -131,10 +139,38 @@ function cmdInitExecutePhase(cwd, phase, raw) {
|
|
|
131
139
|
config_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'config.json'))),
|
|
132
140
|
};
|
|
133
141
|
|
|
142
|
+
// Optional --validate: run state validation and include warnings (#1627)
|
|
143
|
+
if (options.validate) {
|
|
144
|
+
try {
|
|
145
|
+
const { cmdStateValidate } = require('./state.cjs');
|
|
146
|
+
// Capture validate output by temporarily redirecting
|
|
147
|
+
const statePath = path.join(planningDir(cwd), 'STATE.md');
|
|
148
|
+
if (fs.existsSync(statePath)) {
|
|
149
|
+
const stateContent = fs.readFileSync(statePath, 'utf-8');
|
|
150
|
+
const { stateExtractField } = require('./state.cjs');
|
|
151
|
+
const status = stateExtractField(stateContent, 'Status') || '';
|
|
152
|
+
result.state_validation_ran = true;
|
|
153
|
+
// Simple inline validation — check for obvious drift
|
|
154
|
+
const warnings = [];
|
|
155
|
+
const phasesPath = planningPaths(cwd).phases;
|
|
156
|
+
if (phaseInfo && phaseInfo.directory && fs.existsSync(path.join(cwd, phaseInfo.directory))) {
|
|
157
|
+
const files = fs.readdirSync(path.join(cwd, phaseInfo.directory));
|
|
158
|
+
const diskPlans = files.filter(f => f.match(/-PLAN\.md$/i)).length;
|
|
159
|
+
const totalPlansRaw = stateExtractField(stateContent, 'Total Plans in Phase');
|
|
160
|
+
const totalPlansInPhase = totalPlansRaw ? parseInt(totalPlansRaw, 10) : null;
|
|
161
|
+
if (totalPlansInPhase !== null && diskPlans !== totalPlansInPhase) {
|
|
162
|
+
warnings.push(`Plan count mismatch: STATE.md says ${totalPlansInPhase}, disk has ${diskPlans}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
result.state_warnings = warnings;
|
|
166
|
+
}
|
|
167
|
+
} catch { /* intentionally empty */ }
|
|
168
|
+
}
|
|
169
|
+
|
|
134
170
|
output(withProjectRoot(cwd, result), raw);
|
|
135
171
|
}
|
|
136
172
|
|
|
137
|
-
function cmdInitPlanPhase(cwd, phase, raw) {
|
|
173
|
+
function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
138
174
|
if (!phase) {
|
|
139
175
|
error('phase required for init plan-phase');
|
|
140
176
|
}
|
|
@@ -235,6 +271,25 @@ function cmdInitPlanPhase(cwd, phase, raw) {
|
|
|
235
271
|
} catch { /* intentionally empty */ }
|
|
236
272
|
}
|
|
237
273
|
|
|
274
|
+
// Optional --validate: run state validation and include warnings (#1627)
|
|
275
|
+
if (options.validate) {
|
|
276
|
+
try {
|
|
277
|
+
const statePath = path.join(planningDir(cwd), 'STATE.md');
|
|
278
|
+
if (fs.existsSync(statePath)) {
|
|
279
|
+
const { stateExtractField } = require('./state.cjs');
|
|
280
|
+
const stateContent = fs.readFileSync(statePath, 'utf-8');
|
|
281
|
+
const warnings = [];
|
|
282
|
+
result.state_validation_ran = true;
|
|
283
|
+
const totalPlansRaw = stateExtractField(stateContent, 'Total Plans in Phase');
|
|
284
|
+
const totalPlansInPhase = totalPlansRaw ? parseInt(totalPlansRaw, 10) : null;
|
|
285
|
+
if (totalPlansInPhase !== null && phaseInfo && totalPlansInPhase !== (phaseInfo.plans?.length || 0)) {
|
|
286
|
+
warnings.push(`Plan count mismatch: STATE.md says ${totalPlansInPhase}, disk has ${phaseInfo.plans?.length || 0}`);
|
|
287
|
+
}
|
|
288
|
+
result.state_warnings = warnings;
|
|
289
|
+
}
|
|
290
|
+
} catch { /* intentionally empty */ }
|
|
291
|
+
}
|
|
292
|
+
|
|
238
293
|
output(withProjectRoot(cwd, result), raw);
|
|
239
294
|
}
|
|
240
295
|
|
|
@@ -275,7 +330,7 @@ function cmdInitNewProject(cwd, raw) {
|
|
|
275
330
|
'.ex', '.exs', // Elixir
|
|
276
331
|
'.clj', // Clojure
|
|
277
332
|
]);
|
|
278
|
-
const skipDirs = new Set(['node_modules', '.git', '.planning', '.claude', '__pycache__', 'target', 'dist', 'build']);
|
|
333
|
+
const skipDirs = new Set(['node_modules', '.git', '.planning', '.claude', '.codex', '__pycache__', 'target', 'dist', 'build']);
|
|
279
334
|
function findCodeFiles(dir, depth) {
|
|
280
335
|
if (depth > 3) return false;
|
|
281
336
|
let entries;
|
|
@@ -779,6 +834,7 @@ function cmdInitMapCodebase(cwd, raw) {
|
|
|
779
834
|
commit_docs: config.commit_docs,
|
|
780
835
|
search_gitignored: config.search_gitignored,
|
|
781
836
|
parallelization: config.parallelization,
|
|
837
|
+
subagent_timeout: config.subagent_timeout,
|
|
782
838
|
|
|
783
839
|
// Paths
|
|
784
840
|
codebase_dir: '.planning/codebase',
|
|
@@ -804,16 +860,33 @@ function cmdInitManager(cwd, raw) {
|
|
|
804
860
|
|
|
805
861
|
// Validate prerequisites
|
|
806
862
|
if (!fs.existsSync(paths.roadmap)) {
|
|
807
|
-
error('No ROADMAP.md found. Run /sdd
|
|
863
|
+
error('No ROADMAP.md found. Run /sdd-new-milestone first.');
|
|
808
864
|
}
|
|
809
865
|
if (!fs.existsSync(paths.state)) {
|
|
810
|
-
error('No STATE.md found. Run /sdd
|
|
866
|
+
error('No STATE.md found. Run /sdd-new-milestone first.');
|
|
811
867
|
}
|
|
812
868
|
const rawContent = fs.readFileSync(paths.roadmap, 'utf-8');
|
|
813
869
|
const content = extractCurrentMilestone(rawContent, cwd);
|
|
814
870
|
const phasesDir = paths.phases;
|
|
815
871
|
const isDirInMilestone = getMilestonePhaseFilter(cwd);
|
|
816
872
|
|
|
873
|
+
// Pre-compute directory listing once (avoids O(N) readdirSync per phase)
|
|
874
|
+
const _phaseDirEntries = (() => {
|
|
875
|
+
try {
|
|
876
|
+
return fs.readdirSync(phasesDir, { withFileTypes: true })
|
|
877
|
+
.filter(e => e.isDirectory())
|
|
878
|
+
.map(e => e.name);
|
|
879
|
+
} catch { return []; }
|
|
880
|
+
})();
|
|
881
|
+
|
|
882
|
+
// Pre-extract all checkbox states in a single pass (avoids O(N) regex per phase)
|
|
883
|
+
const _checkboxStates = new Map();
|
|
884
|
+
const _cbPattern = /-\s*\[(x| )\]\s*.*Phase\s+(\d+[A-Z]?(?:\.\d+)*)[:\s]/gi;
|
|
885
|
+
let _cbMatch;
|
|
886
|
+
while ((_cbMatch = _cbPattern.exec(content)) !== null) {
|
|
887
|
+
_checkboxStates.set(_cbMatch[2], _cbMatch[1].toLowerCase() === 'x');
|
|
888
|
+
}
|
|
889
|
+
|
|
817
890
|
const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi;
|
|
818
891
|
const phases = [];
|
|
819
892
|
let match;
|
|
@@ -844,9 +917,8 @@ function cmdInitManager(cwd, raw) {
|
|
|
844
917
|
let isActive = false;
|
|
845
918
|
|
|
846
919
|
try {
|
|
847
|
-
const
|
|
848
|
-
const
|
|
849
|
-
const dirMatch = dirs.find(d => d.startsWith(normalized + '-') || d === normalized);
|
|
920
|
+
const dirs = _phaseDirEntries.filter(isDirInMilestone);
|
|
921
|
+
const dirMatch = dirs.find(d => phaseTokenMatches(d, normalized));
|
|
850
922
|
|
|
851
923
|
if (dirMatch) {
|
|
852
924
|
const fullDir = path.join(phasesDir, dirMatch);
|
|
@@ -879,10 +951,8 @@ function cmdInitManager(cwd, raw) {
|
|
|
879
951
|
}
|
|
880
952
|
} catch { /* intentionally empty */ }
|
|
881
953
|
|
|
882
|
-
// Check ROADMAP checkbox status
|
|
883
|
-
const
|
|
884
|
-
const checkboxMatch = content.match(checkboxPattern);
|
|
885
|
-
const roadmapComplete = checkboxMatch ? checkboxMatch[1] === 'x' : false;
|
|
954
|
+
// Check ROADMAP checkbox status (pre-extracted above the loop)
|
|
955
|
+
const roadmapComplete = _checkboxStates.get(phaseNum) || false;
|
|
886
956
|
if (roadmapComplete && diskStatus !== 'complete') {
|
|
887
957
|
diskStatus = 'complete';
|
|
888
958
|
}
|
|
@@ -954,9 +1024,11 @@ function cmdInitManager(cwd, raw) {
|
|
|
954
1024
|
} catch { /* intentionally empty */ }
|
|
955
1025
|
|
|
956
1026
|
// Compute recommended actions (execute > plan > discuss)
|
|
1027
|
+
// Skip BACKLOG phases (999.x numbering) — they are parked ideas, not active work
|
|
957
1028
|
const recommendedActions = [];
|
|
958
1029
|
for (const phase of phases) {
|
|
959
1030
|
if (phase.disk_status === 'complete') continue;
|
|
1031
|
+
if (/^999(?:\.|$)/.test(phase.number)) continue;
|
|
960
1032
|
|
|
961
1033
|
if (phase.disk_status === 'planned' && phase.deps_satisfied) {
|
|
962
1034
|
recommendedActions.push({
|
|
@@ -964,7 +1036,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
964
1036
|
phase_name: phase.name,
|
|
965
1037
|
action: 'execute',
|
|
966
1038
|
reason: `${phase.plan_count} plans ready, dependencies met`,
|
|
967
|
-
command: `/sdd
|
|
1039
|
+
command: `/sdd-execute-phase ${phase.number}`,
|
|
968
1040
|
});
|
|
969
1041
|
} else if (phase.disk_status === 'discussed' || phase.disk_status === 'researched') {
|
|
970
1042
|
recommendedActions.push({
|
|
@@ -972,7 +1044,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
972
1044
|
phase_name: phase.name,
|
|
973
1045
|
action: 'plan',
|
|
974
1046
|
reason: 'Context gathered, ready for planning',
|
|
975
|
-
command: `/sdd
|
|
1047
|
+
command: `/sdd-plan-phase ${phase.number}`,
|
|
976
1048
|
});
|
|
977
1049
|
} else if ((phase.disk_status === 'empty' || phase.disk_status === 'no_directory') && phase.is_next_to_discuss) {
|
|
978
1050
|
recommendedActions.push({
|
|
@@ -980,7 +1052,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
980
1052
|
phase_name: phase.name,
|
|
981
1053
|
action: 'discuss',
|
|
982
1054
|
reason: 'Unblocked, ready to gather context',
|
|
983
|
-
command: `/sdd
|
|
1055
|
+
command: `/sdd-discuss-phase ${phase.number}`,
|
|
984
1056
|
});
|
|
985
1057
|
}
|
|
986
1058
|
}
|
|
@@ -1024,6 +1096,27 @@ function cmdInitManager(cwd, raw) {
|
|
|
1024
1096
|
});
|
|
1025
1097
|
|
|
1026
1098
|
const completedCount = phases.filter(p => p.disk_status === 'complete').length;
|
|
1099
|
+
|
|
1100
|
+
// Read manager flags from config (passthrough flags for each step)
|
|
1101
|
+
// Validate: flags must be CLI-safe (only --flags, alphanumeric, hyphens, spaces)
|
|
1102
|
+
const sanitizeFlags = (raw) => {
|
|
1103
|
+
const val = typeof raw === 'string' ? raw : '';
|
|
1104
|
+
if (!val) return '';
|
|
1105
|
+
// Allow only --flag patterns with alphanumeric/hyphen values separated by spaces
|
|
1106
|
+
const tokens = val.split(/\s+/).filter(Boolean);
|
|
1107
|
+
const safe = tokens.every(t => /^--[a-zA-Z0-9][-a-zA-Z0-9]*$/.test(t) || /^[a-zA-Z0-9][-a-zA-Z0-9_.]*$/.test(t));
|
|
1108
|
+
if (!safe) {
|
|
1109
|
+
process.stderr.write(`sdd-tools: warning: manager.flags contains invalid tokens, ignoring: ${val}\n`);
|
|
1110
|
+
return '';
|
|
1111
|
+
}
|
|
1112
|
+
return val;
|
|
1113
|
+
};
|
|
1114
|
+
const managerFlags = {
|
|
1115
|
+
discuss: sanitizeFlags(config.manager && config.manager.flags && config.manager.flags.discuss),
|
|
1116
|
+
plan: sanitizeFlags(config.manager && config.manager.flags && config.manager.flags.plan),
|
|
1117
|
+
execute: sanitizeFlags(config.manager && config.manager.flags && config.manager.flags.execute),
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1027
1120
|
const result = {
|
|
1028
1121
|
milestone_version: milestone.version,
|
|
1029
1122
|
milestone_name: milestone.name,
|
|
@@ -1037,6 +1130,7 @@ function cmdInitManager(cwd, raw) {
|
|
|
1037
1130
|
project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
|
|
1038
1131
|
roadmap_exists: true,
|
|
1039
1132
|
state_exists: true,
|
|
1133
|
+
manager_flags: managerFlags,
|
|
1040
1134
|
};
|
|
1041
1135
|
|
|
1042
1136
|
output(withProjectRoot(cwd, result), raw);
|