@opengsd/gsd-core 1.3.1 → 1.4.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/gsd-advisor-researcher.md +1 -20
- package/agents/gsd-ai-researcher.md +1 -20
- package/agents/gsd-domain-researcher.md +1 -20
- package/agents/gsd-executor.md +1 -1
- package/agents/gsd-phase-researcher.md +92 -166
- package/agents/gsd-planner.md +9 -36
- package/agents/gsd-project-researcher.md +62 -141
- package/agents/gsd-ui-researcher.md +2 -21
- package/agents/gsd-verifier.md +8 -2
- package/bin/install.js +85 -4
- package/commands/gsd/graphify.md +11 -6
- package/commands/gsd/import.md +6 -2
- package/commands/gsd/plan-phase.md +2 -2
- package/gsd-core/bin/check-latest-version.cjs +3 -2
- package/gsd-core/bin/gsd-tools.cjs +238 -32
- package/gsd-core/bin/lib/check-command-router.cjs +1 -0
- package/gsd-core/bin/lib/cli-exit.cjs +42 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +1 -1
- package/gsd-core/bin/lib/commands.cjs +5 -4
- package/gsd-core/bin/lib/config.cjs +28 -4
- package/gsd-core/bin/lib/core.cjs +72 -28
- package/gsd-core/bin/lib/graphify.cjs +2 -2
- package/gsd-core/bin/lib/init-command-router.cjs +2 -2
- package/gsd-core/bin/lib/init.cjs +19 -3
- package/gsd-core/bin/lib/intel.cjs +3 -20
- package/gsd-core/bin/lib/package-legitimacy.cjs +368 -0
- package/gsd-core/bin/lib/phase.cjs +3 -3
- package/gsd-core/bin/lib/research-provider.cjs +137 -0
- package/gsd-core/bin/lib/research-store.cjs +167 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +4 -19
- package/gsd-core/bin/lib/security.cjs +73 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +3 -0
- package/gsd-core/bin/lib/validate.cjs +2 -2
- package/gsd-core/bin/lib/verification-command-router.cjs +31 -0
- package/gsd-core/bin/lib/verification.cjs +193 -0
- package/gsd-core/bin/lib/verify.cjs +2 -2
- package/gsd-core/bin/lib/workstream-inventory.cjs +1 -1
- package/gsd-core/bin/lib/worktree-base-ref.cjs +325 -0
- package/gsd-core/bin/lib/worktree-safety.cjs +31 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -1
- package/gsd-core/bin/verify-reapply-patches.cjs +8 -11
- package/gsd-core/references/planner-load-graph-context.md +36 -0
- package/gsd-core/references/planning-config.md +3 -1
- package/gsd-core/references/research-documentation-lookup.md +29 -0
- package/gsd-core/references/research-philosophy.md +29 -0
- package/gsd-core/references/research-verification-protocol.md +27 -0
- package/gsd-core/workflows/execute-phase.md +19 -8
- package/gsd-core/workflows/help/modes/full.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -2
- package/gsd-core/workflows/plan-phase.md +14 -10
- package/gsd-core/workflows/plan-review-convergence.md +3 -3
- package/gsd-core/workflows/review.md +22 -5
- package/gsd-core/workflows/ship.md +5 -8
- package/gsd-core/workflows/spec-phase.md +2 -1
- package/gsd-core/workflows/update.md +2 -1
- package/hooks/dist/gsd-context-monitor.js +1 -1
- package/hooks/dist/gsd-workflow-guard.js +1 -0
- package/hooks/dist/gsd-worktree-path-guard.js +1 -1
- package/hooks/gsd-context-monitor.js +1 -1
- package/hooks/gsd-workflow-guard.js +1 -0
- package/hooks/gsd-worktree-path-guard.js +1 -1
- package/package.json +4 -1
- package/scripts/affected-tests-lib.cjs +3 -2
- package/scripts/changeset/cli.cjs +183 -28
- package/scripts/changeset/lint.cjs +5 -4
- package/scripts/changeset/new.cjs +4 -4
- package/scripts/check-alias-drift.cjs +77 -71
- package/scripts/check-env.cjs +185 -179
- package/scripts/check-npm-integrity.cjs +115 -109
- package/scripts/ci-guard-runner.cjs +11 -5
- package/scripts/ci-prepare-test-scope.cjs +27 -22
- package/scripts/ci-rebase-check.cjs +46 -45
- package/scripts/ci-test-scope.cjs +6 -4
- package/scripts/diff-touches-shipped-paths.cjs +52 -44
- package/scripts/gen-inventory-manifest.cjs +38 -32
- package/scripts/gen-research-agents.cjs +276 -0
- package/scripts/lib/cli-exit.cjs +56 -0
- package/scripts/lint-command-contract.cjs +28 -22
- package/scripts/lint-descriptions.cjs +32 -28
- package/scripts/lint-docs-required.cjs +4 -4
- package/scripts/lint-legacy-dir-name.cjs +56 -52
- package/scripts/lint-pr-check-project-dir.cjs +3 -1
- package/scripts/lint-shell-command-projection-drift.cjs +27 -22
- package/scripts/lint-skill-deps.cjs +31 -26
- package/scripts/lint-test-file-count.allowlist.json +1 -0
- package/scripts/lint-test-file-count.cjs +5 -4
- package/scripts/mutation-matrix.cjs +6 -3
- package/scripts/prompt-injection-scan.sh +1 -1
- package/scripts/release-notes/format-github-release-notes.cjs +8 -3
- package/scripts/release-tarball-smoke.cjs +6 -4
- package/scripts/research-profiles.cjs +149 -0
- package/scripts/run-affected-tests.cjs +2 -1
- package/scripts/run-cross-platform-tests.cjs +11 -7
- package/scripts/run-tests.cjs +8 -7
- package/scripts/strip-prose-atrefs.cjs +1 -1
- package/scripts/sync-runtime-launcher.cjs +0 -3
- package/scripts/verify-npm-publish.cjs +14 -26
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsd-project-researcher
|
|
3
3
|
description: Researches domain ecosystem before roadmap creation. Produces files in .planning/research/ consumed during roadmap creation. Spawned by /gsd:new-project or /gsd:new-milestone orchestrators.
|
|
4
|
-
tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*
|
|
4
|
+
tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*, mcp__tavily__*, mcp__ref__*, mcp__jina__*
|
|
5
5
|
color: cyan
|
|
6
6
|
# hooks:
|
|
7
7
|
# PostToolUse:
|
|
@@ -33,53 +33,11 @@ Your files feed the roadmap:
|
|
|
33
33
|
</role>
|
|
34
34
|
|
|
35
35
|
<documentation_lookup>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
1. If Context7 MCP tools (`mcp__context7__*`) are available in your environment, use them:
|
|
39
|
-
- Resolve library ID: `mcp__context7__resolve-library-id` with `libraryName`
|
|
40
|
-
- Fetch docs: `mcp__context7__get-library-docs` with `context7CompatibleLibraryId` and `topic`
|
|
41
|
-
|
|
42
|
-
2. If Context7 MCP is not available (upstream bug anthropics/claude-code#13898 strips MCP
|
|
43
|
-
tools from agents with a `tools:` frontmatter restriction), use the CLI fallback via Bash:
|
|
44
|
-
|
|
45
|
-
Step 1 — Resolve library ID:
|
|
46
|
-
```bash
|
|
47
|
-
npx --yes ctx7@latest library <name> "<query>"
|
|
48
|
-
```
|
|
49
|
-
Step 2 — Fetch documentation:
|
|
50
|
-
```bash
|
|
51
|
-
npx --yes ctx7@latest docs <libraryId> "<query>"
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Do not skip documentation lookups because MCP tools are unavailable — the CLI fallback
|
|
55
|
-
works via Bash and produces equivalent output.
|
|
36
|
+
@~/.claude/gsd-core/references/research-documentation-lookup.md
|
|
56
37
|
</documentation_lookup>
|
|
57
38
|
|
|
58
39
|
<philosophy>
|
|
59
|
-
|
|
60
|
-
## Training Data = Hypothesis
|
|
61
|
-
|
|
62
|
-
Claude's training is 6-18 months stale. Knowledge may be outdated, incomplete, or wrong.
|
|
63
|
-
|
|
64
|
-
**Discipline:**
|
|
65
|
-
1. **Verify before asserting** — check Context7 or official docs before stating capabilities
|
|
66
|
-
2. **Prefer current sources** — Context7 and official docs trump training data
|
|
67
|
-
3. **Flag uncertainty** — LOW confidence when only training data supports a claim
|
|
68
|
-
|
|
69
|
-
## Honest Reporting
|
|
70
|
-
|
|
71
|
-
- "I couldn't find X" is valuable (investigate differently)
|
|
72
|
-
- "LOW confidence" is valuable (flags for validation)
|
|
73
|
-
- "Sources contradict" is valuable (surfaces ambiguity)
|
|
74
|
-
- Never pad findings, state unverified claims as fact, or hide uncertainty
|
|
75
|
-
|
|
76
|
-
## Investigation, Not Confirmation
|
|
77
|
-
|
|
78
|
-
**Bad research:** Start with hypothesis, find supporting evidence
|
|
79
|
-
**Good research:** Gather evidence, form conclusions from evidence
|
|
80
|
-
|
|
81
|
-
Don't find articles supporting your initial guess — find what the ecosystem actually uses and let evidence drive recommendations.
|
|
82
|
-
|
|
40
|
+
@~/.claude/gsd-core/references/research-philosophy.md
|
|
83
41
|
</philosophy>
|
|
84
42
|
|
|
85
43
|
<research_modes>
|
|
@@ -94,132 +52,95 @@ Don't find articles supporting your initial guess — find what the ecosystem ac
|
|
|
94
52
|
|
|
95
53
|
<tool_strategy>
|
|
96
54
|
|
|
97
|
-
##
|
|
55
|
+
## Research Plan via Code Seam
|
|
98
56
|
|
|
99
|
-
|
|
100
|
-
Authoritative, current, version-aware documentation.
|
|
57
|
+
The agent decides **what** to research (the questions). The seam decides **which provider** to use and manages caching.
|
|
101
58
|
|
|
102
|
-
|
|
103
|
-
1. mcp__context7__resolve-library-id with libraryName: "[library]"
|
|
104
|
-
2. mcp__context7__query-docs with libraryId: [resolved ID], query: "[question]"
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Resolve first (don't guess IDs). Use specific queries. Trust over training data.
|
|
108
|
-
|
|
109
|
-
### 2. Official Docs via WebFetch — Authoritative Sources
|
|
110
|
-
For libraries not in Context7, changelogs, release notes, official announcements.
|
|
111
|
-
|
|
112
|
-
Use exact URLs (not search result pages). Check publication dates. Prefer /docs/ over marketing.
|
|
59
|
+
### Step A — Build a research-plan input file
|
|
113
60
|
|
|
114
|
-
|
|
115
|
-
For finding what exists, community patterns, real-world usage.
|
|
61
|
+
Construct a JSON file at a temp path (e.g. `/tmp/research-plan-input.json`):
|
|
116
62
|
|
|
117
|
-
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"ecosystem": "<npm|pypi|crates|...>",
|
|
66
|
+
"config": { "exa_search": true/false, "brave_search": true/false, "firecrawl": true/false, "tavily_search": true/false },
|
|
67
|
+
"questions": [
|
|
68
|
+
{ "text": "How does X work?", "kind": "docs", "library": "x", "version": "1.2.3" },
|
|
69
|
+
{ "text": "Best practices for Y?", "kind": "web" }
|
|
70
|
+
]
|
|
71
|
+
}
|
|
118
72
|
```
|
|
119
|
-
Ecosystem: "[tech] best practices", "[tech] recommended libraries"
|
|
120
|
-
Patterns: "how to build [type] with [tech]", "[tech] architecture patterns"
|
|
121
|
-
Problems: "[tech] common mistakes", "[tech] gotchas"
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Use multiple query variations. Mark WebSearch-only findings as LOW confidence. Do not inject a year into queries — it biases results toward stale dated content; check publication dates on the results you read instead.
|
|
125
73
|
|
|
126
|
-
|
|
74
|
+
`config` comes from the init context (availability flags). `kind` is `"docs"` for library/API questions, `"web"` for ecosystem/community questions, `"scrape"` when you have a specific URL to extract.
|
|
127
75
|
|
|
128
|
-
|
|
76
|
+
### Step B — Obtain the fetch plan
|
|
129
77
|
|
|
130
78
|
```bash
|
|
131
|
-
gsd-tools query
|
|
79
|
+
gsd-tools query research-plan --input /tmp/research-plan-input.json
|
|
132
80
|
```
|
|
133
81
|
|
|
134
|
-
|
|
135
|
-
- `--limit N` — Number of results (default: 10)
|
|
136
|
-
- `--freshness day|week|month` — Restrict to recent content
|
|
82
|
+
Returns `{ "items": [ { "question": "...", "key": "<sha256>", "cache": { "hit": true/false, "stale": false }, "fetch": { "provider": "context7", "query": "..." } } ] }`.
|
|
137
83
|
|
|
138
|
-
|
|
84
|
+
- `cache.hit && !cache.stale` → reuse the cached digest; no fetch needed.
|
|
85
|
+
- `cache.hit && cache.stale` → fetch anyway to refresh; the old entry is returned as a fallback.
|
|
86
|
+
- no `cache` field → cache miss; must fetch.
|
|
139
87
|
|
|
140
|
-
|
|
88
|
+
### Step C — Execute the indicated fetch
|
|
141
89
|
|
|
142
|
-
|
|
90
|
+
For each item where `fetch` is present, invoke the MCP tool matching `fetch.provider`:
|
|
143
91
|
|
|
144
|
-
|
|
92
|
+
| provider id | MCP tool / built-in |
|
|
93
|
+
|-------------|---------------------|
|
|
94
|
+
| `context7` | `mcp__context7__resolve-library-id` then `mcp__context7__query-docs` |
|
|
95
|
+
| `ref` | `mcp__ref__*` (use the appropriate ref MCP tool for the query) |
|
|
96
|
+
| `jina` | `mcp__jina__*` (use the appropriate jina MCP tool for the query) |
|
|
97
|
+
| `exa` | `mcp__exa__web_search_exa` with `fetch.query` |
|
|
98
|
+
| `tavily` | `mcp__tavily__search` with `fetch.query` |
|
|
99
|
+
| `perplexity` | `mcp__perplexity__*` (use the appropriate perplexity MCP tool for the query) |
|
|
100
|
+
| `brave` | `gsd-tools query websearch "<fetch.query>"` (Brave-backed) or built-in `WebSearch` |
|
|
101
|
+
| `firecrawl` | `mcp__firecrawl__scrape` with url (scrape kind) or `mcp__firecrawl__search` |
|
|
102
|
+
| `websearch` | built-in `WebSearch` tool |
|
|
103
|
+
| `webfetch` | built-in `WebFetch` tool |
|
|
145
104
|
|
|
146
|
-
|
|
147
|
-
mcp__exa__web_search_exa with query: "your semantic query"
|
|
148
|
-
```
|
|
105
|
+
For any other provider id `X` not listed above: use `mcp__X__*` if available, else fall back to `WebSearch`.
|
|
149
106
|
|
|
150
|
-
**
|
|
107
|
+
**WebSearch tip:** Do not inject a year into queries — it biases results toward stale dated content; check publication dates on the results you read instead.
|
|
151
108
|
|
|
152
|
-
|
|
109
|
+
### Step D — Cache each digest
|
|
153
110
|
|
|
154
|
-
|
|
111
|
+
After digesting a source, persist it so future runs can reuse it:
|
|
155
112
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
113
|
+
```bash
|
|
114
|
+
gsd-tools query research-store put <key> \
|
|
115
|
+
--content "<one-paragraph digest>" \
|
|
116
|
+
--source <curated|web> \
|
|
117
|
+
--provider <provider-id> \
|
|
118
|
+
--confidence <HIGH|MEDIUM|LOW> \
|
|
119
|
+
--kind <docs|web>
|
|
161
120
|
```
|
|
162
121
|
|
|
163
|
-
|
|
122
|
+
`key` comes from the `research-plan` item. `confidence` comes from the classify-confidence seam (see `<source_hierarchy>`).
|
|
164
123
|
|
|
165
|
-
|
|
124
|
+
</tool_strategy>
|
|
166
125
|
|
|
167
|
-
|
|
126
|
+
<source_hierarchy>
|
|
168
127
|
|
|
169
|
-
|
|
128
|
+
Obtain the confidence tier from code — do not hard-code tiers in your reasoning:
|
|
170
129
|
|
|
130
|
+
```bash
|
|
131
|
+
gsd-tools query classify-confidence --provider <provider-id>
|
|
132
|
+
# for cross-checked findings, add --verified:
|
|
133
|
+
gsd-tools query classify-confidence --provider <provider-id> --verified
|
|
171
134
|
```
|
|
172
|
-
For each finding:
|
|
173
|
-
1. Verify with Context7? YES → HIGH confidence
|
|
174
|
-
2. Verify with official docs? YES → MEDIUM confidence
|
|
175
|
-
3. Multiple sources agree? YES → Increase one level
|
|
176
|
-
Otherwise → LOW confidence, flag for validation
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
Never present LOW confidence findings as authoritative.
|
|
180
135
|
|
|
181
|
-
|
|
136
|
+
Returns `HIGH`, `MEDIUM`, or `LOW`. Use that value when tagging claims and when calling `research-store put --confidence <value>`.
|
|
182
137
|
|
|
183
|
-
|
|
184
|
-
|-------|---------|-----|
|
|
185
|
-
| HIGH | Context7, official documentation, official releases | State as fact |
|
|
186
|
-
| MEDIUM | WebSearch verified with official source, multiple credible sources agree | State with attribution |
|
|
187
|
-
| LOW | WebSearch only, single source, unverified | Flag as needing validation |
|
|
138
|
+
**Never present LOW confidence findings as authoritative.**
|
|
188
139
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
</tool_strategy>
|
|
140
|
+
</source_hierarchy>
|
|
192
141
|
|
|
193
142
|
<verification_protocol>
|
|
194
|
-
|
|
195
|
-
## Research Pitfalls
|
|
196
|
-
|
|
197
|
-
### Configuration Scope Blindness
|
|
198
|
-
**Trap:** Assuming global config means no project-scoping exists
|
|
199
|
-
**Prevention:** Verify ALL scopes (global, project, local, workspace)
|
|
200
|
-
|
|
201
|
-
### Deprecated Features
|
|
202
|
-
**Trap:** Old docs → concluding feature doesn't exist
|
|
203
|
-
**Prevention:** Check current docs, changelog, version numbers
|
|
204
|
-
|
|
205
|
-
### Negative Claims Without Evidence
|
|
206
|
-
**Trap:** Definitive "X is not possible" without official verification
|
|
207
|
-
**Prevention:** Is this in official docs? Checked recent updates? "Didn't find" ≠ "doesn't exist"
|
|
208
|
-
|
|
209
|
-
### Single Source Reliance
|
|
210
|
-
**Trap:** One source for critical claims
|
|
211
|
-
**Prevention:** Require official docs + release notes + additional source
|
|
212
|
-
|
|
213
|
-
## Pre-Submission Checklist
|
|
214
|
-
|
|
215
|
-
- [ ] All domains investigated (stack, features, architecture, pitfalls)
|
|
216
|
-
- [ ] Negative claims verified with official docs
|
|
217
|
-
- [ ] Multiple sources for critical claims
|
|
218
|
-
- [ ] URLs provided for authoritative sources
|
|
219
|
-
- [ ] Publication dates checked (prefer recent/current)
|
|
220
|
-
- [ ] Confidence levels assigned honestly
|
|
221
|
-
- [ ] "What might I have missed?" review completed
|
|
222
|
-
|
|
143
|
+
@~/.claude/gsd-core/references/research-verification-protocol.md
|
|
223
144
|
</verification_protocol>
|
|
224
145
|
|
|
225
146
|
<output_formats>
|
|
@@ -564,7 +485,7 @@ Orchestrator provides: project name/description, research mode, project context,
|
|
|
564
485
|
|
|
565
486
|
## Step 3: Execute Research
|
|
566
487
|
|
|
567
|
-
For each domain:
|
|
488
|
+
For each domain, use the `<tool_strategy>` seam (Steps A–D): build questions JSON, call `gsd-tools query research-plan`, run the indicated provider per item, then cache each digest. Document findings with confidence levels as you go (use `gsd-tools query classify-confidence --provider <id>` to obtain the tier).
|
|
568
489
|
|
|
569
490
|
## Step 4: Quality Check
|
|
570
491
|
|
|
@@ -678,7 +599,7 @@ Research is complete when:
|
|
|
678
599
|
- [ ] Feature landscape mapped (table stakes, differentiators, anti-features)
|
|
679
600
|
- [ ] Architecture patterns documented
|
|
680
601
|
- [ ] Domain pitfalls catalogued
|
|
681
|
-
- [ ] Source hierarchy followed (
|
|
602
|
+
- [ ] Source hierarchy followed (research-plan seam determines provider order; classify-confidence seam determines tiers)
|
|
682
603
|
- [ ] All findings have confidence levels
|
|
683
604
|
- [ ] Output files created in `.planning/research/`
|
|
684
605
|
- [ ] SUMMARY.md includes roadmap implications
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsd-ui-researcher
|
|
3
3
|
description: Produces UI-SPEC.md design contract for frontend phases. Reads upstream artifacts, detects design system state, asks only unanswered questions. Spawned by /gsd:ui-phase orchestrator.
|
|
4
|
-
tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*
|
|
4
|
+
tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*, mcp__tavily__*, mcp__ref__*, mcp__jina__*
|
|
5
5
|
color: "#E879F9"
|
|
6
6
|
# hooks:
|
|
7
7
|
# PostToolUse:
|
|
@@ -28,26 +28,7 @@ If the prompt contains a `<required_reading>` block, you MUST use the `Read` too
|
|
|
28
28
|
</role>
|
|
29
29
|
|
|
30
30
|
<documentation_lookup>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
1. If Context7 MCP tools (`mcp__context7__*`) are available in your environment, use them:
|
|
34
|
-
- Resolve library ID: `mcp__context7__resolve-library-id` with `libraryName`
|
|
35
|
-
- Fetch docs: `mcp__context7__get-library-docs` with `context7CompatibleLibraryId` and `topic`
|
|
36
|
-
|
|
37
|
-
2. If Context7 MCP is not available (upstream bug anthropics/claude-code#13898 strips MCP
|
|
38
|
-
tools from agents with a `tools:` frontmatter restriction), use the CLI fallback via Bash:
|
|
39
|
-
|
|
40
|
-
Step 1 — Resolve library ID:
|
|
41
|
-
```bash
|
|
42
|
-
npx --yes ctx7@latest library <name> "<query>"
|
|
43
|
-
```
|
|
44
|
-
Step 2 — Fetch documentation:
|
|
45
|
-
```bash
|
|
46
|
-
npx --yes ctx7@latest docs <libraryId> "<query>"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Do not skip documentation lookups because MCP tools are unavailable — the CLI fallback
|
|
50
|
-
works via Bash and produces equivalent output.
|
|
31
|
+
@~/.claude/gsd-core/references/research-documentation-lookup.md
|
|
51
32
|
</documentation_lookup>
|
|
52
33
|
|
|
53
34
|
<project_context>
|
package/agents/gsd-verifier.md
CHANGED
|
@@ -466,8 +466,11 @@ ls $BUILD_OUTPUT_DIR/*.{js,css} 2>/dev/null | wc -l
|
|
|
466
466
|
# Module exports expected functions
|
|
467
467
|
node -e "const m = require('$MODULE_PATH'); console.log(typeof m.$FUNCTION_NAME)" 2>/dev/null | grep -q "function"
|
|
468
468
|
|
|
469
|
-
#
|
|
470
|
-
|
|
469
|
+
# A test EXISTS (existence proof — enumerate, do NOT run the suite)
|
|
470
|
+
cargo test -- --list 2>/dev/null | grep -q "$PHASE_TEST_PATTERN" # pytest --collect-only -q · npx vitest list · go test -list '.*'
|
|
471
|
+
|
|
472
|
+
# A specific test PASSES (run ONE named test, never the whole suite)
|
|
473
|
+
cargo test "$TEST_NAME" -- --exact # pytest -k "$TEST_NAME" · npx vitest run -t "$TEST_NAME"
|
|
471
474
|
```
|
|
472
475
|
|
|
473
476
|
2. **Run each check** and record pass/fail:
|
|
@@ -487,6 +490,7 @@ npm test -- --grep "$PHASE_TEST_PATTERN" 2>&1 | grep -q "passing"
|
|
|
487
490
|
- Each check must complete in under 10 seconds
|
|
488
491
|
- Do not start servers or services — only test what's already runnable
|
|
489
492
|
- Do not modify state (no writes, no mutations, no side effects)
|
|
493
|
+
- **Run the full workspace test command at most once per verification.** Never filter a full run per must-have (`<full-suite> 2>&1 | grep X` repeated per truth) — it re-runs everything and yields no new evidence. Prove a test exists by enumeration (`--list` / `--collect-only`); prove one passes via a single named test. If a full run is genuinely required, run it once and `grep` the saved output.
|
|
490
494
|
- If the project has no runnable entry points yet, skip with: "Step 7b: SKIPPED (no runnable entry points)"
|
|
491
495
|
|
|
492
496
|
## Step 7c: Probe Execution
|
|
@@ -572,6 +576,8 @@ Classify status using this decision tree IN ORDER (most restrictive first):
|
|
|
572
576
|
|
|
573
577
|
**passed is ONLY valid when the human verification section is empty.** If you identified items requiring human testing in Step 8, status MUST be human_needed.
|
|
574
578
|
|
|
579
|
+
> **Shared status seam**: the status vocabulary (`passed`, `gaps_found`, `human_needed`) and the per-status routing (next action and next command for each value) are owned by `src/verification.cts` via `gsd_run query verification.status`. This agent is the single emitter of the frontmatter status field; consumers (ship.md, execute-phase.md) read routing from that query instead of re-deriving it.
|
|
580
|
+
|
|
575
581
|
**Score:** `verified_truths / total_truths`
|
|
576
582
|
|
|
577
583
|
## Step 9b: Filter Deferred Items
|
package/bin/install.js
CHANGED
|
@@ -31,6 +31,10 @@ const {
|
|
|
31
31
|
const {
|
|
32
32
|
resolveAntigravityGlobalDir,
|
|
33
33
|
} = require('../gsd-core/bin/lib/runtime-homes.cjs');
|
|
34
|
+
const {
|
|
35
|
+
applyWorktreeBaseRef,
|
|
36
|
+
readBaseRefFromSettings,
|
|
37
|
+
} = require('../gsd-core/bin/lib/worktree-base-ref.cjs');
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* Runtimes that register hyphen-form `name:` per #2808 AND copy agent bodies
|
|
@@ -1997,6 +2001,8 @@ function convertCopilotToolName(claudeTool) {
|
|
|
1997
2001
|
if (claudeToCopilotTools[claudeTool]) {
|
|
1998
2002
|
return claudeToCopilotTools[claudeTool];
|
|
1999
2003
|
}
|
|
2004
|
+
// mcp__{tavily,ref,jina,exa,firecrawl}__* use the generic MCP passthrough like exa/firecrawl;
|
|
2005
|
+
// add explicit Copilot registry mappings when the io.github ids are confirmed (#657 follow-up)
|
|
2000
2006
|
// Default: lowercase
|
|
2001
2007
|
return claudeTool.toLowerCase();
|
|
2002
2008
|
}
|
|
@@ -2795,14 +2801,22 @@ function convertClaudeAgentToClineAgent(content) {
|
|
|
2795
2801
|
// ── End Cline converters ─────────────────────────────────────────────────────
|
|
2796
2802
|
|
|
2797
2803
|
function convertSlashCommandsToCodexSkillMentions(content) {
|
|
2798
|
-
//
|
|
2804
|
+
// Colon-style /gsd: never appears as a filesystem path segment, so no boundary guard is needed (unlike the hyphen-style below).
|
|
2799
2805
|
let converted = content.replace(/\/gsd:([a-z0-9-]+)/gi, (_, commandName) => {
|
|
2800
2806
|
return `$gsd-${String(commandName).toLowerCase()}`;
|
|
2801
2807
|
});
|
|
2802
2808
|
// Convert hyphen-style command references (workflow output) to Codex $ prefix.
|
|
2803
|
-
//
|
|
2804
|
-
//
|
|
2805
|
-
|
|
2809
|
+
// A real /gsd-<cmd> MENTION is defined positively by two boundaries, so any
|
|
2810
|
+
// in-path occurrence is excluded by construction (no denylist of preceding
|
|
2811
|
+
// chars to maintain — see #712, supersedes the #637/#704 lookbehind treadmill):
|
|
2812
|
+
// 1. Left boundary: opens at start-of-string, whitespace, or an inline-prose
|
|
2813
|
+
// delimiter (backtick/quote/paren/bracket) — e.g. `/gsd-execute-phase`.
|
|
2814
|
+
// 2. Right boundary: the command token is NOT followed by a path separator
|
|
2815
|
+
// `/` (a path continues: `/gsd-core/bin/...`; a command does not). The
|
|
2816
|
+
// `(?![a-z0-9/-])` also blocks regex backtracking to a shorter command.
|
|
2817
|
+
// This converts backtick-wrapped MENTIONS (`/gsd-foo`) while leaving backtick-
|
|
2818
|
+
// wrapped PATHS (`/gsd-core/workflows/update.md`) untouched (#712).
|
|
2819
|
+
converted = converted.replace(/(?<=^|[\s`"'([])\/gsd-([a-z0-9-]+)(?![a-z0-9/-])/gi, (_, commandName) => {
|
|
2806
2820
|
return `$gsd-${String(commandName).toLowerCase()}`;
|
|
2807
2821
|
});
|
|
2808
2822
|
return converted;
|
|
@@ -8575,6 +8589,10 @@ function install(isGlobal, runtime = 'claude', options = {}) {
|
|
|
8575
8589
|
// agentsSrc is declared here (let, not const) because installCodexConfig() inside the
|
|
8576
8590
|
// Codex config block below also references it, and that block is outside the try scope.
|
|
8577
8591
|
let agentsSrc = path.join(src, 'agents');
|
|
8592
|
+
// Capture upgrade signal BEFORE files are written (#683). Must be declared at function
|
|
8593
|
+
// scope (outside the try block below) so it is accessible in the settings section later.
|
|
8594
|
+
// Absent VERSION = fresh install; present VERSION = upgrade/re-install.
|
|
8595
|
+
const priorInstallExisted = fs.existsSync(path.join(targetDir, 'gsd-core', 'VERSION'));
|
|
8578
8596
|
try {
|
|
8579
8597
|
installerMigrationResult = runInstallerMigrations({
|
|
8580
8598
|
configDir: targetDir,
|
|
@@ -10106,6 +10124,68 @@ function install(isGlobal, runtime = 'claude', options = {}) {
|
|
|
10106
10124
|
? buildHookCommand(targetDir, 'gsd-update-banner.js', hookOpts)
|
|
10107
10125
|
: localCmd('gsd-update-banner.js'));
|
|
10108
10126
|
|
|
10127
|
+
// #683: Set worktree.baseRef:"head" in settings.local.json for local Claude installs.
|
|
10128
|
+
// Both fresh and upgrade paths apply only when worktrees are enabled for the project.
|
|
10129
|
+
// Never applies to global installs, non-Claude runtimes, or when the user already
|
|
10130
|
+
// has an explicit baseRef in EITHER settings.local.json OR settings.json (no-clobber).
|
|
10131
|
+
// Guard: skip entirely when settings is not a plain object (e.g. parsed to [] or primitive)
|
|
10132
|
+
// to avoid crashing applyWorktreeBaseRef on unexpected top-level shapes.
|
|
10133
|
+
if (isLocalClaude && settings !== null && typeof settings === 'object' && !Array.isArray(settings)) {
|
|
10134
|
+
// Read shared settings.json baseRef so no-clobber spans both files (#683 FIX 1).
|
|
10135
|
+
// shared settings.json no-clobber is checked here; settings.local.json no-clobber
|
|
10136
|
+
// is enforced inside applyWorktreeBaseRef itself.
|
|
10137
|
+
const sharedSettingsForBaseRef = readSettings(path.join(targetDir, 'settings.json')) || {};
|
|
10138
|
+
const sharedBaseRef = readBaseRefFromSettings(sharedSettingsForBaseRef);
|
|
10139
|
+
|
|
10140
|
+
// Compute worktrees-enabled ONCE for both fresh and upgrade paths (FIX A: DRY + consistency).
|
|
10141
|
+
// Read workflow.use_worktrees from .planning/config.json by walking up from
|
|
10142
|
+
// targetDir (same walk-up pattern as readGsdRuntimeProfileResolver). Defaults
|
|
10143
|
+
// to enabled (true) when the file is missing, unreadable, or the key is absent;
|
|
10144
|
+
// only boolean false disables (string "false" stays enabled).
|
|
10145
|
+
let worktreesEnabled = true; // default: enabled
|
|
10146
|
+
try {
|
|
10147
|
+
let probeDir = path.resolve(targetDir);
|
|
10148
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
10149
|
+
const candidate = path.join(probeDir, '.planning', 'config.json');
|
|
10150
|
+
if (fs.existsSync(candidate)) {
|
|
10151
|
+
try {
|
|
10152
|
+
const parsed = JSON.parse(stripJsonComments(fs.readFileSync(candidate, 'utf-8')));
|
|
10153
|
+
if (parsed && typeof parsed === 'object' &&
|
|
10154
|
+
parsed.workflow && parsed.workflow.use_worktrees === false) {
|
|
10155
|
+
worktreesEnabled = false;
|
|
10156
|
+
}
|
|
10157
|
+
} catch {
|
|
10158
|
+
// Malformed config.json — treat as enabled (safe fallback).
|
|
10159
|
+
}
|
|
10160
|
+
break;
|
|
10161
|
+
}
|
|
10162
|
+
const parent = path.dirname(probeDir);
|
|
10163
|
+
if (parent === probeDir) break;
|
|
10164
|
+
probeDir = parent;
|
|
10165
|
+
}
|
|
10166
|
+
} catch {
|
|
10167
|
+
// Any unexpected error reading .planning — default to enabled.
|
|
10168
|
+
}
|
|
10169
|
+
|
|
10170
|
+
if (worktreesEnabled && sharedBaseRef === null) {
|
|
10171
|
+
if (!priorInstallExisted) {
|
|
10172
|
+
// Fresh install — apply no-clobber baseRef set.
|
|
10173
|
+
// canonical no-clobber logic: src/worktree-base-ref.cts applyWorktreeBaseRef (#683)
|
|
10174
|
+
const { changed } = applyWorktreeBaseRef(settings);
|
|
10175
|
+
if (changed) {
|
|
10176
|
+
console.log(` ${green}✓${reset} Set worktree.baseRef:"head" for Claude Code worktrees (forks phase worktrees off HEAD; #683)`);
|
|
10177
|
+
}
|
|
10178
|
+
} else {
|
|
10179
|
+
// Upgrade — auto-apply no-clobber baseRef set when worktrees are enabled.
|
|
10180
|
+
const { changed } = applyWorktreeBaseRef(settings);
|
|
10181
|
+
if (changed) {
|
|
10182
|
+
console.log(` ${green}✓${reset} Enabled worktree.baseRef:"head" for Claude Code worktrees (forks phase worktrees off HEAD; #683)`);
|
|
10183
|
+
}
|
|
10184
|
+
}
|
|
10185
|
+
}
|
|
10186
|
+
// When worktreesEnabled is false: do nothing, print nothing (both fresh and upgrade).
|
|
10187
|
+
}
|
|
10188
|
+
|
|
10109
10189
|
persistActiveProfileMarker();
|
|
10110
10190
|
return {
|
|
10111
10191
|
settingsPath,
|
|
@@ -10943,6 +11023,7 @@ module.exports = {
|
|
|
10943
11023
|
install,
|
|
10944
11024
|
installAllRuntimes,
|
|
10945
11025
|
uninstall,
|
|
11026
|
+
convertSlashCommandsToCodexSkillMentions,
|
|
10946
11027
|
convertClaudeCommandToCodexSkill,
|
|
10947
11028
|
convertClaudeToOpencodeFrontmatter,
|
|
10948
11029
|
convertClaudeToKiloFrontmatter,
|
package/commands/gsd/graphify.md
CHANGED
|
@@ -79,7 +79,8 @@ Modes:
|
|
|
79
79
|
Run:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
node $HOME/.claude/gsd-core/bin/gsd-tools.cjs
|
|
82
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
83
|
+
gsd_run graphify query <term>
|
|
83
84
|
```
|
|
84
85
|
|
|
85
86
|
Parse the JSON output and display results:
|
|
@@ -95,7 +96,8 @@ Parse the JSON output and display results:
|
|
|
95
96
|
Run:
|
|
96
97
|
|
|
97
98
|
```bash
|
|
98
|
-
node $HOME/.claude/gsd-core/bin/gsd-tools.cjs
|
|
99
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
100
|
+
gsd_run graphify status
|
|
99
101
|
```
|
|
100
102
|
|
|
101
103
|
Parse the JSON output and display:
|
|
@@ -119,7 +121,8 @@ Surface both so the agent can choose.
|
|
|
119
121
|
Run:
|
|
120
122
|
|
|
121
123
|
```bash
|
|
122
|
-
node $HOME/.claude/gsd-core/bin/gsd-tools.cjs
|
|
124
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
125
|
+
gsd_run graphify diff
|
|
123
126
|
```
|
|
124
127
|
|
|
125
128
|
Parse the JSON output and display:
|
|
@@ -137,7 +140,8 @@ If no snapshot exists, suggest running `build` twice (first to create, second to
|
|
|
137
140
|
Run the pre-flight check first:
|
|
138
141
|
|
|
139
142
|
```bash
|
|
140
|
-
node "$HOME/.claude/gsd-core/bin/gsd-tools.cjs"
|
|
143
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
144
|
+
gsd_run graphify build
|
|
141
145
|
```
|
|
142
146
|
|
|
143
147
|
Parse the JSON output:
|
|
@@ -156,12 +160,13 @@ GSD > Building knowledge graph...
|
|
|
156
160
|
Run the build, copy artifacts, write the diff snapshot, and report the summary in a single foreground Bash call so the whole pipeline survives to completion. Use a `timeout` of `600000` ms (10 minutes), which covers the `graphify.build_timeout` ceiling (default 300 s) with margin:
|
|
157
161
|
|
|
158
162
|
```bash
|
|
163
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
159
164
|
graphify update . \
|
|
160
165
|
&& cp graphify-out/graph.json .planning/graphs/graph.json \
|
|
161
166
|
&& { [ -f graphify-out/graph.html ] && cp graphify-out/graph.html .planning/graphs/graph.html || true; } \
|
|
162
167
|
&& cp graphify-out/GRAPH_REPORT.md .planning/graphs/GRAPH_REPORT.md \
|
|
163
|
-
&&
|
|
164
|
-
&&
|
|
168
|
+
&& gsd_run graphify build snapshot \
|
|
169
|
+
&& gsd_run graphify status
|
|
165
170
|
```
|
|
166
171
|
|
|
167
172
|
Do NOT pass `run_in_background: true`. Typical builds complete in 15-60 seconds and the entire chain must run foreground.
|
package/commands/gsd/import.md
CHANGED
|
@@ -33,8 +33,12 @@ $ARGUMENTS
|
|
|
33
33
|
|
|
34
34
|
<process>
|
|
35
35
|
If `--from-gsd2` is in $ARGUMENTS:
|
|
36
|
-
Run
|
|
37
|
-
|
|
36
|
+
Run the reverse-migration (append `--path <dir>` if provided):
|
|
37
|
+
```bash
|
|
38
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
39
|
+
gsd_run from-gsd2
|
|
40
|
+
```
|
|
41
|
+
Present the migration result to the user.
|
|
38
42
|
Stop here (do not run the standard import workflow).
|
|
39
43
|
|
|
40
44
|
Otherwise, execute the import workflow end-to-end.
|
|
@@ -22,8 +22,8 @@ Create executable phase prompts (PLAN.md files) for a roadmap phase with integra
|
|
|
22
22
|
**Research-only mode (`--research-phase <N>`):** Spawn `gsd-phase-researcher` for phase `N`, write `RESEARCH.md`, then exit before the planner runs. Useful for cross-phase research, doc review before committing to a planning approach, and correction-without-replanning loops where iterating on research alone is dramatically cheaper than re-spawning the planner. Replaces the deleted research-phase command (#3042).
|
|
23
23
|
|
|
24
24
|
**Research-only modifiers:**
|
|
25
|
-
- **No flag** — when `RESEARCH.md` already exists,
|
|
26
|
-
- **`--research`** — force-refresh: re-spawn the researcher unconditionally, no prompt.
|
|
25
|
+
- **No flag** — when `RESEARCH.md` already exists, auto-uses it: emits a one-line notice and exits cleanly, no prompt.
|
|
26
|
+
- **`--research`** — force-refresh: re-spawn the researcher unconditionally, no prompt. Bypasses the existing-RESEARCH.md auto-use path.
|
|
27
27
|
- **`--view`** — view-only: print existing `RESEARCH.md` to stdout. Does not spawn the researcher. Cheapest mode for the correction-without-replanning loop. If no `RESEARCH.md` exists yet, errors with a hint to drop `--view`.
|
|
28
28
|
|
|
29
29
|
**Orchestrator role:** Parse arguments, validate phase, research domain (unless skipped), spawn gsd-planner, verify with gsd-plan-checker, iterate until pass or max iterations, present results.
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
const { execNpm } = require('./lib/shell-command-projection.cjs');
|
|
24
|
+
const { runMain } = require('./lib/cli-exit.cjs');
|
|
24
25
|
|
|
25
26
|
// Sourced from the single Package Identity seam (#498), not re-typed. The seam
|
|
26
27
|
// bakes the value from package.json at build time, so it is a code constant —
|
|
@@ -98,9 +99,9 @@ function main() {
|
|
|
98
99
|
} else {
|
|
99
100
|
process.stderr.write(`check-latest-version: ${r.reason}: ${r.detail}\n`);
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
+
return r.ok ? 0 : 1;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
if (require.main === module) main
|
|
105
|
+
if (require.main === module) runMain(main);
|
|
105
106
|
|
|
106
107
|
module.exports = { checkLatestVersion, CHECK_REASON, PACKAGE_NAME };
|