gsd-opencode 1.30.0 → 1.33.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-debugger.md +0 -1
- package/agents/gsd-doc-verifier.md +207 -0
- package/agents/gsd-doc-writer.md +608 -0
- package/agents/gsd-executor.md +22 -1
- package/agents/gsd-phase-researcher.md +41 -0
- package/agents/gsd-plan-checker.md +82 -0
- package/agents/gsd-planner.md +123 -194
- package/agents/gsd-security-auditor.md +129 -0
- package/agents/gsd-ui-auditor.md +40 -0
- package/agents/gsd-user-profiler.md +2 -2
- package/agents/gsd-verifier.md +84 -18
- package/commands/gsd/gsd-add-backlog.md +1 -1
- package/commands/gsd/gsd-analyze-dependencies.md +34 -0
- package/commands/gsd/gsd-autonomous.md +6 -2
- package/commands/gsd/gsd-cleanup.md +5 -0
- package/commands/gsd/gsd-debug.md +24 -21
- package/commands/gsd/gsd-discuss-phase.md +7 -2
- package/commands/gsd/gsd-docs-update.md +48 -0
- package/commands/gsd/gsd-execute-phase.md +4 -0
- package/commands/gsd/gsd-help.md +2 -0
- package/commands/gsd/gsd-join-discord.md +2 -1
- package/commands/gsd/gsd-manager.md +1 -0
- package/commands/gsd/gsd-new-project.md +4 -0
- package/commands/gsd/gsd-plan-phase.md +5 -0
- package/commands/gsd/gsd-quick.md +5 -3
- package/commands/gsd/gsd-reapply-patches.md +171 -39
- package/commands/gsd/gsd-research-phase.md +2 -12
- package/commands/gsd/gsd-review-backlog.md +1 -0
- package/commands/gsd/gsd-review.md +3 -2
- package/commands/gsd/gsd-secure-phase.md +35 -0
- package/commands/gsd/gsd-set-profile.md +0 -1
- package/commands/gsd/gsd-thread.md +1 -1
- package/commands/gsd/gsd-workstreams.md +7 -2
- package/get-shit-done/bin/gsd-tools.cjs +42 -8
- package/get-shit-done/bin/lib/commands.cjs +68 -14
- package/get-shit-done/bin/lib/config.cjs +18 -10
- package/get-shit-done/bin/lib/core.cjs +383 -80
- package/get-shit-done/bin/lib/docs.cjs +267 -0
- package/get-shit-done/bin/lib/frontmatter.cjs +47 -2
- package/get-shit-done/bin/lib/init.cjs +85 -5
- package/get-shit-done/bin/lib/milestone.cjs +21 -0
- package/get-shit-done/bin/lib/model-profiles.cjs +2 -0
- package/get-shit-done/bin/lib/phase.cjs +232 -189
- package/get-shit-done/bin/lib/profile-output.cjs +97 -1
- package/get-shit-done/bin/lib/roadmap.cjs +137 -113
- package/get-shit-done/bin/lib/schema-detect.cjs +238 -0
- package/get-shit-done/bin/lib/security.cjs +5 -3
- package/get-shit-done/bin/lib/state.cjs +366 -44
- package/get-shit-done/bin/lib/verify.cjs +158 -14
- package/get-shit-done/bin/lib/workstream.cjs +6 -2
- package/get-shit-done/references/agent-contracts.md +79 -0
- package/get-shit-done/references/artifact-types.md +113 -0
- package/get-shit-done/references/context-budget.md +49 -0
- package/get-shit-done/references/continuation-format.md +15 -15
- package/get-shit-done/references/domain-probes.md +125 -0
- package/get-shit-done/references/gate-prompts.md +100 -0
- package/get-shit-done/references/model-profiles.md +2 -2
- package/get-shit-done/references/planner-gap-closure.md +62 -0
- package/get-shit-done/references/planner-reviews.md +39 -0
- package/get-shit-done/references/planner-revision.md +87 -0
- package/get-shit-done/references/planning-config.md +15 -0
- package/get-shit-done/references/revision-loop.md +97 -0
- package/get-shit-done/references/ui-brand.md +2 -2
- package/get-shit-done/references/universal-anti-patterns.md +58 -0
- package/get-shit-done/references/workstream-flag.md +56 -3
- package/get-shit-done/templates/SECURITY.md +61 -0
- package/get-shit-done/templates/VALIDATION.md +3 -3
- package/get-shit-done/templates/claude-md.md +27 -4
- package/get-shit-done/templates/config.json +4 -0
- package/get-shit-done/templates/debug-subagent-prompt.md +2 -6
- package/get-shit-done/templates/planner-subagent-prompt.md +2 -10
- package/get-shit-done/workflows/add-phase.md +2 -2
- package/get-shit-done/workflows/add-todo.md +1 -1
- package/get-shit-done/workflows/analyze-dependencies.md +96 -0
- package/get-shit-done/workflows/audit-milestone.md +8 -12
- package/get-shit-done/workflows/autonomous.md +158 -13
- package/get-shit-done/workflows/check-todos.md +2 -2
- package/get-shit-done/workflows/complete-milestone.md +13 -4
- package/get-shit-done/workflows/diagnose-issues.md +8 -6
- package/get-shit-done/workflows/discovery-phase.md +1 -1
- package/get-shit-done/workflows/discuss-phase-assumptions.md +24 -6
- package/get-shit-done/workflows/discuss-phase-power.md +291 -0
- package/get-shit-done/workflows/discuss-phase.md +153 -20
- package/get-shit-done/workflows/docs-update.md +1093 -0
- package/get-shit-done/workflows/execute-phase.md +362 -66
- package/get-shit-done/workflows/execute-plan.md +1 -1
- package/get-shit-done/workflows/help.md +9 -6
- package/get-shit-done/workflows/insert-phase.md +2 -2
- package/get-shit-done/workflows/manager.md +27 -26
- package/get-shit-done/workflows/map-codebase.md +10 -32
- package/get-shit-done/workflows/new-milestone.md +14 -8
- package/get-shit-done/workflows/new-project.md +48 -25
- package/get-shit-done/workflows/next.md +1 -1
- package/get-shit-done/workflows/note.md +1 -1
- package/get-shit-done/workflows/pause-work.md +73 -10
- package/get-shit-done/workflows/plan-milestone-gaps.md +2 -2
- package/get-shit-done/workflows/plan-phase.md +184 -32
- package/get-shit-done/workflows/progress.md +20 -20
- package/get-shit-done/workflows/quick.md +102 -84
- package/get-shit-done/workflows/research-phase.md +2 -6
- package/get-shit-done/workflows/resume-project.md +4 -4
- package/get-shit-done/workflows/review.md +56 -3
- package/get-shit-done/workflows/secure-phase.md +154 -0
- package/get-shit-done/workflows/settings.md +13 -2
- package/get-shit-done/workflows/ship.md +13 -4
- package/get-shit-done/workflows/transition.md +6 -6
- package/get-shit-done/workflows/ui-phase.md +4 -14
- package/get-shit-done/workflows/ui-review.md +25 -7
- package/get-shit-done/workflows/update.md +165 -16
- package/get-shit-done/workflows/validate-phase.md +1 -11
- package/get-shit-done/workflows/verify-phase.md +127 -6
- package/get-shit-done/workflows/verify-work.md +69 -21
- package/package.json +1 -1
|
@@ -12,7 +12,9 @@ permissions:
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
<objective>
|
|
15
|
-
After a GSD update wipes and reinstalls files, this command merges user's previously saved local modifications back into the new version. Uses
|
|
15
|
+
After a GSD update wipes and reinstalls files, this command merges user's previously saved local modifications back into the new version. Uses three-way comparison (pristine baseline, user-modified backup, newly installed version) to reliably distinguish user customizations from version drift.
|
|
16
|
+
|
|
17
|
+
**Critical invariant:** Every file in `gsd-local-patches/` was backed up because the installer's hash comparison detected it was modified. The workflow must NEVER conclude "no custom content" for any backed-up file — that is a logical contradiction. When in doubt, classify as CONFLICT requiring user review, not SKIP.
|
|
16
18
|
</objective>
|
|
17
19
|
|
|
18
20
|
<process>
|
|
@@ -22,19 +24,90 @@ After a GSD update wipes and reinstalls files, this command merges user's previo
|
|
|
22
24
|
Check for local patches directory:
|
|
23
25
|
|
|
24
26
|
```bash
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
expand_home() {
|
|
28
|
+
case "$1" in
|
|
29
|
+
"~/"*) printf '%s/%s\n' "$HOME" "${1#~/}" ;;
|
|
30
|
+
*) printf '%s\n' "$1" ;;
|
|
31
|
+
esac
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
PATCHES_DIR=""
|
|
35
|
+
|
|
36
|
+
# Env overrides first — covers custom config directories used with --config-dir
|
|
37
|
+
if [ -n "$KILO_CONFIG_DIR" ]; then
|
|
38
|
+
candidate="$(expand_home "$KILO_CONFIG_DIR")/gsd-local-patches"
|
|
39
|
+
if [ -d "$candidate" ]; then
|
|
40
|
+
PATCHES_DIR="$candidate"
|
|
41
|
+
fi
|
|
42
|
+
elif [ -n "$KILO_CONFIG" ]; then
|
|
43
|
+
candidate="$(dirname "$(expand_home "$KILO_CONFIG")")/gsd-local-patches"
|
|
44
|
+
if [ -d "$candidate" ]; then
|
|
45
|
+
PATCHES_DIR="$candidate"
|
|
46
|
+
fi
|
|
47
|
+
elif [ -n "$XDG_CONFIG_HOME" ]; then
|
|
48
|
+
candidate="$(expand_home "$XDG_CONFIG_HOME")/kilo/gsd-local-patches"
|
|
49
|
+
if [ -d "$candidate" ]; then
|
|
50
|
+
PATCHES_DIR="$candidate"
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if [ -z "$PATCHES_DIR" ] && [ -n "$OPENCODE_CONFIG_DIR" ]; then
|
|
55
|
+
candidate="$(expand_home "$OPENCODE_CONFIG_DIR")/gsd-local-patches"
|
|
56
|
+
if [ -d "$candidate" ]; then
|
|
57
|
+
PATCHES_DIR="$candidate"
|
|
58
|
+
fi
|
|
59
|
+
elif [ -z "$PATCHES_DIR" ] && [ -n "$OPENCODE_CONFIG" ]; then
|
|
60
|
+
candidate="$(dirname "$(expand_home "$OPENCODE_CONFIG")")/gsd-local-patches"
|
|
61
|
+
if [ -d "$candidate" ]; then
|
|
62
|
+
PATCHES_DIR="$candidate"
|
|
63
|
+
fi
|
|
64
|
+
elif [ -z "$PATCHES_DIR" ] && [ -n "$XDG_CONFIG_HOME" ]; then
|
|
65
|
+
candidate="$(expand_home "$XDG_CONFIG_HOME")/opencode/gsd-local-patches"
|
|
66
|
+
if [ -d "$candidate" ]; then
|
|
67
|
+
PATCHES_DIR="$candidate"
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [ -z "$PATCHES_DIR" ] && [ -n "$GEMINI_CONFIG_DIR" ]; then
|
|
72
|
+
candidate="$(expand_home "$GEMINI_CONFIG_DIR")/gsd-local-patches"
|
|
73
|
+
if [ -d "$candidate" ]; then
|
|
74
|
+
PATCHES_DIR="$candidate"
|
|
75
|
+
fi
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
if [ -z "$PATCHES_DIR" ] && [ -n "$CODEX_HOME" ]; then
|
|
79
|
+
candidate="$(expand_home "$CODEX_HOME")/gsd-local-patches"
|
|
80
|
+
if [ -d "$candidate" ]; then
|
|
81
|
+
PATCHES_DIR="$candidate"
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [ -z "$PATCHES_DIR" ] && [ -n "$CLAUDE_CONFIG_DIR" ]; then
|
|
86
|
+
candidate="$(expand_home "$CLAUDE_CONFIG_DIR")/gsd-local-patches"
|
|
87
|
+
if [ -d "$candidate" ]; then
|
|
88
|
+
PATCHES_DIR="$candidate"
|
|
89
|
+
fi
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Global install — detect runtime config directory defaults
|
|
93
|
+
if [ -z "$PATCHES_DIR" ]; then
|
|
94
|
+
if [ -d "$HOME/.config/kilo/gsd-local-patches" ]; then
|
|
95
|
+
PATCHES_DIR="$HOME/.config/kilo/gsd-local-patches"
|
|
96
|
+
elif [ -d "$HOME/.config/opencode/gsd-local-patches" ]; then
|
|
97
|
+
PATCHES_DIR="$HOME/.config/opencode/gsd-local-patches"
|
|
98
|
+
elif [ -d "$HOME/.opencode/gsd-local-patches" ]; then
|
|
99
|
+
PATCHES_DIR="$HOME/.opencode/gsd-local-patches"
|
|
100
|
+
elif [ -d "$HOME/.gemini/gsd-local-patches" ]; then
|
|
101
|
+
PATCHES_DIR="$HOME/.gemini/gsd-local-patches"
|
|
102
|
+
elif [ -d "$HOME/.codex/gsd-local-patches" ]; then
|
|
103
|
+
PATCHES_DIR="$HOME/.codex/gsd-local-patches"
|
|
104
|
+
else
|
|
105
|
+
PATCHES_DIR="$HOME/.OpenCode/gsd-local-patches"
|
|
106
|
+
fi
|
|
34
107
|
fi
|
|
35
108
|
# Local install fallback — check all runtime directories
|
|
36
109
|
if [ ! -d "$PATCHES_DIR" ]; then
|
|
37
|
-
for dir in .config/opencode .opencode .gemini .OpenCode; do
|
|
110
|
+
for dir in .config/kilo .kilo .config/opencode .opencode .gemini .codex .OpenCode; do
|
|
38
111
|
if [ -d "./$dir/gsd-local-patches" ]; then
|
|
39
112
|
PATCHES_DIR="./$dir/gsd-local-patches"
|
|
40
113
|
break
|
|
@@ -54,7 +127,43 @@ after modifying any GSD workflow, command, or agent files.
|
|
|
54
127
|
```
|
|
55
128
|
Exit.
|
|
56
129
|
|
|
57
|
-
## Step 2:
|
|
130
|
+
## Step 2: Determine baseline for three-way comparison
|
|
131
|
+
|
|
132
|
+
The quality of the merge depends on having a **pristine baseline** — the original unmodified version of each file from the pre-update GSD release. This enables three-way comparison:
|
|
133
|
+
- **Pristine baseline** (original GSD file before any user edits)
|
|
134
|
+
- **User's version** (backed up in `gsd-local-patches/`)
|
|
135
|
+
- **New version** (freshly installed after update)
|
|
136
|
+
|
|
137
|
+
Check for baseline sources in priority order:
|
|
138
|
+
|
|
139
|
+
### Option A: Git history (most reliable)
|
|
140
|
+
If the config directory is a git repository:
|
|
141
|
+
```bash
|
|
142
|
+
CONFIG_DIR=$(dirname "$PATCHES_DIR")
|
|
143
|
+
if git -C "$CONFIG_DIR" rev-parse --git-dir >/dev/null 2>&1; then
|
|
144
|
+
HAS_GIT=true
|
|
145
|
+
fi
|
|
146
|
+
```
|
|
147
|
+
When `HAS_GIT=true`, use `git log` to find the commit where GSD was originally installed (before user edits). For each file, the pristine baseline can be extracted with:
|
|
148
|
+
```bash
|
|
149
|
+
git -C "$CONFIG_DIR" log --diff-filter=A --format="%H" -- "{file_path}"
|
|
150
|
+
```
|
|
151
|
+
This gives the commit that first added the file (the install commit). Extract the pristine version:
|
|
152
|
+
```bash
|
|
153
|
+
git -C "$CONFIG_DIR" show {install_commit}:{file_path}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Option B: Pristine snapshot directory
|
|
157
|
+
Check if a `gsd-pristine/` directory exists alongside `gsd-local-patches/`:
|
|
158
|
+
```bash
|
|
159
|
+
PRISTINE_DIR="$CONFIG_DIR/gsd-pristine"
|
|
160
|
+
```
|
|
161
|
+
If it exists, the installer saved pristine copies at install time. Use these as the baseline.
|
|
162
|
+
|
|
163
|
+
### Option C: No baseline available (two-way fallback)
|
|
164
|
+
If neither git history nor pristine snapshots are available, fall back to two-way comparison — but with **strengthened heuristics** (see Step 3).
|
|
165
|
+
|
|
166
|
+
## Step 3: Show patch summary
|
|
58
167
|
|
|
59
168
|
```
|
|
60
169
|
## Local Patches to Reapply
|
|
@@ -62,6 +171,7 @@ Exit.
|
|
|
62
171
|
**Backed up from:** v{from_version}
|
|
63
172
|
**Current version:** {read VERSION file}
|
|
64
173
|
**Files modified:** {count}
|
|
174
|
+
**Merge strategy:** {three-way (git) | three-way (pristine) | two-way (enhanced)}
|
|
65
175
|
|
|
66
176
|
| # | File | Status |
|
|
67
177
|
|---|------|--------|
|
|
@@ -69,37 +179,57 @@ Exit.
|
|
|
69
179
|
| 2 | {file_path} | Pending |
|
|
70
180
|
```
|
|
71
181
|
|
|
72
|
-
## Step
|
|
182
|
+
## Step 4: Merge each file
|
|
73
183
|
|
|
74
184
|
For each file in `backup-meta.json`:
|
|
75
185
|
|
|
76
186
|
1. **read the backed-up version** (user's modified copy from `gsd-local-patches/`)
|
|
77
187
|
2. **read the newly installed version** (current file after update)
|
|
78
|
-
3. **
|
|
188
|
+
3. **If available, read the pristine baseline** (from git history or `gsd-pristine/`)
|
|
79
189
|
|
|
80
|
-
|
|
81
|
-
- If the new file differs: identify the user's modifications and apply them to the new version
|
|
190
|
+
### Three-way merge (when baseline is available)
|
|
82
191
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- Apply user's additions/modifications to the new version
|
|
87
|
-
- If a section the user modified was also changed upstream: flag as conflict, show both versions, ask user which to keep
|
|
192
|
+
Compare the three versions to isolate changes:
|
|
193
|
+
- **User changes** = diff(pristine → user's version) — these are the customizations to preserve
|
|
194
|
+
- **Upstream changes** = diff(pristine → new version) — these are version updates to accept
|
|
88
195
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
196
|
+
**Merge rules:**
|
|
197
|
+
- Sections changed only by user → apply user's version
|
|
198
|
+
- Sections changed only by upstream → accept upstream version
|
|
199
|
+
- Sections changed by both → flag as CONFLICT, show both, ask user
|
|
200
|
+
- Sections unchanged by either → use new version (identical to all three)
|
|
94
201
|
|
|
95
|
-
|
|
202
|
+
### Two-way merge (fallback when no baseline)
|
|
96
203
|
|
|
97
|
-
|
|
204
|
+
When no pristine baseline is available, use these **strengthened heuristics**:
|
|
98
205
|
|
|
206
|
+
**CRITICAL RULE: Every file in this backup directory was explicitly detected as modified by the installer's SHA-256 hash comparison. "No custom content" is never a valid conclusion.**
|
|
207
|
+
|
|
208
|
+
For each file:
|
|
209
|
+
a. read both versions completely
|
|
210
|
+
b. Identify ALL differences, then classify each as:
|
|
211
|
+
- **Mechanical drift** — path substitutions (e.g. `/Users/xxx/.OpenCode/` → `$HOME/.OpenCode/`), variable additions (`${GSD_WS}`, `${AGENT_SKILLS_*}`), error handling additions (`|| true`)
|
|
212
|
+
- **User customization** — added steps/sections, removed sections, reordered content, changed behavior, added frontmatter fields, modified instructions
|
|
213
|
+
|
|
214
|
+
c. **If ANY differences remain after filtering out mechanical drift → those are user customizations. Merge them.**
|
|
215
|
+
d. **If ALL differences appear to be mechanical drift → still flag as CONFLICT.** The installer's hash check already proved this file was modified. Ask the user: "This file appears to only have path/variable differences. Were there intentional customizations?" Do NOT silently skip.
|
|
216
|
+
|
|
217
|
+
### Git-enhanced two-way merge
|
|
218
|
+
|
|
219
|
+
When the config directory is a git repo but the pristine install commit can't be found, use commit history to identify user changes:
|
|
99
220
|
```bash
|
|
100
|
-
#
|
|
101
|
-
|
|
221
|
+
# Find non-update commits that touched this file
|
|
222
|
+
git -C "$CONFIG_DIR" log --oneline --no-merges -- "{file_path}" | grep -v "gsd:update\|GSD update\|gsd-install"
|
|
102
223
|
```
|
|
224
|
+
Each matching commit represents an intentional user modification. Use the commit messages and diffs to understand what was changed and why.
|
|
225
|
+
|
|
226
|
+
4. **write merged result** to the installed location
|
|
227
|
+
5. **Report status per file:**
|
|
228
|
+
- `Merged` — user modifications applied cleanly (show summary of what was preserved)
|
|
229
|
+
- `Conflict` — user reviewed and chose resolution
|
|
230
|
+
- `Incorporated` — user's modification was already adopted upstream (only valid when pristine baseline confirms this)
|
|
231
|
+
|
|
232
|
+
**Never report `Skipped — no custom content`.** If a file is in the backup, it has custom content.
|
|
103
233
|
|
|
104
234
|
## Step 5: Cleanup option
|
|
105
235
|
|
|
@@ -112,11 +242,11 @@ Ask user:
|
|
|
112
242
|
```
|
|
113
243
|
## Patches Reapplied
|
|
114
244
|
|
|
115
|
-
| # | File |
|
|
116
|
-
|
|
117
|
-
| 1 | {file_path} |
|
|
118
|
-
| 2 | {file_path} |
|
|
119
|
-
| 3 | {file_path} |
|
|
245
|
+
| # | File | Result | User Changes Preserved |
|
|
246
|
+
|---|------|--------|----------------------|
|
|
247
|
+
| 1 | {file_path} | Merged | Added step X, modified section Y |
|
|
248
|
+
| 2 | {file_path} | Incorporated | Already in upstream v{version} |
|
|
249
|
+
| 3 | {file_path} | Conflict resolved | User chose: keep custom section |
|
|
120
250
|
|
|
121
251
|
{count} file(s) updated. Your local modifications are active again.
|
|
122
252
|
```
|
|
@@ -124,8 +254,10 @@ Ask user:
|
|
|
124
254
|
</process>
|
|
125
255
|
|
|
126
256
|
<success_criteria>
|
|
127
|
-
- [ ] All backed-up patches processed
|
|
128
|
-
- [ ]
|
|
129
|
-
- [ ]
|
|
130
|
-
- [ ]
|
|
257
|
+
- [ ] All backed-up patches processed — zero files left unhandled
|
|
258
|
+
- [ ] No file classified as "no custom content" or "SKIP" — every backed-up file is definitionally modified
|
|
259
|
+
- [ ] Three-way merge used when pristine baseline available (git history or gsd-pristine/)
|
|
260
|
+
- [ ] User modifications identified and merged into new version
|
|
261
|
+
- [ ] Conflicts surfaced to user with both versions shown
|
|
262
|
+
- [ ] Status reported for each file with summary of what was preserved
|
|
131
263
|
</success_criteria>
|
|
@@ -140,12 +140,7 @@ write to: .planning/phases/${PHASE}-{slug}/${PHASE}-RESEARCH.md
|
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
```
|
|
143
|
-
|
|
144
|
-
prompt=filled_prompt,
|
|
145
|
-
subagent_type="gsd-phase-researcher",
|
|
146
|
-
model="{researcher_model}",
|
|
147
|
-
description="Research Phase {phase}"
|
|
148
|
-
)
|
|
143
|
+
@gsd-phase-researcher filled_prompt
|
|
149
144
|
```
|
|
150
145
|
|
|
151
146
|
## 5. Handle Agent Return
|
|
@@ -176,12 +171,7 @@ Continue research for Phase {phase_number}: {phase_name}
|
|
|
176
171
|
```
|
|
177
172
|
|
|
178
173
|
```
|
|
179
|
-
|
|
180
|
-
prompt=continuation_prompt,
|
|
181
|
-
subagent_type="gsd-phase-researcher",
|
|
182
|
-
model="{researcher_model}",
|
|
183
|
-
description="Continue research Phase {phase}"
|
|
184
|
-
)
|
|
174
|
+
@gsd-phase-researcher continuation_prompt
|
|
185
175
|
```
|
|
186
176
|
|
|
187
177
|
</process>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsd-review
|
|
3
3
|
description: Request cross-AI peer review of phase plans from external AI CLIs
|
|
4
|
-
argument-hint: "--phase N [--gemini] [--OpenCode] [--codex] [--all]"
|
|
4
|
+
argument-hint: "--phase N [--gemini] [--OpenCode] [--codex] [--opencode] [--all]"
|
|
5
5
|
permissions:
|
|
6
6
|
read: true
|
|
7
7
|
write: true
|
|
@@ -11,7 +11,7 @@ permissions:
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
<objective>
|
|
14
|
-
Invoke external AI CLIs (Gemini, OpenCode, Codex) to independently review phase plans.
|
|
14
|
+
Invoke external AI CLIs (Gemini, OpenCode, Codex, OpenCode) to independently review phase plans.
|
|
15
15
|
Produces a structured REVIEWS.md with per-reviewer feedback that can be fed back into
|
|
16
16
|
planning via /gsd-plan-phase --reviews.
|
|
17
17
|
|
|
@@ -29,6 +29,7 @@ Phase number: extracted from $ARGUMENTS (required)
|
|
|
29
29
|
- `--gemini` — Include Gemini CLI review
|
|
30
30
|
- `--OpenCode` — Include OpenCode CLI review (uses separate session)
|
|
31
31
|
- `--codex` — Include Codex CLI review
|
|
32
|
+
- `--opencode` — Include OpenCode review (uses model from user's OpenCode config)
|
|
32
33
|
- `--all` — Include all available CLIs
|
|
33
34
|
</context>
|
|
34
35
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gsd-secure-phase
|
|
3
|
+
description: Retroactively verify threat mitigations for a completed phase
|
|
4
|
+
argument-hint: "[phase number]"
|
|
5
|
+
permissions:
|
|
6
|
+
read: true
|
|
7
|
+
write: true
|
|
8
|
+
edit: true
|
|
9
|
+
bash: true
|
|
10
|
+
glob: true
|
|
11
|
+
grep: true
|
|
12
|
+
task: true
|
|
13
|
+
question: true
|
|
14
|
+
---
|
|
15
|
+
<objective>
|
|
16
|
+
Verify threat mitigations for a completed phase. Three states:
|
|
17
|
+
- (A) SECURITY.md exists — audit and verify mitigations
|
|
18
|
+
- (B) No SECURITY.md, PLAN.md with threat model exists — run from artifacts
|
|
19
|
+
- (C) Phase not executed — exit with guidance
|
|
20
|
+
|
|
21
|
+
Output: updated SECURITY.md.
|
|
22
|
+
</objective>
|
|
23
|
+
|
|
24
|
+
<execution_context>
|
|
25
|
+
@$HOME/.config/opencode/get-shit-done/workflows/secure-phase.md
|
|
26
|
+
</execution_context>
|
|
27
|
+
|
|
28
|
+
<context>
|
|
29
|
+
Phase: $ARGUMENTS — optional, defaults to last completed phase.
|
|
30
|
+
</context>
|
|
31
|
+
|
|
32
|
+
<process>
|
|
33
|
+
Execute @$HOME/.config/opencode/get-shit-done/workflows/secure-phase.md.
|
|
34
|
+
Preserve all workflow gates.
|
|
35
|
+
</process>
|
|
@@ -62,7 +62,7 @@ Create a new thread:
|
|
|
62
62
|
|
|
63
63
|
1. Generate slug from description:
|
|
64
64
|
```bash
|
|
65
|
-
SLUG=$(node "$HOME/.config/opencode/get-shit-done/bin/gsd-tools.cjs" generate-slug "$ARGUMENTS")
|
|
65
|
+
SLUG=$(node "$HOME/.config/opencode/get-shit-done/bin/gsd-tools.cjs" generate-slug "$ARGUMENTS" --raw)
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
2. Create the threads directory if needed:
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsd-workstreams
|
|
3
3
|
description: Manage parallel workstreams — list, create, switch, status, progress, complete, and resume
|
|
4
|
+
permissions:
|
|
5
|
+
read: true
|
|
6
|
+
bash: true
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# /gsd-workstreams
|
|
7
10
|
|
|
8
11
|
<objective>
|
|
9
|
-
Manage parallel workstreams for concurrent milestone work.
|
|
12
|
+
Manage parallel workstreams for concurrent milestone work.
|
|
10
13
|
</objective>
|
|
11
14
|
|
|
12
15
|
## Usage
|
|
@@ -47,7 +50,9 @@ Display detailed phase breakdown and state information.
|
|
|
47
50
|
|
|
48
51
|
### switch
|
|
49
52
|
Run: `node "$GSD_TOOLS" workstream set <name> --raw --cwd "$CWD"`
|
|
50
|
-
Also set `GSD_WORKSTREAM`
|
|
53
|
+
Also set `GSD_WORKSTREAM` for the current session when the runtime supports it.
|
|
54
|
+
If the runtime exposes a session identifier, GSD also stores the active workstream
|
|
55
|
+
session-locally so concurrent sessions do not overwrite each other.
|
|
51
56
|
|
|
52
57
|
### progress
|
|
53
58
|
Run: `node "$GSD_TOOLS" workstream progress --raw --cwd "$CWD"`
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
* verify commits <h1> [h2] ... Batch verify commit hashes
|
|
94
94
|
* verify artifacts <plan-file> Check must_haves.artifacts
|
|
95
95
|
* verify key-links <plan-file> Check must_haves.key_links
|
|
96
|
+
* verify schema-drift <phase> [--skip] Detect schema file changes without push
|
|
96
97
|
*
|
|
97
98
|
* Template Fill:
|
|
98
99
|
* template fill summary --phase N Create pre-filled SUMMARY.md
|
|
@@ -133,6 +134,9 @@
|
|
|
133
134
|
* init milestone-op All context for milestone operations
|
|
134
135
|
* init map-codebase All context for map-codebase workflow
|
|
135
136
|
* init progress All context for progress workflow
|
|
137
|
+
*
|
|
138
|
+
* Documentation:
|
|
139
|
+
* docs-init Project context for docs-update workflow
|
|
136
140
|
*/
|
|
137
141
|
|
|
138
142
|
const fs = require('fs');
|
|
@@ -152,6 +156,7 @@ const frontmatter = require('./lib/frontmatter.cjs');
|
|
|
152
156
|
const profilePipeline = require('./lib/profile-pipeline.cjs');
|
|
153
157
|
const profileOutput = require('./lib/profile-output.cjs');
|
|
154
158
|
const workstream = require('./lib/workstream.cjs');
|
|
159
|
+
const docs = require('./lib/docs.cjs');
|
|
155
160
|
|
|
156
161
|
// ─── Arg parsing helpers ──────────────────────────────────────────────────────
|
|
157
162
|
|
|
@@ -230,7 +235,7 @@ async function main() {
|
|
|
230
235
|
}
|
|
231
236
|
|
|
232
237
|
// Optional workstream override for parallel milestone work.
|
|
233
|
-
// Priority: --ws flag > GSD_WORKSTREAM env var >
|
|
238
|
+
// Priority: --ws flag > GSD_WORKSTREAM env var > session-scoped pointer > shared legacy pointer > null
|
|
234
239
|
const wsEqArg = args.find(arg => arg.startsWith('--ws='));
|
|
235
240
|
const wsIdx = args.indexOf('--ws');
|
|
236
241
|
let ws = null;
|
|
@@ -274,7 +279,7 @@ async function main() {
|
|
|
274
279
|
const command = args[0];
|
|
275
280
|
|
|
276
281
|
if (!command) {
|
|
277
|
-
error('Usage: gsd-tools <command> [args] [--raw] [--pick <field>] [--cwd <path>] [--ws <name>]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, config-new-project, init, workstream');
|
|
282
|
+
error('Usage: gsd-tools <command> [args] [--raw] [--pick <field>] [--cwd <path>] [--ws <name>]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, config-new-project, init, workstream, docs-init');
|
|
278
283
|
}
|
|
279
284
|
|
|
280
285
|
// Multi-repo guard: resolve project root for commands that read/write .planning/.
|
|
@@ -394,6 +399,14 @@ async function runCommand(command, args, cwd, raw) {
|
|
|
394
399
|
state.cmdSignalWaiting(cwd, type, question, options, p, raw);
|
|
395
400
|
} else if (subcommand === 'signal-resume') {
|
|
396
401
|
state.cmdSignalResume(cwd, raw);
|
|
402
|
+
} else if (subcommand === 'planned-phase') {
|
|
403
|
+
const { phase: p, name, plans } = parseNamedArgs(args, ['phase', 'name', 'plans']);
|
|
404
|
+
state.cmdStatePlannedPhase(cwd, p, plans !== null ? parseInt(plans, 10) : null, raw);
|
|
405
|
+
} else if (subcommand === 'validate') {
|
|
406
|
+
state.cmdStateValidate(cwd, raw);
|
|
407
|
+
} else if (subcommand === 'sync') {
|
|
408
|
+
const { verify } = parseNamedArgs(args, [], ['verify']);
|
|
409
|
+
state.cmdStateSync(cwd, { verify }, raw);
|
|
397
410
|
} else {
|
|
398
411
|
state.cmdStateLoad(cwd, raw);
|
|
399
412
|
}
|
|
@@ -425,6 +438,11 @@ async function runCommand(command, args, cwd, raw) {
|
|
|
425
438
|
break;
|
|
426
439
|
}
|
|
427
440
|
|
|
441
|
+
case 'check-commit': {
|
|
442
|
+
commands.cmdCheckCommit(cwd, raw);
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
|
|
428
446
|
case 'commit-to-subrepo': {
|
|
429
447
|
const message = args[1];
|
|
430
448
|
const filesIndex = args.indexOf('--files');
|
|
@@ -498,8 +516,11 @@ async function runCommand(command, args, cwd, raw) {
|
|
|
498
516
|
verify.cmdVerifyArtifacts(cwd, args[2], raw);
|
|
499
517
|
} else if (subcommand === 'key-links') {
|
|
500
518
|
verify.cmdVerifyKeyLinks(cwd, args[2], raw);
|
|
519
|
+
} else if (subcommand === 'schema-drift') {
|
|
520
|
+
const skipFlag = args.includes('--skip');
|
|
521
|
+
verify.cmdVerifySchemaDrift(cwd, args[2], skipFlag, raw);
|
|
501
522
|
} else {
|
|
502
|
-
error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links');
|
|
523
|
+
error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links, schema-drift');
|
|
503
524
|
}
|
|
504
525
|
break;
|
|
505
526
|
}
|
|
@@ -570,8 +591,10 @@ async function runCommand(command, args, cwd, raw) {
|
|
|
570
591
|
includeArchived: args.includes('--include-archived'),
|
|
571
592
|
};
|
|
572
593
|
phase.cmdPhasesList(cwd, options, raw);
|
|
594
|
+
} else if (subcommand === 'clear') {
|
|
595
|
+
milestone.cmdPhasesClear(cwd, raw);
|
|
573
596
|
} else {
|
|
574
|
-
error('Unknown phases subcommand. Available: list');
|
|
597
|
+
error('Unknown phases subcommand. Available: list, clear');
|
|
575
598
|
}
|
|
576
599
|
break;
|
|
577
600
|
}
|
|
@@ -712,12 +735,16 @@ async function runCommand(command, args, cwd, raw) {
|
|
|
712
735
|
case 'init': {
|
|
713
736
|
const workflow = args[1];
|
|
714
737
|
switch (workflow) {
|
|
715
|
-
case 'execute-phase':
|
|
716
|
-
|
|
738
|
+
case 'execute-phase': {
|
|
739
|
+
const { validate: epValidate } = parseNamedArgs(args, [], ['validate']);
|
|
740
|
+
init.cmdInitExecutePhase(cwd, args[2], raw, { validate: epValidate });
|
|
717
741
|
break;
|
|
718
|
-
|
|
719
|
-
|
|
742
|
+
}
|
|
743
|
+
case 'plan-phase': {
|
|
744
|
+
const { validate: ppValidate } = parseNamedArgs(args, [], ['validate']);
|
|
745
|
+
init.cmdInitPlanPhase(cwd, args[2], raw, { validate: ppValidate });
|
|
720
746
|
break;
|
|
747
|
+
}
|
|
721
748
|
case 'new-project':
|
|
722
749
|
init.cmdInitNewProject(cwd, raw);
|
|
723
750
|
break;
|
|
@@ -910,6 +937,13 @@ async function runCommand(command, args, cwd, raw) {
|
|
|
910
937
|
break;
|
|
911
938
|
}
|
|
912
939
|
|
|
940
|
+
// ─── Documentation ────────────────────────────────────────────────────
|
|
941
|
+
|
|
942
|
+
case 'docs-init': {
|
|
943
|
+
docs.cmdDocsInit(cwd, raw);
|
|
944
|
+
break;
|
|
945
|
+
}
|
|
946
|
+
|
|
913
947
|
default:
|
|
914
948
|
error(`Unknown command: ${command}`);
|
|
915
949
|
}
|