@bhargavvc/sdd-cc 1.30.0 → 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 +2151 -551
- 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/config.cjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
|
-
const { output, error,
|
|
7
|
+
const { output, error, planningDir, withPlanningLock, CONFIG_DEFAULTS, atomicWriteFileSync } = require('./core.cjs');
|
|
8
8
|
const {
|
|
9
9
|
VALID_PROFILES,
|
|
10
10
|
getAgentToModelMapForProfile,
|
|
@@ -15,16 +15,28 @@ const VALID_CONFIG_KEYS = new Set([
|
|
|
15
15
|
'mode', 'granularity', 'parallelization', 'commit_docs', 'model_profile',
|
|
16
16
|
'search_gitignored', 'brave_search', 'firecrawl', 'exa_search',
|
|
17
17
|
'workflow.research', 'workflow.plan_check', 'workflow.verifier',
|
|
18
|
-
'workflow.nyquist_validation', 'workflow.ui_phase', 'workflow.ui_safety_gate',
|
|
18
|
+
'workflow.nyquist_validation', 'workflow.ai_integration_phase', 'workflow.ui_phase', 'workflow.ui_safety_gate',
|
|
19
19
|
'workflow.auto_advance', 'workflow.node_repair', 'workflow.node_repair_budget',
|
|
20
20
|
'workflow.text_mode',
|
|
21
21
|
'workflow.research_before_questions',
|
|
22
22
|
'workflow.discuss_mode',
|
|
23
23
|
'workflow.skip_discuss',
|
|
24
24
|
'workflow._auto_chain_active',
|
|
25
|
-
'
|
|
25
|
+
'workflow.use_worktrees',
|
|
26
|
+
'workflow.code_review',
|
|
27
|
+
'workflow.code_review_depth',
|
|
28
|
+
'git.branching_strategy', 'git.base_branch', 'git.phase_branch_template', 'git.milestone_branch_template', 'git.quick_branch_template',
|
|
26
29
|
'planning.commit_docs', 'planning.search_gitignored',
|
|
30
|
+
'workflow.subagent_timeout',
|
|
27
31
|
'hooks.context_warnings',
|
|
32
|
+
'features.thinking_partner',
|
|
33
|
+
'context',
|
|
34
|
+
'features.global_learnings',
|
|
35
|
+
'learnings.max_inject',
|
|
36
|
+
'project_code', 'phase_naming',
|
|
37
|
+
'manager.flags.discuss', 'manager.flags.plan', 'manager.flags.execute',
|
|
38
|
+
'response_language',
|
|
39
|
+
'intel.enabled',
|
|
28
40
|
]);
|
|
29
41
|
|
|
30
42
|
/**
|
|
@@ -36,6 +48,12 @@ function isValidConfigKey(keyPath) {
|
|
|
36
48
|
if (VALID_CONFIG_KEYS.has(keyPath)) return true;
|
|
37
49
|
// Allow agent_skills.<agent-type> with any agent type string
|
|
38
50
|
if (/^agent_skills\.[a-zA-Z0-9_-]+$/.test(keyPath)) return true;
|
|
51
|
+
// Allow review.models.<cli-name> for per-CLI model selection in /sdd-review
|
|
52
|
+
if (/^review\.models\.[a-zA-Z0-9_-]+$/.test(keyPath)) return true;
|
|
53
|
+
// Allow features.<feature_name> — dynamic namespace for feature flags.
|
|
54
|
+
// Intentionally open-ended so new flags (e.g., features.global_learnings) work
|
|
55
|
+
// without updating VALID_CONFIG_KEYS each time.
|
|
56
|
+
if (/^features\.[a-zA-Z0-9_]+$/.test(keyPath)) return true;
|
|
39
57
|
return false;
|
|
40
58
|
}
|
|
41
59
|
|
|
@@ -45,6 +63,11 @@ const CONFIG_KEY_SUGGESTIONS = {
|
|
|
45
63
|
'nyquist.validation_enabled': 'workflow.nyquist_validation',
|
|
46
64
|
'hooks.research_questions': 'workflow.research_before_questions',
|
|
47
65
|
'workflow.research_questions': 'workflow.research_before_questions',
|
|
66
|
+
'workflow.codereview': 'workflow.code_review',
|
|
67
|
+
'workflow.review': 'workflow.code_review',
|
|
68
|
+
'workflow.code_review_level': 'workflow.code_review_depth',
|
|
69
|
+
'workflow.review_depth': 'workflow.code_review_depth',
|
|
70
|
+
'review.model': 'review.models.<cli-name>',
|
|
48
71
|
};
|
|
49
72
|
|
|
50
73
|
function validateKnownConfigKeyPath(keyPath) {
|
|
@@ -60,7 +83,7 @@ function validateKnownConfigKeyPath(keyPath) {
|
|
|
60
83
|
* Merges (increasing priority):
|
|
61
84
|
* 1. Hardcoded defaults — every key that loadConfig() resolves, plus mode/granularity
|
|
62
85
|
* 2. User-level defaults from ~/.sdd/defaults.json (if present)
|
|
63
|
-
* 3. userChoices — the settings the user explicitly selected during /sdd
|
|
86
|
+
* 3. userChoices — the settings the user explicitly selected during /sdd-new-project
|
|
64
87
|
*
|
|
65
88
|
* Uses the canonical `git` namespace for branching keys (consistent with VALID_CONFIG_KEYS
|
|
66
89
|
* and the settings workflow). loadConfig() handles both flat and nested formats, so this
|
|
@@ -101,18 +124,18 @@ function buildNewProjectConfig(userChoices) {
|
|
|
101
124
|
}
|
|
102
125
|
|
|
103
126
|
const hardcoded = {
|
|
104
|
-
model_profile:
|
|
105
|
-
commit_docs:
|
|
106
|
-
parallelization:
|
|
107
|
-
search_gitignored:
|
|
127
|
+
model_profile: CONFIG_DEFAULTS.model_profile,
|
|
128
|
+
commit_docs: CONFIG_DEFAULTS.commit_docs,
|
|
129
|
+
parallelization: CONFIG_DEFAULTS.parallelization,
|
|
130
|
+
search_gitignored: CONFIG_DEFAULTS.search_gitignored,
|
|
108
131
|
brave_search: hasBraveSearch,
|
|
109
132
|
firecrawl: hasFirecrawl,
|
|
110
133
|
exa_search: hasExaSearch,
|
|
111
134
|
git: {
|
|
112
|
-
branching_strategy:
|
|
113
|
-
phase_branch_template:
|
|
114
|
-
milestone_branch_template:
|
|
115
|
-
quick_branch_template:
|
|
135
|
+
branching_strategy: CONFIG_DEFAULTS.branching_strategy,
|
|
136
|
+
phase_branch_template: CONFIG_DEFAULTS.phase_branch_template,
|
|
137
|
+
milestone_branch_template: CONFIG_DEFAULTS.milestone_branch_template,
|
|
138
|
+
quick_branch_template: CONFIG_DEFAULTS.quick_branch_template,
|
|
116
139
|
},
|
|
117
140
|
workflow: {
|
|
118
141
|
research: true,
|
|
@@ -124,14 +147,19 @@ function buildNewProjectConfig(userChoices) {
|
|
|
124
147
|
node_repair_budget: 2,
|
|
125
148
|
ui_phase: true,
|
|
126
149
|
ui_safety_gate: true,
|
|
150
|
+
ai_integration_phase: true,
|
|
127
151
|
text_mode: false,
|
|
128
152
|
research_before_questions: false,
|
|
129
153
|
discuss_mode: 'discuss',
|
|
130
154
|
skip_discuss: false,
|
|
155
|
+
code_review: true,
|
|
156
|
+
code_review_depth: 'standard',
|
|
131
157
|
},
|
|
132
158
|
hooks: {
|
|
133
159
|
context_warnings: true,
|
|
134
160
|
},
|
|
161
|
+
project_code: null,
|
|
162
|
+
phase_naming: 'sequential',
|
|
135
163
|
agent_skills: {},
|
|
136
164
|
};
|
|
137
165
|
|
|
@@ -167,13 +195,13 @@ function buildNewProjectConfig(userChoices) {
|
|
|
167
195
|
* Command: create a fully-materialized .planning/config.json for a new project.
|
|
168
196
|
*
|
|
169
197
|
* Accepts user-chosen settings as a JSON string (the keys the user explicitly
|
|
170
|
-
* configured during /sdd
|
|
198
|
+
* configured during /sdd-new-project). All remaining keys are filled from
|
|
171
199
|
* hardcoded defaults and optional ~/.sdd/defaults.json.
|
|
172
200
|
*
|
|
173
201
|
* Idempotent: if config.json already exists, returns { created: false }.
|
|
174
202
|
*/
|
|
175
203
|
function cmdConfigNewProject(cwd, choicesJson, raw) {
|
|
176
|
-
const planningBase =
|
|
204
|
+
const planningBase = planningDir(cwd);
|
|
177
205
|
const configPath = path.join(planningBase, 'config.json');
|
|
178
206
|
|
|
179
207
|
// Idempotent: don't overwrite existing config
|
|
@@ -204,7 +232,7 @@ function cmdConfigNewProject(cwd, choicesJson, raw) {
|
|
|
204
232
|
const config = buildNewProjectConfig(userChoices);
|
|
205
233
|
|
|
206
234
|
try {
|
|
207
|
-
|
|
235
|
+
atomicWriteFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
208
236
|
output({ created: true, path: '.planning/config.json' }, raw, 'created');
|
|
209
237
|
} catch (err) {
|
|
210
238
|
error('Failed to write config.json: ' + err.message);
|
|
@@ -218,7 +246,7 @@ function cmdConfigNewProject(cwd, choicesJson, raw) {
|
|
|
218
246
|
* the happy path. But note that `error()` will still `exit(1)` out of the process.
|
|
219
247
|
*/
|
|
220
248
|
function ensureConfigFile(cwd) {
|
|
221
|
-
const planningBase =
|
|
249
|
+
const planningBase = planningDir(cwd);
|
|
222
250
|
const configPath = path.join(planningBase, 'config.json');
|
|
223
251
|
|
|
224
252
|
// Ensure .planning directory exists
|
|
@@ -238,7 +266,7 @@ function ensureConfigFile(cwd) {
|
|
|
238
266
|
const config = buildNewProjectConfig({});
|
|
239
267
|
|
|
240
268
|
try {
|
|
241
|
-
|
|
269
|
+
atomicWriteFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
242
270
|
return { created: true, path: '.planning/config.json' };
|
|
243
271
|
} catch (err) {
|
|
244
272
|
error('Failed to create config.json: ' + err.message);
|
|
@@ -268,38 +296,40 @@ function cmdConfigEnsureSection(cwd, raw) {
|
|
|
268
296
|
* the happy path. But note that `error()` will still `exit(1)` out of the process.
|
|
269
297
|
*/
|
|
270
298
|
function setConfigValue(cwd, keyPath, parsedValue) {
|
|
271
|
-
const configPath = path.join(
|
|
299
|
+
const configPath = path.join(planningDir(cwd), 'config.json');
|
|
272
300
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
301
|
+
return withPlanningLock(cwd, () => {
|
|
302
|
+
// Load existing config or start with empty object
|
|
303
|
+
let config = {};
|
|
304
|
+
try {
|
|
305
|
+
if (fs.existsSync(configPath)) {
|
|
306
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
307
|
+
}
|
|
308
|
+
} catch (err) {
|
|
309
|
+
error('Failed to read config.json: ' + err.message);
|
|
278
310
|
}
|
|
279
|
-
} catch (err) {
|
|
280
|
-
error('Failed to read config.json: ' + err.message);
|
|
281
|
-
}
|
|
282
311
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
312
|
+
// Set nested value using dot notation (e.g., "workflow.research")
|
|
313
|
+
const keys = keyPath.split('.');
|
|
314
|
+
let current = config;
|
|
315
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
316
|
+
const key = keys[i];
|
|
317
|
+
if (current[key] === undefined || typeof current[key] !== 'object') {
|
|
318
|
+
current[key] = {};
|
|
319
|
+
}
|
|
320
|
+
current = current[key];
|
|
290
321
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const previousValue = current[keys[keys.length - 1]]; // Capture previous value before overwriting
|
|
294
|
-
current[keys[keys.length - 1]] = parsedValue;
|
|
322
|
+
const previousValue = current[keys[keys.length - 1]]; // Capture previous value before overwriting
|
|
323
|
+
current[keys[keys.length - 1]] = parsedValue;
|
|
295
324
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
325
|
+
// Write back
|
|
326
|
+
try {
|
|
327
|
+
atomicWriteFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
328
|
+
return { updated: true, key: keyPath, value: parsedValue, previousValue };
|
|
329
|
+
} catch (err) {
|
|
330
|
+
error('Failed to write config.json: ' + err.message);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
303
333
|
}
|
|
304
334
|
|
|
305
335
|
/**
|
|
@@ -317,7 +347,7 @@ function cmdConfigSet(cwd, keyPath, value, raw) {
|
|
|
317
347
|
validateKnownConfigKeyPath(keyPath);
|
|
318
348
|
|
|
319
349
|
if (!isValidConfigKey(keyPath)) {
|
|
320
|
-
error(`Unknown config key: "${keyPath}". Valid keys: ${[...VALID_CONFIG_KEYS].sort().join(', ')}, agent_skills.<agent-type>`);
|
|
350
|
+
error(`Unknown config key: "${keyPath}". Valid keys: ${[...VALID_CONFIG_KEYS].sort().join(', ')}, agent_skills.<agent-type>, features.<feature_name>`);
|
|
321
351
|
}
|
|
322
352
|
|
|
323
353
|
// Parse value (handle booleans, numbers, and JSON arrays/objects)
|
|
@@ -329,21 +359,30 @@ function cmdConfigSet(cwd, keyPath, value, raw) {
|
|
|
329
359
|
try { parsedValue = JSON.parse(value); } catch { /* keep as string */ }
|
|
330
360
|
}
|
|
331
361
|
|
|
362
|
+
const VALID_CONTEXT_VALUES = ['dev', 'research', 'review'];
|
|
363
|
+
if (keyPath === 'context' && !VALID_CONTEXT_VALUES.includes(String(parsedValue))) {
|
|
364
|
+
error(`Invalid context value '${value}'. Valid values: ${VALID_CONTEXT_VALUES.join(', ')}`);
|
|
365
|
+
}
|
|
366
|
+
|
|
332
367
|
const setConfigValueResult = setConfigValue(cwd, keyPath, parsedValue);
|
|
333
368
|
output(setConfigValueResult, raw, `${keyPath}=${parsedValue}`);
|
|
334
369
|
}
|
|
335
370
|
|
|
336
|
-
function cmdConfigGet(cwd, keyPath, raw) {
|
|
337
|
-
const configPath = path.join(
|
|
371
|
+
function cmdConfigGet(cwd, keyPath, raw, defaultValue) {
|
|
372
|
+
const configPath = path.join(planningDir(cwd), 'config.json');
|
|
373
|
+
const hasDefault = defaultValue !== undefined;
|
|
338
374
|
|
|
339
375
|
if (!keyPath) {
|
|
340
|
-
error('Usage: config-get <key.path>');
|
|
376
|
+
error('Usage: config-get <key.path> [--default <value>]');
|
|
341
377
|
}
|
|
342
378
|
|
|
343
379
|
let config = {};
|
|
344
380
|
try {
|
|
345
381
|
if (fs.existsSync(configPath)) {
|
|
346
382
|
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
383
|
+
} else if (hasDefault) {
|
|
384
|
+
output(defaultValue, raw, String(defaultValue));
|
|
385
|
+
return;
|
|
347
386
|
} else {
|
|
348
387
|
error('No config.json found at ' + configPath);
|
|
349
388
|
}
|
|
@@ -357,12 +396,14 @@ function cmdConfigGet(cwd, keyPath, raw) {
|
|
|
357
396
|
let current = config;
|
|
358
397
|
for (const key of keys) {
|
|
359
398
|
if (current === undefined || current === null || typeof current !== 'object') {
|
|
399
|
+
if (hasDefault) { output(defaultValue, raw, String(defaultValue)); return; }
|
|
360
400
|
error(`Key not found: ${keyPath}`);
|
|
361
401
|
}
|
|
362
402
|
current = current[key];
|
|
363
403
|
}
|
|
364
404
|
|
|
365
405
|
if (current === undefined) {
|
|
406
|
+
if (hasDefault) { output(defaultValue, raw, String(defaultValue)); return; }
|
|
366
407
|
error(`Key not found: ${keyPath}`);
|
|
367
408
|
}
|
|
368
409
|
|
|
@@ -434,6 +475,7 @@ function getCmdConfigSetModelProfileResultMessage(
|
|
|
434
475
|
}
|
|
435
476
|
|
|
436
477
|
module.exports = {
|
|
478
|
+
VALID_CONFIG_KEYS,
|
|
437
479
|
cmdConfigEnsureSection,
|
|
438
480
|
cmdConfigSet,
|
|
439
481
|
cmdConfigGet,
|