gsdd-cli 0.2.0 → 0.3.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/README.md +31 -13
- package/bin/adapters/claude.mjs +1 -1
- package/bin/adapters/opencode.mjs +1 -1
- package/bin/gsdd.mjs +44 -34
- package/bin/lib/init-flow.mjs +220 -0
- package/bin/lib/init-prompts.mjs +308 -0
- package/bin/lib/init-runtime.mjs +224 -0
- package/bin/lib/init.mjs +20 -383
- package/distilled/DESIGN.md +286 -0
- package/distilled/README.md +6 -2
- package/distilled/templates/agents.block.md +4 -2
- package/distilled/templates/delegates/plan-checker.md +5 -1
- package/distilled/workflows/audit-milestone.md +2 -0
- package/distilled/workflows/map-codebase.md +10 -5
- package/distilled/workflows/new-project.md +26 -21
- package/distilled/workflows/pause.md +2 -0
- package/distilled/workflows/plan.md +3 -2
- package/distilled/workflows/quick.md +163 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -48,17 +48,27 @@ This creates:
|
|
|
48
48
|
|
|
49
49
|
1. `.planning/` — durable workspace with templates, role contracts, and config
|
|
50
50
|
2. `.agents/skills/gsdd-*` — portable workflow entrypoints
|
|
51
|
-
3. Tool-specific adapters
|
|
51
|
+
3. Tool-specific adapters you choose in the install wizard (Claude skills/commands/agents, OpenCode commands/agents, Codex agents, optional governance)
|
|
52
52
|
|
|
53
53
|
Then run the new-project workflow to produce `.planning/SPEC.md` and `.planning/ROADMAP.md`.
|
|
54
54
|
|
|
55
|
+
In a terminal, `gsdd init` now opens a guided install wizard:
|
|
56
|
+
|
|
57
|
+
- Step 1: select the runtimes/vendors you want to support
|
|
58
|
+
- Step 2: decide separately whether repo-wide `AGENTS.md` governance is worth installing
|
|
59
|
+
- Step 3: configure planning defaults in the same guided flow
|
|
60
|
+
|
|
61
|
+
Portable `.agents/skills/gsdd-*` skills are always generated. The wizard controls extra native adapters and optional governance, not the portable baseline.
|
|
62
|
+
|
|
55
63
|
### Quickstart (after init)
|
|
56
64
|
|
|
57
65
|
Your tool determines how you invoke workflows:
|
|
58
66
|
|
|
59
|
-
- **Claude Code / OpenCode:** Use slash commands directly — `/gsdd-new-project`, `/gsdd-plan`, etc.
|
|
67
|
+
- **Claude Code / OpenCode / Cursor / Copilot / Gemini:** Use slash commands directly — `/gsdd-new-project`, `/gsdd-plan`, etc.
|
|
60
68
|
- **Codex CLI:** Use skill references — `$gsdd-new-project`, `$gsdd-plan`, etc.
|
|
61
|
-
- **
|
|
69
|
+
- **Other AI tools:** Open `.agents/skills/gsdd-<workflow>/SKILL.md` and follow the instructions.
|
|
70
|
+
|
|
71
|
+
If you generate the root `AGENTS.md` block, it adds GSDD behavioral governance. For Cursor, Copilot, and Gemini, that governance is optional discipline on top of native skill discovery — not the mechanism that makes workflows discoverable.
|
|
62
72
|
|
|
63
73
|
First workflow to run: **new-project** — it asks about your goals, audits the codebase (if brownfield), and produces `.planning/SPEC.md` + `.planning/ROADMAP.md`.
|
|
64
74
|
|
|
@@ -67,11 +77,12 @@ First workflow to run: **new-project** — it asks about your goals, audits the
|
|
|
67
77
|
GSDD generates adapters for whichever tools you use:
|
|
68
78
|
|
|
69
79
|
```bash
|
|
70
|
-
npx gsdd-cli init #
|
|
80
|
+
npx gsdd-cli init # Guided install wizard (detected runtimes preselected)
|
|
71
81
|
npx gsdd-cli init --tools claude # Claude Code: .claude/skills + commands + agents
|
|
72
82
|
npx gsdd-cli init --tools opencode # OpenCode: .opencode/commands + agents
|
|
73
83
|
npx gsdd-cli init --tools codex # Codex CLI: portable gsdd-plan skill + .codex/agents checker
|
|
74
84
|
npx gsdd-cli init --tools agents # Root AGENTS.md fallback
|
|
85
|
+
npx gsdd-cli init --tools cursor # Backward-compatible AGENTS.md governance alias
|
|
75
86
|
npx gsdd-cli init --tools all # All of the above
|
|
76
87
|
```
|
|
77
88
|
|
|
@@ -81,7 +92,8 @@ npx gsdd-cli init --tools all # All of the above
|
|
|
81
92
|
| **Claude Code** | Native | `.claude/skills/`, `.claude/commands/`, `.claude/agents/` — slash commands work immediately |
|
|
82
93
|
| **OpenCode** | Native | `.opencode/commands/`, `.opencode/agents/` — slash commands work immediately |
|
|
83
94
|
| **Codex CLI** | Native | `.codex/agents/gsdd-plan-checker.toml` — skill reference `$gsdd-plan` works immediately |
|
|
84
|
-
| **Cursor / Copilot / Gemini** |
|
|
95
|
+
| **Cursor / Copilot / Gemini** | Skills-native runtime + optional governance | Native slash-command discovery from `.agents/skills/`; optional root `AGENTS.md` block adds behavioral governance |
|
|
96
|
+
| **Other AI tools** | Open standard fallback | Open `.agents/skills/gsdd-*/SKILL.md` directly |
|
|
85
97
|
|
|
86
98
|
### Updating
|
|
87
99
|
|
|
@@ -102,10 +114,13 @@ npx gsdd-cli init --auto --tools claude --brief path/to/PRD.md
|
|
|
102
114
|
|
|
103
115
|
`--auto` skips interactive prompts, uses smart defaults (`autoAdvance: true` in config). `--brief` copies a project document to `.planning/PROJECT_BRIEF.md` for `new-project` to consume.
|
|
104
116
|
|
|
117
|
+
If you already know exactly what to generate, `--tools ...` remains the manual path. The wizard is the primary onboarding UX; flags remain the advanced/headless contract.
|
|
118
|
+
|
|
105
119
|
### Team Use
|
|
106
120
|
|
|
107
121
|
- **Shared state:** Set `commitDocs: true` (default) — `.planning/` is tracked in git. Everyone sees the same spec, roadmap, and phase plans.
|
|
108
122
|
- **Onboarding:** After cloning, run `npx gsdd-cli init` to generate tool-specific adapters. `.planning/` is already tracked — no re-initialization needed.
|
|
123
|
+
- **Governance is explicit:** The wizard asks separately whether to install repo-wide `AGENTS.md` rules, and explains why you may care before writing to the repo root.
|
|
109
124
|
- **Session handoff:** Use `gsdd-pause` / `gsdd-resume` to hand off work. The checkpoint (`.planning/.continue-here.md`) captures context for the next person.
|
|
110
125
|
- **Adapter isolation:** Each developer runs `gsdd init --tools <their-tool>`. Adapter files don't conflict across tools.
|
|
111
126
|
|
|
@@ -192,7 +207,8 @@ When all phases are done, run `gsdd-audit-milestone` to verify:
|
|
|
192
207
|
|
|
193
208
|
- `Claude Code / OpenCode`: `/gsdd-quick`
|
|
194
209
|
- `Codex CLI`: `$gsdd-quick`
|
|
195
|
-
- `Cursor / Copilot / Gemini
|
|
210
|
+
- `Cursor / Copilot / Gemini`: `/gsdd-quick`
|
|
211
|
+
- `Other AI tools`: open `.agents/skills/gsdd-quick/SKILL.md`
|
|
196
212
|
|
|
197
213
|
For sub-hour tasks that don't need the full phase cycle:
|
|
198
214
|
|
|
@@ -231,7 +247,8 @@ Workflows are agent skills or commands, not plain shell utilities. How you invok
|
|
|
231
247
|
| Claude Code | `/gsdd-plan` (slash command, works immediately after init) |
|
|
232
248
|
| OpenCode | `/gsdd-plan` (slash command, works immediately after init) |
|
|
233
249
|
| Codex CLI | `$gsdd-plan` (skill reference, works immediately after init) |
|
|
234
|
-
| Cursor / Copilot / Gemini |
|
|
250
|
+
| Cursor / Copilot / Gemini | `/gsdd-plan` (skills-native slash command). If the root `AGENTS.md` block is present, it adds governance, not workflow discovery. |
|
|
251
|
+
| Other AI tools | Open `.agents/skills/gsdd-plan/SKILL.md` and paste or reference its content. |
|
|
235
252
|
|
|
236
253
|
## CLI Commands
|
|
237
254
|
|
|
@@ -279,14 +296,15 @@ GSDD generates vendor-specific files from vendor-agnostic markdown — it does n
|
|
|
279
296
|
|
|
280
297
|
| Adapter | Kind | Strategy |
|
|
281
298
|
|---------|------|----------|
|
|
282
|
-
| **Claude Code** | `native_capable` | Skill-primary plan surface (stays in main context to spawn checker subagent), thin command alias, native `gsdd-plan-checker` agent |
|
|
283
|
-
| **OpenCode** | `native_capable` | Specialized `/gsdd-plan` command (`subtask: false`), hidden `gsdd-plan-checker` subagent (`mode: subagent`) |
|
|
284
|
-
| **Codex CLI** | `native_capable` | Portable skill as entry surface, `.codex/agents/gsdd-plan-checker.toml` (read-only, high reasoning effort) |
|
|
285
|
-
| **Cursor / Copilot / Gemini** | `governance_only` |
|
|
299
|
+
| **Claude Code** | `native_capable` adapter + skills-native runtime | Skill-primary plan surface (stays in main context to spawn checker subagent), thin command alias, native `gsdd-plan-checker` agent |
|
|
300
|
+
| **OpenCode** | `native_capable` adapter + skills-native runtime | Specialized `/gsdd-plan` command (`subtask: false`), hidden `gsdd-plan-checker` subagent (`mode: subagent`) |
|
|
301
|
+
| **Codex CLI** | `native_capable` adapter + skills-native runtime | Portable skill as entry surface, `.codex/agents/gsdd-plan-checker.toml` (read-only, high reasoning effort) |
|
|
302
|
+
| **Cursor / Copilot / Gemini** | skills-native runtime + `governance_only` adapter | Runtime discovers `.agents/skills/` natively; optional root `AGENTS.md` block adds behavioral governance only |
|
|
303
|
+
| **agents** (`--tools agents`) | `governance_only` adapter | Root `AGENTS.md` block for tools that benefit from governance or need open-standard fallback guidance |
|
|
286
304
|
|
|
287
305
|
All adapters render the plan-checker from a single source (`distilled/templates/delegates/plan-checker.md`). Each adapter shapes the output to its platform's native mechanics, and the portable skill remains the shared workflow source.
|
|
288
306
|
|
|
289
|
-
Cursor, Copilot, and Gemini CLI generate the same root `AGENTS.md` governance block as `--tools agents
|
|
307
|
+
Cursor, Copilot, and Gemini CLI generate the same root `AGENTS.md` governance block as `--tools agents`, but that file is governance only. Those runtimes already discover `.agents/skills/` natively and surface the workflows as slash commands.
|
|
290
308
|
|
|
291
309
|
Model IDs pass through a two-layer injection guard: a regex whitelist (`/^[a-zA-Z0-9._\/:@-]+$/`) at the CLI boundary, plus format-specific escaping (TOML string escaping, triple-quote break prevention) at the adapter layer.
|
|
292
310
|
|
|
@@ -410,7 +428,7 @@ For detailed troubleshooting and recovery procedures, see the [User Guide](docs/
|
|
|
410
428
|
|
|
411
429
|
## Design Decisions
|
|
412
430
|
|
|
413
|
-
GSDD makes
|
|
431
|
+
GSDD makes 36 documented design decisions relative to GSD, each with evidence from source files and external research. See [`distilled/DESIGN.md`](distilled/DESIGN.md) for the full rationale.
|
|
414
432
|
|
|
415
433
|
Key choices:
|
|
416
434
|
- **4-file codebase standard** — drop state that rots (STRUCTURE, INTEGRATIONS, TESTING), keep rules that don't
|
package/bin/adapters/claude.mjs
CHANGED
|
@@ -75,7 +75,7 @@ Execution flow:
|
|
|
75
75
|
"summary": "One sentence overall assessment",
|
|
76
76
|
"issues": [
|
|
77
77
|
{
|
|
78
|
-
"dimension": "requirement_coverage | task_completeness | dependency_correctness | key_link_completeness | scope_sanity | must_have_quality | context_compliance | approach_alignment",
|
|
78
|
+
"dimension": "requirement_coverage | task_completeness | dependency_correctness | key_link_completeness | scope_sanity | must_have_quality | context_compliance | goal_achievement | approach_alignment",
|
|
79
79
|
"severity": "blocker | warning",
|
|
80
80
|
"description": "What is wrong",
|
|
81
81
|
"plan": "01-PLAN",
|
|
@@ -183,7 +183,7 @@ Execution flow:
|
|
|
183
183
|
"summary": "One sentence overall assessment",
|
|
184
184
|
"issues": [
|
|
185
185
|
{
|
|
186
|
-
"dimension": "requirement_coverage | task_completeness | dependency_correctness | key_link_completeness | scope_sanity | must_have_quality | context_compliance | approach_alignment",
|
|
186
|
+
"dimension": "requirement_coverage | task_completeness | dependency_correctness | key_link_completeness | scope_sanity | must_have_quality | context_compliance | goal_achievement | approach_alignment",
|
|
187
187
|
"severity": "blocker | warning",
|
|
188
188
|
"description": "What is wrong",
|
|
189
189
|
"plan": "01-PLAN",
|
package/bin/gsdd.mjs
CHANGED
|
@@ -24,51 +24,61 @@ const __dirname = dirname(__filename);
|
|
|
24
24
|
const DISTILLED_DIR = join(__dirname, '..', 'distilled');
|
|
25
25
|
const AGENTS_DIR = join(__dirname, '..', 'agents');
|
|
26
26
|
const CWD = process.cwd();
|
|
27
|
-
const PLANNING_DIR = join(CWD, '.planning');
|
|
28
27
|
const IS_MAIN = process.argv[1]
|
|
29
28
|
? realpathSync(process.argv[1]) === realpathSync(__filename)
|
|
30
29
|
: false;
|
|
31
30
|
|
|
32
31
|
const [,, command, ...args] = process.argv;
|
|
33
32
|
|
|
33
|
+
function defineWorkflow({ mutatesArtifacts = true, ...workflow }) {
|
|
34
|
+
return {
|
|
35
|
+
...workflow,
|
|
36
|
+
mutatesArtifacts,
|
|
37
|
+
agent: mutatesArtifacts ? 'Code' : 'Plan',
|
|
38
|
+
opencodeType: mutatesArtifacts ? 'edit' : 'plan',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
34
42
|
const WORKFLOWS = [
|
|
35
|
-
{ name: 'gsdd-new-project', workflow: 'new-project.md', description: 'New project - questioning, codebase audit, research, spec, roadmap'
|
|
36
|
-
{ name: 'gsdd-map-codebase', workflow: 'map-codebase.md', description: 'Map or refresh codebase - 4 parallel mappers, staleness check, secrets scan'
|
|
37
|
-
{ name: 'gsdd-plan', workflow: 'plan.md', description: 'Plan a phase - research check, backward planning, task creation'
|
|
38
|
-
{ name: 'gsdd-execute', workflow: 'execute.md', description: 'Execute a phase plan - implement tasks, verify changes, follow repo git conventions'
|
|
39
|
-
{ name: 'gsdd-verify', workflow: 'verify.md', description: 'Verify a completed phase - 3-level checks, anti-pattern scan'
|
|
40
|
-
{ name: 'gsdd-audit-milestone', workflow: 'audit-milestone.md', description: 'Audit a completed milestone - cross-phase integration, requirements coverage, E2E flows'
|
|
41
|
-
{ name: 'gsdd-quick', workflow: 'quick.md', description: 'Quick task - plan and execute a sub-hour task outside the phase cycle'
|
|
42
|
-
{ name: 'gsdd-pause', workflow: 'pause.md', description: 'Pause work - save session context for seamless resumption'
|
|
43
|
-
{ name: 'gsdd-resume', workflow: 'resume.md', description: 'Resume work - restore context and route to next action'
|
|
44
|
-
{ name: 'gsdd-progress', workflow: 'progress.md', description: 'Check progress - show project status and route to next action',
|
|
43
|
+
defineWorkflow({ name: 'gsdd-new-project', workflow: 'new-project.md', description: 'New project - questioning, codebase audit, research, spec, roadmap' }),
|
|
44
|
+
defineWorkflow({ name: 'gsdd-map-codebase', workflow: 'map-codebase.md', description: 'Map or refresh codebase - 4 parallel mappers, staleness check, secrets scan' }),
|
|
45
|
+
defineWorkflow({ name: 'gsdd-plan', workflow: 'plan.md', description: 'Plan a phase - research check, backward planning, task creation' }),
|
|
46
|
+
defineWorkflow({ name: 'gsdd-execute', workflow: 'execute.md', description: 'Execute a phase plan - implement tasks, verify changes, follow repo git conventions' }),
|
|
47
|
+
defineWorkflow({ name: 'gsdd-verify', workflow: 'verify.md', description: 'Verify a completed phase - 3-level checks, anti-pattern scan' }),
|
|
48
|
+
defineWorkflow({ name: 'gsdd-audit-milestone', workflow: 'audit-milestone.md', description: 'Audit a completed milestone - cross-phase integration, requirements coverage, E2E flows' }),
|
|
49
|
+
defineWorkflow({ name: 'gsdd-quick', workflow: 'quick.md', description: 'Quick task - plan and execute a sub-hour task outside the phase cycle' }),
|
|
50
|
+
defineWorkflow({ name: 'gsdd-pause', workflow: 'pause.md', description: 'Pause work - save session context for seamless resumption' }),
|
|
51
|
+
defineWorkflow({ name: 'gsdd-resume', workflow: 'resume.md', description: 'Resume work - restore context and route to next action' }),
|
|
52
|
+
defineWorkflow({ name: 'gsdd-progress', workflow: 'progress.md', description: 'Check progress - show project status and route to next action', mutatesArtifacts: false }),
|
|
45
53
|
];
|
|
46
54
|
|
|
47
55
|
const FRAMEWORK_VERSION = 'v1.2';
|
|
48
56
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
function createCliContext(cwd = process.cwd()) {
|
|
58
|
+
return {
|
|
59
|
+
cwd,
|
|
60
|
+
planningDir: join(cwd, '.planning'),
|
|
61
|
+
distilledDir: DISTILLED_DIR,
|
|
62
|
+
agentsDir: AGENTS_DIR,
|
|
63
|
+
workflows: WORKFLOWS,
|
|
64
|
+
frameworkVersion: FRAMEWORK_VERSION,
|
|
65
|
+
adapters: createAdapterRegistry({
|
|
66
|
+
cwd,
|
|
67
|
+
workflows: WORKFLOWS,
|
|
68
|
+
renderAgentsBoundedBlock,
|
|
69
|
+
renderAgentsFileContent,
|
|
70
|
+
renderOpenCodeCommandContent,
|
|
71
|
+
renderSkillContent,
|
|
72
|
+
upsertBoundedBlock,
|
|
73
|
+
getDelegateContent,
|
|
74
|
+
loadProjectModelConfig,
|
|
75
|
+
getRuntimeModelOverride,
|
|
76
|
+
resolveRuntimeAgentModel,
|
|
77
|
+
}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
62
80
|
|
|
63
|
-
const INIT_CONTEXT =
|
|
64
|
-
cwd: CWD,
|
|
65
|
-
planningDir: PLANNING_DIR,
|
|
66
|
-
distilledDir: DISTILLED_DIR,
|
|
67
|
-
agentsDir: AGENTS_DIR,
|
|
68
|
-
workflows: WORKFLOWS,
|
|
69
|
-
frameworkVersion: FRAMEWORK_VERSION,
|
|
70
|
-
adapters: ADAPTERS,
|
|
71
|
-
};
|
|
81
|
+
const INIT_CONTEXT = createCliContext(CWD);
|
|
72
82
|
|
|
73
83
|
const cmdInit = createCmdInit(INIT_CONTEXT);
|
|
74
84
|
const cmdUpdate = createCmdUpdate(INIT_CONTEXT);
|
|
@@ -99,4 +109,4 @@ if (IS_MAIN) {
|
|
|
99
109
|
await runCli();
|
|
100
110
|
}
|
|
101
111
|
|
|
102
|
-
export { cmdHelp, cmdInit, cmdUpdate, cmdModels, cmdHealth, cmdFindPhase, cmdVerify, cmdScaffold, runCli, FRAMEWORK_VERSION };
|
|
112
|
+
export { cmdHelp, cmdInit, cmdUpdate, cmdModels, cmdHealth, cmdFindPhase, cmdVerify, cmdScaffold, runCli, FRAMEWORK_VERSION, createCliContext };
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, cpSync } from 'fs';
|
|
2
|
+
import { join, isAbsolute } from 'path';
|
|
3
|
+
import { renderSkillContent } from './rendering.mjs';
|
|
4
|
+
import { buildManifest, writeManifest } from './manifest.mjs';
|
|
5
|
+
import { parseFlagValue, parseToolsFlag, parseAutoFlag } from './cli-utils.mjs';
|
|
6
|
+
import { buildDefaultConfig } from './models.mjs';
|
|
7
|
+
import { installProjectTemplates, refreshTemplates } from './templates.mjs';
|
|
8
|
+
import {
|
|
9
|
+
detectPlatforms,
|
|
10
|
+
getAdaptersToUpdate,
|
|
11
|
+
getPostInitRoutingLines,
|
|
12
|
+
normalizeRequestedTools,
|
|
13
|
+
resolveAdapters,
|
|
14
|
+
resolveInteractiveInitSession,
|
|
15
|
+
} from './init-runtime.mjs';
|
|
16
|
+
import { createInitPromptApi } from './init-prompts.mjs';
|
|
17
|
+
|
|
18
|
+
export function createCmdInit(ctx) {
|
|
19
|
+
return async function cmdInit(...initArgs) {
|
|
20
|
+
console.log('gsdd init - setting up SDD workflow\n');
|
|
21
|
+
|
|
22
|
+
const isAuto = parseAutoFlag(initArgs);
|
|
23
|
+
const toolsFlag = parseFlagValue(initArgs, '--tools');
|
|
24
|
+
const briefFlag = parseFlagValue(initArgs, '--brief');
|
|
25
|
+
let briefSource = null;
|
|
26
|
+
|
|
27
|
+
if (toolsFlag.invalid) {
|
|
28
|
+
console.error('ERROR: --tools requires a value. Example: gsdd init --tools claude');
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (briefFlag.invalid) {
|
|
34
|
+
console.error('ERROR: --brief requires a file path. Example: gsdd init --brief project-idea.md');
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (briefFlag.value) {
|
|
40
|
+
briefSource = isAbsolute(briefFlag.value) ? briefFlag.value : join(ctx.cwd, briefFlag.value);
|
|
41
|
+
if (!existsSync(briefSource)) {
|
|
42
|
+
console.error(`ERROR: Brief file not found: ${briefFlag.value}`);
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const parsedTools = parseToolsFlag(initArgs);
|
|
49
|
+
if (isAuto && parsedTools.length === 0) {
|
|
50
|
+
console.error('ERROR: --auto requires --tools <platform>. Example: gsdd init --auto --tools claude');
|
|
51
|
+
process.exitCode = 1;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const promptApi = ctx.initPromptApi || createInitPromptApi();
|
|
56
|
+
const interactiveSession = await resolveInteractiveInitSession({
|
|
57
|
+
ctx,
|
|
58
|
+
promptApi,
|
|
59
|
+
parsedTools,
|
|
60
|
+
isAuto,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const existed = existsSync(ctx.planningDir);
|
|
64
|
+
mkdirSync(join(ctx.planningDir, 'phases'), { recursive: true });
|
|
65
|
+
mkdirSync(join(ctx.planningDir, 'research'), { recursive: true });
|
|
66
|
+
console.log(existed
|
|
67
|
+
? ' - .planning/ already exists (ensured subdirectories)'
|
|
68
|
+
: ' - created .planning/ directory structure');
|
|
69
|
+
|
|
70
|
+
installProjectTemplates(ctx);
|
|
71
|
+
await ensureConfig({
|
|
72
|
+
cwd: ctx.cwd,
|
|
73
|
+
planningDir: ctx.planningDir,
|
|
74
|
+
isAuto,
|
|
75
|
+
promptApi,
|
|
76
|
+
preselectedConfig: interactiveSession.config,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (briefSource) {
|
|
80
|
+
cpSync(briefSource, join(ctx.planningDir, 'PROJECT_BRIEF.md'));
|
|
81
|
+
console.log(' - copied project brief to .planning/PROJECT_BRIEF.md');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
generateOpenStandardSkills(ctx.cwd, ctx.workflows);
|
|
85
|
+
console.log(' - generated open-standard skills (.agents/skills/gsdd-*)');
|
|
86
|
+
|
|
87
|
+
for (const adapter of resolveAdapters(ctx.adapters, interactiveSession.adapterTargets)) {
|
|
88
|
+
adapter.generate();
|
|
89
|
+
console.log(` - ${adapter.summary('generated')}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const manifest = buildManifest({ planningDir: ctx.planningDir, frameworkVersion: ctx.frameworkVersion });
|
|
93
|
+
writeManifest(ctx.planningDir, manifest);
|
|
94
|
+
console.log(' - wrote generation manifest');
|
|
95
|
+
|
|
96
|
+
console.log('\nSDD initialized.');
|
|
97
|
+
console.log('Next: run the new-project workflow to produce SPEC.md and ROADMAP.md:\n');
|
|
98
|
+
printPostInitRouting(interactiveSession.selectedRuntimes);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function createCmdUpdate(ctx) {
|
|
103
|
+
return function cmdUpdate(...updateArgs) {
|
|
104
|
+
const isDry = updateArgs.includes('--dry');
|
|
105
|
+
const doTemplates = updateArgs.includes('--templates');
|
|
106
|
+
|
|
107
|
+
console.log(`gsdd update - regenerating adapter files${isDry ? ' (dry run)' : ''}\n`);
|
|
108
|
+
|
|
109
|
+
const parsedTools = parseToolsFlag(updateArgs);
|
|
110
|
+
const requested = normalizeRequestedTools(parsedTools);
|
|
111
|
+
const platforms = parsedTools.length > 0 ? requested.adapterTargets : detectPlatforms(ctx.adapters);
|
|
112
|
+
|
|
113
|
+
let updated = false;
|
|
114
|
+
|
|
115
|
+
if (doTemplates) {
|
|
116
|
+
refreshTemplates({ ...ctx, isDry });
|
|
117
|
+
updated = true;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (platforms.length > 0 || existsSync(join(ctx.cwd, '.agents', 'skills'))) {
|
|
121
|
+
if (isDry) {
|
|
122
|
+
console.log(' - would update open-standard skills (.agents/skills/gsdd-*)');
|
|
123
|
+
} else {
|
|
124
|
+
generateOpenStandardSkills(ctx.cwd, ctx.workflows);
|
|
125
|
+
console.log(' - updated open-standard skills (.agents/skills/gsdd-*)');
|
|
126
|
+
}
|
|
127
|
+
updated = true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for (const adapter of getAdaptersToUpdate(ctx.adapters, platforms)) {
|
|
131
|
+
if (isDry) {
|
|
132
|
+
console.log(` - would update ${adapter.name} adapter`);
|
|
133
|
+
} else {
|
|
134
|
+
adapter.generate();
|
|
135
|
+
console.log(` - ${adapter.summary('updated')}`);
|
|
136
|
+
}
|
|
137
|
+
updated = true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!updated) {
|
|
141
|
+
console.log(' - no adapters found to update (run `gsdd init` first)');
|
|
142
|
+
} else if (isDry) {
|
|
143
|
+
console.log('\nDry run complete. No files were written.\n');
|
|
144
|
+
} else {
|
|
145
|
+
if (doTemplates && existsSync(ctx.planningDir)) {
|
|
146
|
+
const manifest = buildManifest({ planningDir: ctx.planningDir, frameworkVersion: ctx.frameworkVersion });
|
|
147
|
+
writeManifest(ctx.planningDir, manifest);
|
|
148
|
+
console.log(' - updated generation manifest');
|
|
149
|
+
}
|
|
150
|
+
console.log('\nAdapters updated.\n');
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function generateOpenStandardSkills(cwd, workflows) {
|
|
156
|
+
for (const workflow of workflows) {
|
|
157
|
+
const dir = join(cwd, '.agents', 'skills', workflow.name);
|
|
158
|
+
mkdirSync(dir, { recursive: true });
|
|
159
|
+
writeFileSync(join(dir, 'SKILL.md'), renderSkillContent(workflow));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function ensureConfig({ cwd, planningDir, isAuto, promptApi, preselectedConfig = null }) {
|
|
164
|
+
const configFile = join(planningDir, 'config.json');
|
|
165
|
+
if (existsSync(configFile)) {
|
|
166
|
+
console.log(' - .planning/config.json already exists');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (preselectedConfig) {
|
|
171
|
+
writeFileSync(configFile, JSON.stringify(preselectedConfig, null, 2));
|
|
172
|
+
console.log(' - saved .planning/config.json (guided wizard)\n');
|
|
173
|
+
if (!preselectedConfig.commitDocs) ensureGitignoreEntry(cwd);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (isAuto) {
|
|
178
|
+
console.log(' - auto mode: writing config.json with defaults');
|
|
179
|
+
writeFileSync(configFile, JSON.stringify(buildDefaultConfig({ autoAdvance: true }), null, 2));
|
|
180
|
+
console.log(' - saved .planning/config.json (auto mode - autoAdvance enabled)\n');
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!process.stdin.isTTY) {
|
|
185
|
+
console.log(' - non-interactive mode detected: writing config.json with defaults');
|
|
186
|
+
writeFileSync(configFile, JSON.stringify(buildDefaultConfig(), null, 2));
|
|
187
|
+
console.log(' - saved .planning/config.json (defaults - re-run gsdd init in a terminal to customize)\n');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const config = await promptApi.promptForConfig(cwd);
|
|
192
|
+
writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
193
|
+
console.log(' - saved .planning/config.json (guided wizard)\n');
|
|
194
|
+
|
|
195
|
+
if (!config.commitDocs) ensureGitignoreEntry(cwd);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function ensureGitignoreEntry(cwd) {
|
|
199
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
200
|
+
const ignoreEntry = '\n# GSDD planning docs (local only)\n.planning/\n';
|
|
201
|
+
|
|
202
|
+
if (existsSync(gitignorePath)) {
|
|
203
|
+
const existing = readFileSync(gitignorePath, 'utf-8');
|
|
204
|
+
if (!existing.includes('.planning/')) {
|
|
205
|
+
writeFileSync(gitignorePath, existing + ignoreEntry);
|
|
206
|
+
console.log(' - added .planning/ to .gitignore');
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
writeFileSync(gitignorePath, ignoreEntry.trimStart());
|
|
212
|
+
console.log(' - created .gitignore with .planning/ entry');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function printPostInitRouting(selectedRuntimes) {
|
|
216
|
+
for (const line of getPostInitRoutingLines(selectedRuntimes)) {
|
|
217
|
+
console.log(line);
|
|
218
|
+
}
|
|
219
|
+
console.log('');
|
|
220
|
+
}
|