gsdd-cli 0.18.5 → 0.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/LICENSE +21 -21
- package/README.md +609 -608
- package/agents/DISTILLATION.md +421 -421
- package/agents/README.md +62 -62
- package/agents/approach-explorer.md +361 -361
- package/agents/debugger.md +82 -82
- package/agents/executor.md +394 -394
- package/agents/integration-checker.md +318 -318
- package/agents/mapper.md +103 -103
- package/agents/planner.md +313 -313
- package/agents/researcher.md +84 -84
- package/agents/roadmapper.md +296 -296
- package/agents/synthesizer.md +236 -236
- package/agents/verifier.md +337 -337
- package/bin/adapters/agents.mjs +34 -34
- package/bin/adapters/claude.mjs +191 -191
- package/bin/adapters/codex.mjs +85 -85
- package/bin/adapters/index.mjs +20 -20
- package/bin/adapters/opencode.mjs +278 -278
- package/bin/gsdd.mjs +123 -116
- package/bin/lib/cli-utils.mjs +28 -28
- package/bin/lib/evidence-contract.mjs +112 -112
- package/bin/lib/file-ops.mjs +186 -144
- package/bin/lib/health-truth.mjs +181 -178
- package/bin/lib/health.mjs +246 -226
- package/bin/lib/init-flow.mjs +247 -231
- package/bin/lib/init-prompts.mjs +248 -247
- package/bin/lib/init-runtime.mjs +191 -190
- package/bin/lib/init.mjs +17 -17
- package/bin/lib/lifecycle-preflight.mjs +347 -325
- package/bin/lib/lifecycle-state.mjs +351 -267
- package/bin/lib/manifest.mjs +116 -114
- package/bin/lib/models.mjs +411 -411
- package/bin/lib/phase.mjs +360 -358
- package/bin/lib/plan-constants.mjs +30 -30
- package/bin/lib/provenance.mjs +109 -106
- package/bin/lib/rendering.mjs +115 -83
- package/bin/lib/runtime-freshness.mjs +214 -214
- package/bin/lib/templates.mjs +225 -224
- package/bin/lib/workspace-root.mjs +2 -1
- package/distilled/DESIGN.md +2333 -2323
- package/distilled/EVIDENCE-INDEX.md +394 -392
- package/distilled/README.md +196 -193
- package/distilled/SKILL.md +86 -85
- package/distilled/templates/agents.block.md +21 -21
- package/distilled/templates/agents.md +6 -6
- package/distilled/templates/approach.md +232 -232
- package/distilled/templates/auth-matrix.md +78 -78
- package/distilled/templates/brownfield-change/CHANGE.md +99 -0
- package/distilled/templates/brownfield-change/HANDOFF.md +38 -0
- package/distilled/templates/brownfield-change/VERIFICATION.md +56 -0
- package/distilled/templates/codebase/architecture.md +110 -110
- package/distilled/templates/codebase/concerns.md +95 -95
- package/distilled/templates/codebase/conventions.md +193 -193
- package/distilled/templates/codebase/stack.md +96 -96
- package/distilled/templates/delegates/approach-explorer.md +25 -25
- package/distilled/templates/delegates/mapper-arch.md +26 -26
- package/distilled/templates/delegates/mapper-concerns.md +27 -27
- package/distilled/templates/delegates/mapper-quality.md +28 -28
- package/distilled/templates/delegates/mapper-tech.md +25 -25
- package/distilled/templates/delegates/plan-checker.md +68 -68
- package/distilled/templates/delegates/researcher-architecture.md +30 -30
- package/distilled/templates/delegates/researcher-features.md +30 -30
- package/distilled/templates/delegates/researcher-pitfalls.md +30 -30
- package/distilled/templates/delegates/researcher-stack.md +30 -30
- package/distilled/templates/delegates/researcher-synthesizer.md +31 -31
- package/distilled/templates/research/architecture.md +57 -57
- package/distilled/templates/research/features.md +23 -23
- package/distilled/templates/research/pitfalls.md +46 -46
- package/distilled/templates/research/stack.md +45 -45
- package/distilled/templates/research/summary.md +67 -67
- package/distilled/templates/roadmap.md +74 -62
- package/distilled/templates/spec.md +110 -110
- package/distilled/workflows/audit-milestone.md +275 -271
- package/distilled/workflows/complete-milestone.md +336 -332
- package/distilled/workflows/execute.md +454 -449
- package/distilled/workflows/map-codebase.md +253 -253
- package/distilled/workflows/new-milestone.md +242 -238
- package/distilled/workflows/new-project.md +398 -398
- package/distilled/workflows/pause.md +160 -156
- package/distilled/workflows/plan-milestone-gaps.md +183 -183
- package/distilled/workflows/plan.md +451 -447
- package/distilled/workflows/progress.md +227 -223
- package/distilled/workflows/quick.md +351 -347
- package/distilled/workflows/resume.md +220 -212
- package/distilled/workflows/verify-work.md +260 -260
- package/distilled/workflows/verify.md +431 -429
- package/docs/BROWNFIELD-PROOF.md +95 -95
- package/docs/RUNTIME-SUPPORT.md +80 -69
- package/docs/USER-GUIDE.md +394 -386
- package/docs/VERIFICATION-DISCIPLINE.md +59 -59
- package/docs/claude/context-monitor.md +98 -98
- package/docs/proof/consumer-node-cli/README.md +37 -37
- package/docs/proof/consumer-node-cli/ROADMAP.md +14 -14
- package/docs/proof/consumer-node-cli/SPEC.md +17 -17
- package/docs/proof/consumer-node-cli/brief.md +9 -9
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-PLAN.md +34 -34
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-SUMMARY.md +10 -10
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-VERIFICATION.md +30 -30
- package/package.json +62 -61
package/bin/adapters/agents.mjs
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
|
|
4
|
-
function createRootAgentsAdapter({ cwd, renderAgentsBoundedBlock, renderAgentsFileContent, upsertBoundedBlock }, name = 'agents') {
|
|
5
|
-
return {
|
|
6
|
-
id: 'agents',
|
|
7
|
-
name,
|
|
8
|
-
kind: 'governance_only',
|
|
9
|
-
subagentFiles: [],
|
|
10
|
-
detect() {
|
|
11
|
-
return false;
|
|
12
|
-
},
|
|
13
|
-
isInstalled() {
|
|
14
|
-
return existsSync(join(cwd, 'AGENTS.md'));
|
|
15
|
-
},
|
|
16
|
-
generate() {
|
|
17
|
-
const agentsPath = join(cwd, 'AGENTS.md');
|
|
18
|
-
const block = renderAgentsBoundedBlock();
|
|
19
|
-
|
|
20
|
-
if (!existsSync(agentsPath)) {
|
|
21
|
-
writeFileSync(agentsPath, renderAgentsFileContent());
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const existing = readFileSync(agentsPath, 'utf-8');
|
|
26
|
-
writeFileSync(agentsPath, upsertBoundedBlock(existing, block));
|
|
27
|
-
},
|
|
28
|
-
summary(action) {
|
|
29
|
-
return `${action} root AGENTS.md (bounded GSDD block)`;
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export { createRootAgentsAdapter };
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
function createRootAgentsAdapter({ cwd, renderAgentsBoundedBlock, renderAgentsFileContent, upsertBoundedBlock }, name = 'agents') {
|
|
5
|
+
return {
|
|
6
|
+
id: 'agents',
|
|
7
|
+
name,
|
|
8
|
+
kind: 'governance_only',
|
|
9
|
+
subagentFiles: [],
|
|
10
|
+
detect() {
|
|
11
|
+
return false;
|
|
12
|
+
},
|
|
13
|
+
isInstalled() {
|
|
14
|
+
return existsSync(join(cwd, 'AGENTS.md'));
|
|
15
|
+
},
|
|
16
|
+
generate() {
|
|
17
|
+
const agentsPath = join(cwd, 'AGENTS.md');
|
|
18
|
+
const block = renderAgentsBoundedBlock();
|
|
19
|
+
|
|
20
|
+
if (!existsSync(agentsPath)) {
|
|
21
|
+
writeFileSync(agentsPath, renderAgentsFileContent());
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const existing = readFileSync(agentsPath, 'utf-8');
|
|
26
|
+
writeFileSync(agentsPath, upsertBoundedBlock(existing, block));
|
|
27
|
+
},
|
|
28
|
+
summary(action) {
|
|
29
|
+
return `${action} root AGENTS.md (bounded GSDD block)`;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { createRootAgentsAdapter };
|
package/bin/adapters/claude.mjs
CHANGED
|
@@ -1,191 +1,191 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import {
|
|
4
|
-
PLAN_CHECK_DIMENSIONS,
|
|
5
|
-
MAX_CHECKER_CYCLES,
|
|
6
|
-
CHECKER_STATUSES,
|
|
7
|
-
} from '../lib/plan-constants.mjs';
|
|
8
|
-
|
|
9
|
-
const CLAUDE_MODEL_PROFILES = {
|
|
10
|
-
quality: 'opus',
|
|
11
|
-
balanced: 'sonnet',
|
|
12
|
-
budget: 'haiku',
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
function renderClaudeApproachExplorer(delegateContent, modelAlias = 'opus') {
|
|
16
|
-
return `---
|
|
17
|
-
name: gsdd-approach-explorer
|
|
18
|
-
description: Explores implementation approaches for a phase and aligns with the user through structured questioning before planning begins.
|
|
19
|
-
model: ${modelAlias}
|
|
20
|
-
tools: Read, Grep, Glob, WebSearch, WebFetch, Write, AskUserQuestion
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
${delegateContent.trim()}
|
|
24
|
-
`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function renderClaudePlanChecker(delegateContent, modelAlias = 'sonnet') {
|
|
28
|
-
return `---
|
|
29
|
-
name: gsdd-plan-checker
|
|
30
|
-
description: Fresh-context plan checker for GSDD plan drafts. Review-only; never edits plans directly.
|
|
31
|
-
model: ${modelAlias}
|
|
32
|
-
tools: Read, Grep, Glob
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
${delegateContent.trim()}
|
|
36
|
-
`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function renderClaudePlanSkill() {
|
|
40
|
-
return `---
|
|
41
|
-
name: gsdd-plan
|
|
42
|
-
description: Claude-native Phase planning with fresh-context plan checking for GSDD
|
|
43
|
-
argument-hint: [phase-number]
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
You are the Claude-native \`/gsdd-plan\` skill for GSDD phase planning.
|
|
47
|
-
|
|
48
|
-
Portable contract:
|
|
49
|
-
- Read \`.agents/skills/gsdd-plan/SKILL.md\` first. That file remains the canonical vendor-agnostic plan contract.
|
|
50
|
-
- Keep the portable contract honest: it defines the workflow, but it does not by itself prove fresh-context checker orchestration across runtimes.
|
|
51
|
-
- If the portable skill says plan is still a stub, treat that as a portability-status warning for the generic surface, not as a stop signal for this Claude-native adapter path.
|
|
52
|
-
|
|
53
|
-
Native Claude adapter rule:
|
|
54
|
-
- This skill is the canonical Claude-native entry surface for \`/gsdd-plan\`.
|
|
55
|
-
- Stay in the primary Claude context for orchestration. Do NOT fork this skill into a subagent, because the checker must run as its own fresh-context subagent.
|
|
56
|
-
- Use the native \`gsdd-plan-checker\` subagent to regain the fresh-context checker pass that portable markdown alone cannot guarantee.
|
|
57
|
-
- Do NOT claim that other runtimes have the same behavior unless their own adapters explicitly implement and prove it.
|
|
58
|
-
|
|
59
|
-
Execution flow:
|
|
60
|
-
1. Read \`.planning/SPEC.md\`, \`.planning/ROADMAP.md\`, \`.planning/config.json\`, relevant phase research, and any existing phase plan files.
|
|
61
|
-
2. Resolve the target phase from the command arguments. If no phase is provided, choose the first roadmap phase that is not complete.
|
|
62
|
-
3. **Approach exploration** (before planning):
|
|
63
|
-
a. Check \`.planning/config.json\` for \`workflow.discuss\`. If \`false\` or missing, skip to step 4 and report \`reduced_alignment\` in the summary.
|
|
64
|
-
b. Check if \`{phase_dir}/{padded_phase}-APPROACH.md\` exists. If it does, offer the user: "Use existing" / "Update it" / "View it". If "Use existing", load decisions and skip to step 4.
|
|
65
|
-
c. If no APPROACH.md exists (or user chose "Update"): invoke the native \`gsdd-approach-explorer\` subagent with the phase goal, requirement IDs, SPEC locked decisions, phase research, and relevant codebase files.
|
|
66
|
-
d. The explorer runs a GSD-style interactive conversation with the user (gray areas, research, deep-dive questions, assumptions) and writes APPROACH.md.
|
|
67
|
-
e. Load APPROACH.md decisions as locked constraints alongside SPEC.md decisions.
|
|
68
|
-
4. Produce the initial phase plan according to \`.agents/skills/gsdd-plan/SKILL.md\`. Pass APPROACH.md decisions (if any) as locked constraints to the planner.
|
|
69
|
-
5. If \`.planning/config.json\` has \`workflow.planCheck: false\`, stop after planner self-check and explicitly report reduced assurance.
|
|
70
|
-
6. If \`workflow.planCheck: true\`, invoke the native \`gsdd-plan-checker\` subagent with fresh context.
|
|
71
|
-
7. Pass only explicit inputs to the checker:
|
|
72
|
-
- target phase goal and requirement IDs
|
|
73
|
-
- relevant locked decisions / deferred items from \`.planning/SPEC.md\`
|
|
74
|
-
- approach decisions from \`.planning/phases/*-APPROACH.md\` (if exists)
|
|
75
|
-
- relevant phase research file(s)
|
|
76
|
-
- produced \`.planning/phases/*-PLAN.md\` file(s)
|
|
77
|
-
8. Require the checker to return a single JSON object with this shape:
|
|
78
|
-
{
|
|
79
|
-
"status": "passed",
|
|
80
|
-
"summary": "One sentence overall assessment",
|
|
81
|
-
"issues": [
|
|
82
|
-
{
|
|
83
|
-
"dimension": "${PLAN_CHECK_DIMENSIONS.join(' | ')}",
|
|
84
|
-
"severity": "blocker | warning",
|
|
85
|
-
"description": "What is wrong",
|
|
86
|
-
"plan": "01-PLAN",
|
|
87
|
-
"task": "1-02",
|
|
88
|
-
"fix_hint": "Specific revision instruction"
|
|
89
|
-
}
|
|
90
|
-
]
|
|
91
|
-
}
|
|
92
|
-
Status must be either "${CHECKER_STATUSES[0]}" or "${CHECKER_STATUSES[1]}".
|
|
93
|
-
9. If the checker returns \`passed\`, finish and summarize.
|
|
94
|
-
10. If the checker returns \`issues_found\`, revise the existing plan files only where needed, then run the checker again.
|
|
95
|
-
11. Maximum ${MAX_CHECKER_CYCLES} checker cycles total. If blockers remain after cycle ${MAX_CHECKER_CYCLES}, stop and escalate to the user instead of pretending the plan is ready.
|
|
96
|
-
|
|
97
|
-
Return a concise orchestration summary:
|
|
98
|
-
- target phase
|
|
99
|
-
- whether approach exploration ran (and alignment level: full | reduced_alignment | skipped)
|
|
100
|
-
- whether native plan checking ran
|
|
101
|
-
- checker cycle count
|
|
102
|
-
- final result: passed | reduced_assurance | escalated
|
|
103
|
-
|
|
104
|
-
Never return raw checker JSON without summarizing it.
|
|
105
|
-
`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function renderClaudePlanCommand() {
|
|
109
|
-
return `---
|
|
110
|
-
description: Compatibility alias for the Claude-native \`/gsdd-plan\` skill
|
|
111
|
-
argument-hint: [phase-number]
|
|
112
|
-
allowed-tools: Read
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
Read \`.claude/skills/gsdd-plan/SKILL.md\` and execute that skill as the canonical Claude-native \`/gsdd-plan\` entry.
|
|
116
|
-
|
|
117
|
-
Rules:
|
|
118
|
-
- Do NOT duplicate orchestration logic here.
|
|
119
|
-
- Do NOT fork into a separate planning subagent.
|
|
120
|
-
- Preserve the argument value and apply it when resolving the target phase.
|
|
121
|
-
`;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function createClaudeAdapter({ cwd, workflows, renderSkillContent, getDelegateContent, resolveRuntimeAgentModel }) {
|
|
125
|
-
const skillsDir = join(cwd, '.claude', 'skills');
|
|
126
|
-
const commandsDir = join(cwd, '.claude', 'commands');
|
|
127
|
-
const agentsDir = join(cwd, '.claude', 'agents');
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
id: 'claude',
|
|
131
|
-
name: 'claude',
|
|
132
|
-
kind: 'native_capable',
|
|
133
|
-
subagentFiles: [
|
|
134
|
-
'.claude/agents/gsdd-plan-checker.md',
|
|
135
|
-
'.claude/agents/gsdd-approach-explorer.md',
|
|
136
|
-
],
|
|
137
|
-
detect() {
|
|
138
|
-
return existsSync(join(cwd, 'CLAUDE.md')) || existsSync(join(cwd, '.claude'));
|
|
139
|
-
},
|
|
140
|
-
isInstalled() {
|
|
141
|
-
return existsSync(skillsDir) || existsSync(commandsDir) || existsSync(agentsDir);
|
|
142
|
-
},
|
|
143
|
-
generate() {
|
|
144
|
-
const checkerModelAlias = resolveRuntimeAgentModel({
|
|
145
|
-
cwd,
|
|
146
|
-
runtime: 'claude',
|
|
147
|
-
agentId: 'plan-checker',
|
|
148
|
-
profileMap: CLAUDE_MODEL_PROFILES,
|
|
149
|
-
});
|
|
150
|
-
const explorerModelAlias = resolveRuntimeAgentModel({
|
|
151
|
-
cwd,
|
|
152
|
-
runtime: 'claude',
|
|
153
|
-
agentId: 'approach-explorer',
|
|
154
|
-
profileMap: CLAUDE_MODEL_PROFILES,
|
|
155
|
-
});
|
|
156
|
-
for (const workflow of workflows) {
|
|
157
|
-
const dir = join(skillsDir, workflow.name);
|
|
158
|
-
mkdirSync(dir, { recursive: true });
|
|
159
|
-
const content = workflow.name === 'gsdd-plan'
|
|
160
|
-
? renderClaudePlanSkill()
|
|
161
|
-
: renderSkillContent(workflow);
|
|
162
|
-
writeFileSync(join(dir, 'SKILL.md'), content);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
mkdirSync(commandsDir, { recursive: true });
|
|
166
|
-
writeFileSync(join(commandsDir, 'gsdd-plan.md'), renderClaudePlanCommand());
|
|
167
|
-
|
|
168
|
-
mkdirSync(agentsDir, { recursive: true });
|
|
169
|
-
writeFileSync(
|
|
170
|
-
join(agentsDir, 'gsdd-plan-checker.md'),
|
|
171
|
-
renderClaudePlanChecker(getDelegateContent('plan-checker.md'), checkerModelAlias)
|
|
172
|
-
);
|
|
173
|
-
writeFileSync(
|
|
174
|
-
join(agentsDir, 'gsdd-approach-explorer.md'),
|
|
175
|
-
renderClaudeApproachExplorer(getDelegateContent('approach-explorer.md'), explorerModelAlias)
|
|
176
|
-
);
|
|
177
|
-
},
|
|
178
|
-
summary(action) {
|
|
179
|
-
return `${action} Claude Code skills (.claude/skills/gsdd-*), native commands (.claude/commands/gsdd-*.md), and native agents (.claude/agents/gsdd-*.md)`;
|
|
180
|
-
},
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export {
|
|
185
|
-
createClaudeAdapter,
|
|
186
|
-
CLAUDE_MODEL_PROFILES,
|
|
187
|
-
renderClaudeApproachExplorer,
|
|
188
|
-
renderClaudePlanChecker,
|
|
189
|
-
renderClaudePlanCommand,
|
|
190
|
-
renderClaudePlanSkill,
|
|
191
|
-
};
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import {
|
|
4
|
+
PLAN_CHECK_DIMENSIONS,
|
|
5
|
+
MAX_CHECKER_CYCLES,
|
|
6
|
+
CHECKER_STATUSES,
|
|
7
|
+
} from '../lib/plan-constants.mjs';
|
|
8
|
+
|
|
9
|
+
const CLAUDE_MODEL_PROFILES = {
|
|
10
|
+
quality: 'opus',
|
|
11
|
+
balanced: 'sonnet',
|
|
12
|
+
budget: 'haiku',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function renderClaudeApproachExplorer(delegateContent, modelAlias = 'opus') {
|
|
16
|
+
return `---
|
|
17
|
+
name: gsdd-approach-explorer
|
|
18
|
+
description: Explores implementation approaches for a phase and aligns with the user through structured questioning before planning begins.
|
|
19
|
+
model: ${modelAlias}
|
|
20
|
+
tools: Read, Grep, Glob, WebSearch, WebFetch, Write, AskUserQuestion
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
${delegateContent.trim()}
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function renderClaudePlanChecker(delegateContent, modelAlias = 'sonnet') {
|
|
28
|
+
return `---
|
|
29
|
+
name: gsdd-plan-checker
|
|
30
|
+
description: Fresh-context plan checker for GSDD plan drafts. Review-only; never edits plans directly.
|
|
31
|
+
model: ${modelAlias}
|
|
32
|
+
tools: Read, Grep, Glob
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
${delegateContent.trim()}
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function renderClaudePlanSkill() {
|
|
40
|
+
return `---
|
|
41
|
+
name: gsdd-plan
|
|
42
|
+
description: Claude-native Phase planning with fresh-context plan checking for GSDD
|
|
43
|
+
argument-hint: [phase-number]
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
You are the Claude-native \`/gsdd-plan\` skill for GSDD phase planning.
|
|
47
|
+
|
|
48
|
+
Portable contract:
|
|
49
|
+
- Read \`.agents/skills/gsdd-plan/SKILL.md\` first. That file remains the canonical vendor-agnostic plan contract.
|
|
50
|
+
- Keep the portable contract honest: it defines the workflow, but it does not by itself prove fresh-context checker orchestration across runtimes.
|
|
51
|
+
- If the portable skill says plan is still a stub, treat that as a portability-status warning for the generic surface, not as a stop signal for this Claude-native adapter path.
|
|
52
|
+
|
|
53
|
+
Native Claude adapter rule:
|
|
54
|
+
- This skill is the canonical Claude-native entry surface for \`/gsdd-plan\`.
|
|
55
|
+
- Stay in the primary Claude context for orchestration. Do NOT fork this skill into a subagent, because the checker must run as its own fresh-context subagent.
|
|
56
|
+
- Use the native \`gsdd-plan-checker\` subagent to regain the fresh-context checker pass that portable markdown alone cannot guarantee.
|
|
57
|
+
- Do NOT claim that other runtimes have the same behavior unless their own adapters explicitly implement and prove it.
|
|
58
|
+
|
|
59
|
+
Execution flow:
|
|
60
|
+
1. Read \`.planning/SPEC.md\`, \`.planning/ROADMAP.md\`, \`.planning/config.json\`, relevant phase research, and any existing phase plan files.
|
|
61
|
+
2. Resolve the target phase from the command arguments. If no phase is provided, choose the first roadmap phase that is not complete.
|
|
62
|
+
3. **Approach exploration** (before planning):
|
|
63
|
+
a. Check \`.planning/config.json\` for \`workflow.discuss\`. If \`false\` or missing, skip to step 4 and report \`reduced_alignment\` in the summary.
|
|
64
|
+
b. Check if \`{phase_dir}/{padded_phase}-APPROACH.md\` exists. If it does, offer the user: "Use existing" / "Update it" / "View it". If "Use existing", load decisions and skip to step 4.
|
|
65
|
+
c. If no APPROACH.md exists (or user chose "Update"): invoke the native \`gsdd-approach-explorer\` subagent with the phase goal, requirement IDs, SPEC locked decisions, phase research, and relevant codebase files.
|
|
66
|
+
d. The explorer runs a GSD-style interactive conversation with the user (gray areas, research, deep-dive questions, assumptions) and writes APPROACH.md.
|
|
67
|
+
e. Load APPROACH.md decisions as locked constraints alongside SPEC.md decisions.
|
|
68
|
+
4. Produce the initial phase plan according to \`.agents/skills/gsdd-plan/SKILL.md\`. Pass APPROACH.md decisions (if any) as locked constraints to the planner.
|
|
69
|
+
5. If \`.planning/config.json\` has \`workflow.planCheck: false\`, stop after planner self-check and explicitly report reduced assurance.
|
|
70
|
+
6. If \`workflow.planCheck: true\`, invoke the native \`gsdd-plan-checker\` subagent with fresh context.
|
|
71
|
+
7. Pass only explicit inputs to the checker:
|
|
72
|
+
- target phase goal and requirement IDs
|
|
73
|
+
- relevant locked decisions / deferred items from \`.planning/SPEC.md\`
|
|
74
|
+
- approach decisions from \`.planning/phases/*-APPROACH.md\` (if exists)
|
|
75
|
+
- relevant phase research file(s)
|
|
76
|
+
- produced \`.planning/phases/*-PLAN.md\` file(s)
|
|
77
|
+
8. Require the checker to return a single JSON object with this shape:
|
|
78
|
+
{
|
|
79
|
+
"status": "passed",
|
|
80
|
+
"summary": "One sentence overall assessment",
|
|
81
|
+
"issues": [
|
|
82
|
+
{
|
|
83
|
+
"dimension": "${PLAN_CHECK_DIMENSIONS.join(' | ')}",
|
|
84
|
+
"severity": "blocker | warning",
|
|
85
|
+
"description": "What is wrong",
|
|
86
|
+
"plan": "01-PLAN",
|
|
87
|
+
"task": "1-02",
|
|
88
|
+
"fix_hint": "Specific revision instruction"
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
Status must be either "${CHECKER_STATUSES[0]}" or "${CHECKER_STATUSES[1]}".
|
|
93
|
+
9. If the checker returns \`passed\`, finish and summarize.
|
|
94
|
+
10. If the checker returns \`issues_found\`, revise the existing plan files only where needed, then run the checker again.
|
|
95
|
+
11. Maximum ${MAX_CHECKER_CYCLES} checker cycles total. If blockers remain after cycle ${MAX_CHECKER_CYCLES}, stop and escalate to the user instead of pretending the plan is ready.
|
|
96
|
+
|
|
97
|
+
Return a concise orchestration summary:
|
|
98
|
+
- target phase
|
|
99
|
+
- whether approach exploration ran (and alignment level: full | reduced_alignment | skipped)
|
|
100
|
+
- whether native plan checking ran
|
|
101
|
+
- checker cycle count
|
|
102
|
+
- final result: passed | reduced_assurance | escalated
|
|
103
|
+
|
|
104
|
+
Never return raw checker JSON without summarizing it.
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function renderClaudePlanCommand() {
|
|
109
|
+
return `---
|
|
110
|
+
description: Compatibility alias for the Claude-native \`/gsdd-plan\` skill
|
|
111
|
+
argument-hint: [phase-number]
|
|
112
|
+
allowed-tools: Read
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
Read \`.claude/skills/gsdd-plan/SKILL.md\` and execute that skill as the canonical Claude-native \`/gsdd-plan\` entry.
|
|
116
|
+
|
|
117
|
+
Rules:
|
|
118
|
+
- Do NOT duplicate orchestration logic here.
|
|
119
|
+
- Do NOT fork into a separate planning subagent.
|
|
120
|
+
- Preserve the argument value and apply it when resolving the target phase.
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function createClaudeAdapter({ cwd, workflows, renderSkillContent, getDelegateContent, resolveRuntimeAgentModel }) {
|
|
125
|
+
const skillsDir = join(cwd, '.claude', 'skills');
|
|
126
|
+
const commandsDir = join(cwd, '.claude', 'commands');
|
|
127
|
+
const agentsDir = join(cwd, '.claude', 'agents');
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
id: 'claude',
|
|
131
|
+
name: 'claude',
|
|
132
|
+
kind: 'native_capable',
|
|
133
|
+
subagentFiles: [
|
|
134
|
+
'.claude/agents/gsdd-plan-checker.md',
|
|
135
|
+
'.claude/agents/gsdd-approach-explorer.md',
|
|
136
|
+
],
|
|
137
|
+
detect() {
|
|
138
|
+
return existsSync(join(cwd, 'CLAUDE.md')) || existsSync(join(cwd, '.claude'));
|
|
139
|
+
},
|
|
140
|
+
isInstalled() {
|
|
141
|
+
return existsSync(skillsDir) || existsSync(commandsDir) || existsSync(agentsDir);
|
|
142
|
+
},
|
|
143
|
+
generate() {
|
|
144
|
+
const checkerModelAlias = resolveRuntimeAgentModel({
|
|
145
|
+
cwd,
|
|
146
|
+
runtime: 'claude',
|
|
147
|
+
agentId: 'plan-checker',
|
|
148
|
+
profileMap: CLAUDE_MODEL_PROFILES,
|
|
149
|
+
});
|
|
150
|
+
const explorerModelAlias = resolveRuntimeAgentModel({
|
|
151
|
+
cwd,
|
|
152
|
+
runtime: 'claude',
|
|
153
|
+
agentId: 'approach-explorer',
|
|
154
|
+
profileMap: CLAUDE_MODEL_PROFILES,
|
|
155
|
+
});
|
|
156
|
+
for (const workflow of workflows) {
|
|
157
|
+
const dir = join(skillsDir, workflow.name);
|
|
158
|
+
mkdirSync(dir, { recursive: true });
|
|
159
|
+
const content = workflow.name === 'gsdd-plan'
|
|
160
|
+
? renderClaudePlanSkill()
|
|
161
|
+
: renderSkillContent(workflow);
|
|
162
|
+
writeFileSync(join(dir, 'SKILL.md'), content);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
mkdirSync(commandsDir, { recursive: true });
|
|
166
|
+
writeFileSync(join(commandsDir, 'gsdd-plan.md'), renderClaudePlanCommand());
|
|
167
|
+
|
|
168
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
169
|
+
writeFileSync(
|
|
170
|
+
join(agentsDir, 'gsdd-plan-checker.md'),
|
|
171
|
+
renderClaudePlanChecker(getDelegateContent('plan-checker.md'), checkerModelAlias)
|
|
172
|
+
);
|
|
173
|
+
writeFileSync(
|
|
174
|
+
join(agentsDir, 'gsdd-approach-explorer.md'),
|
|
175
|
+
renderClaudeApproachExplorer(getDelegateContent('approach-explorer.md'), explorerModelAlias)
|
|
176
|
+
);
|
|
177
|
+
},
|
|
178
|
+
summary(action) {
|
|
179
|
+
return `${action} Claude Code skills (.claude/skills/gsdd-*), native commands (.claude/commands/gsdd-*.md), and native agents (.claude/agents/gsdd-*.md)`;
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
createClaudeAdapter,
|
|
186
|
+
CLAUDE_MODEL_PROFILES,
|
|
187
|
+
renderClaudeApproachExplorer,
|
|
188
|
+
renderClaudePlanChecker,
|
|
189
|
+
renderClaudePlanCommand,
|
|
190
|
+
renderClaudePlanSkill,
|
|
191
|
+
};
|
package/bin/adapters/codex.mjs
CHANGED
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
|
|
4
|
-
function safeTomlString(value) {
|
|
5
|
-
return value.replace(/[\\"]/g, '\\$&').replace(/\n/g, '\\n');
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function renderCodexApproachExplorer(delegateContent, modelId = null) {
|
|
9
|
-
const safe = delegateContent.trim().replaceAll('"""', '"" "');
|
|
10
|
-
const modelLine = modelId ? `model = "${safeTomlString(modelId)}"\n` : '';
|
|
11
|
-
return `name = "gsdd-approach-explorer"
|
|
12
|
-
description = "Explores implementation approaches for a phase and aligns with the user through structured questioning before planning begins."
|
|
13
|
-
model_reasoning_effort = "high"
|
|
14
|
-
${modelLine}
|
|
15
|
-
developer_instructions = """
|
|
16
|
-
${safe}
|
|
17
|
-
"""
|
|
18
|
-
`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function renderCodexPlanChecker(delegateContent, modelId = null) {
|
|
22
|
-
const safe = delegateContent.trim().replaceAll('"""', '"" "');
|
|
23
|
-
const modelLine = modelId ? `model = "${safeTomlString(modelId)}"\n` : '';
|
|
24
|
-
return `name = "gsdd-plan-checker"
|
|
25
|
-
description = "Fresh-context plan checker for GSDD plan drafts. Review-only; never edits plans directly."
|
|
26
|
-
sandbox_mode = "read-only"
|
|
27
|
-
model_reasoning_effort = "high"
|
|
28
|
-
${modelLine}
|
|
29
|
-
developer_instructions = """
|
|
30
|
-
${safe}
|
|
31
|
-
"""
|
|
32
|
-
`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function createCodexAdapter({
|
|
36
|
-
cwd,
|
|
37
|
-
getDelegateContent,
|
|
38
|
-
getRuntimeModelOverride,
|
|
39
|
-
loadProjectModelConfig,
|
|
40
|
-
}) {
|
|
41
|
-
const agentsDir = join(cwd, '.codex', 'agents');
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
id: 'codex',
|
|
45
|
-
name: 'codex',
|
|
46
|
-
kind: 'native_capable',
|
|
47
|
-
subagentFiles: [
|
|
48
|
-
'.codex/agents/gsdd-plan-checker.toml',
|
|
49
|
-
'.codex/agents/gsdd-approach-explorer.toml',
|
|
50
|
-
],
|
|
51
|
-
detect() {
|
|
52
|
-
return existsSync(join(cwd, '.codex'));
|
|
53
|
-
},
|
|
54
|
-
isInstalled() {
|
|
55
|
-
return existsSync(agentsDir);
|
|
56
|
-
},
|
|
57
|
-
generate() {
|
|
58
|
-
const config = loadProjectModelConfig(cwd);
|
|
59
|
-
const checkerModelId = getRuntimeModelOverride(config, 'codex', 'plan-checker');
|
|
60
|
-
const explorerModelId = getRuntimeModelOverride(config, 'codex', 'approach-explorer');
|
|
61
|
-
|
|
62
|
-
mkdirSync(agentsDir, { recursive: true });
|
|
63
|
-
|
|
64
|
-
// Checker agent (read-only reviewer, spawned by the portable skill's orchestration loop)
|
|
65
|
-
writeFileSync(
|
|
66
|
-
join(agentsDir, 'gsdd-plan-checker.toml'),
|
|
67
|
-
renderCodexPlanChecker(getDelegateContent('plan-checker.md'), checkerModelId)
|
|
68
|
-
);
|
|
69
|
-
// Approach explorer agent (interactive, spawned by the portable skill's approach exploration step)
|
|
70
|
-
writeFileSync(
|
|
71
|
-
join(agentsDir, 'gsdd-approach-explorer.toml'),
|
|
72
|
-
renderCodexApproachExplorer(getDelegateContent('approach-explorer.md'), explorerModelId)
|
|
73
|
-
);
|
|
74
|
-
},
|
|
75
|
-
summary(action) {
|
|
76
|
-
return `${action} Codex CLI native agents (.codex/agents/gsdd-plan-checker.toml, .codex/agents/gsdd-approach-explorer.toml)`;
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export {
|
|
82
|
-
createCodexAdapter,
|
|
83
|
-
renderCodexApproachExplorer,
|
|
84
|
-
renderCodexPlanChecker,
|
|
85
|
-
};
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
function safeTomlString(value) {
|
|
5
|
+
return value.replace(/[\\"]/g, '\\$&').replace(/\n/g, '\\n');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function renderCodexApproachExplorer(delegateContent, modelId = null) {
|
|
9
|
+
const safe = delegateContent.trim().replaceAll('"""', '"" "');
|
|
10
|
+
const modelLine = modelId ? `model = "${safeTomlString(modelId)}"\n` : '';
|
|
11
|
+
return `name = "gsdd-approach-explorer"
|
|
12
|
+
description = "Explores implementation approaches for a phase and aligns with the user through structured questioning before planning begins."
|
|
13
|
+
model_reasoning_effort = "high"
|
|
14
|
+
${modelLine}
|
|
15
|
+
developer_instructions = """
|
|
16
|
+
${safe}
|
|
17
|
+
"""
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function renderCodexPlanChecker(delegateContent, modelId = null) {
|
|
22
|
+
const safe = delegateContent.trim().replaceAll('"""', '"" "');
|
|
23
|
+
const modelLine = modelId ? `model = "${safeTomlString(modelId)}"\n` : '';
|
|
24
|
+
return `name = "gsdd-plan-checker"
|
|
25
|
+
description = "Fresh-context plan checker for GSDD plan drafts. Review-only; never edits plans directly."
|
|
26
|
+
sandbox_mode = "read-only"
|
|
27
|
+
model_reasoning_effort = "high"
|
|
28
|
+
${modelLine}
|
|
29
|
+
developer_instructions = """
|
|
30
|
+
${safe}
|
|
31
|
+
"""
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createCodexAdapter({
|
|
36
|
+
cwd,
|
|
37
|
+
getDelegateContent,
|
|
38
|
+
getRuntimeModelOverride,
|
|
39
|
+
loadProjectModelConfig,
|
|
40
|
+
}) {
|
|
41
|
+
const agentsDir = join(cwd, '.codex', 'agents');
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
id: 'codex',
|
|
45
|
+
name: 'codex',
|
|
46
|
+
kind: 'native_capable',
|
|
47
|
+
subagentFiles: [
|
|
48
|
+
'.codex/agents/gsdd-plan-checker.toml',
|
|
49
|
+
'.codex/agents/gsdd-approach-explorer.toml',
|
|
50
|
+
],
|
|
51
|
+
detect() {
|
|
52
|
+
return existsSync(join(cwd, '.codex'));
|
|
53
|
+
},
|
|
54
|
+
isInstalled() {
|
|
55
|
+
return existsSync(agentsDir);
|
|
56
|
+
},
|
|
57
|
+
generate() {
|
|
58
|
+
const config = loadProjectModelConfig(cwd);
|
|
59
|
+
const checkerModelId = getRuntimeModelOverride(config, 'codex', 'plan-checker');
|
|
60
|
+
const explorerModelId = getRuntimeModelOverride(config, 'codex', 'approach-explorer');
|
|
61
|
+
|
|
62
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
63
|
+
|
|
64
|
+
// Checker agent (read-only reviewer, spawned by the portable skill's orchestration loop)
|
|
65
|
+
writeFileSync(
|
|
66
|
+
join(agentsDir, 'gsdd-plan-checker.toml'),
|
|
67
|
+
renderCodexPlanChecker(getDelegateContent('plan-checker.md'), checkerModelId)
|
|
68
|
+
);
|
|
69
|
+
// Approach explorer agent (interactive, spawned by the portable skill's approach exploration step)
|
|
70
|
+
writeFileSync(
|
|
71
|
+
join(agentsDir, 'gsdd-approach-explorer.toml'),
|
|
72
|
+
renderCodexApproachExplorer(getDelegateContent('approach-explorer.md'), explorerModelId)
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
summary(action) {
|
|
76
|
+
return `${action} Codex CLI native agents (.codex/agents/gsdd-plan-checker.toml, .codex/agents/gsdd-approach-explorer.toml)`;
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
createCodexAdapter,
|
|
83
|
+
renderCodexApproachExplorer,
|
|
84
|
+
renderCodexPlanChecker,
|
|
85
|
+
};
|