pi-gsd 1.1.0 → 1.2.2
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/.gsd/extensions/gsd-hooks.ts +212 -212
- package/README.md +45 -44
- package/dist/{gsd-tools.js → pi-gsd-tools.js} +54 -54
- package/package.json +6 -6
- package/scripts/postinstall.js +253 -293
- package/skills/gsd-add-backlog/SKILL.md +3 -3
- package/skills/gsd-add-phase/SKILL.md +2 -2
- package/skills/gsd-add-tests/SKILL.md +2 -2
- package/skills/gsd-add-todo/SKILL.md +2 -2
- package/skills/gsd-audit-milestone/SKILL.md +2 -2
- package/skills/gsd-audit-uat/SKILL.md +1 -1
- package/skills/gsd-autonomous/SKILL.md +4 -4
- package/skills/gsd-check-todos/SKILL.md +2 -2
- package/skills/gsd-cleanup/SKILL.md +2 -2
- package/skills/gsd-complete-milestone/SKILL.md +2 -2
- package/skills/gsd-debug/SKILL.md +2 -2
- package/skills/gsd-discuss-phase/SKILL.md +6 -6
- package/skills/gsd-do/SKILL.md +3 -3
- package/skills/gsd-execute-phase/SKILL.md +4 -4
- package/skills/gsd-fast/SKILL.md +2 -2
- package/skills/gsd-forensics/SKILL.md +2 -2
- package/skills/gsd-health/SKILL.md +4 -4
- package/skills/gsd-help/SKILL.md +2 -2
- package/skills/gsd-insert-phase/SKILL.md +2 -2
- package/skills/gsd-list-phase-assumptions/SKILL.md +1 -1
- package/skills/gsd-list-workspaces/SKILL.md +3 -3
- package/skills/gsd-manager/SKILL.md +4 -4
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-milestone-summary/SKILL.md +2 -2
- package/skills/gsd-new-milestone/SKILL.md +6 -6
- package/skills/gsd-new-project/SKILL.md +6 -6
- package/skills/gsd-new-workspace/SKILL.md +3 -3
- package/skills/gsd-next/SKILL.md +2 -2
- package/skills/gsd-note/SKILL.md +3 -3
- package/skills/gsd-pause-work/SKILL.md +2 -2
- package/skills/gsd-plan-milestone-gaps/SKILL.md +2 -2
- package/skills/gsd-plan-phase/SKILL.md +3 -3
- package/skills/gsd-plant-seed/SKILL.md +2 -2
- package/skills/gsd-pr-branch/SKILL.md +2 -2
- package/skills/gsd-profile-user/SKILL.md +2 -2
- package/skills/gsd-progress/SKILL.md +4 -4
- package/skills/gsd-quick/SKILL.md +2 -2
- package/skills/gsd-remove-phase/SKILL.md +2 -2
- package/skills/gsd-remove-workspace/SKILL.md +3 -3
- package/skills/gsd-research-phase/SKILL.md +3 -3
- package/skills/gsd-resume-work/SKILL.md +2 -2
- package/skills/gsd-review/SKILL.md +2 -2
- package/skills/gsd-review-backlog/SKILL.md +2 -2
- package/skills/gsd-session-report/SKILL.md +2 -2
- package/skills/gsd-set-profile/SKILL.md +1 -1
- package/skills/gsd-settings/SKILL.md +2 -2
- package/skills/gsd-setup-pi/SKILL.md +15 -13
- package/skills/gsd-ship/SKILL.md +2 -2
- package/skills/gsd-stats/SKILL.md +4 -4
- package/skills/gsd-thread/SKILL.md +2 -2
- package/skills/gsd-ui-phase/SKILL.md +3 -3
- package/skills/gsd-ui-review/SKILL.md +3 -3
- package/skills/gsd-update/SKILL.md +2 -2
- package/skills/gsd-validate-phase/SKILL.md +2 -2
- package/skills/gsd-verify-work/SKILL.md +3 -3
- package/skills/gsd-workstreams/SKILL.md +1 -1
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-gsd",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Get Shit Done - Unofficial port of the renowned AI-native project-planning spec-driven toolkit",
|
|
5
|
-
"main": "dist/gsd-tools.js",
|
|
5
|
+
"main": "dist/pi-gsd-tools.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"gsd-tools": "./dist/gsd-tools.js",
|
|
8
|
-
"pi-gsd": "./dist/gsd-tools.js"
|
|
7
|
+
"pi-gsd-tools": "./dist/pi-gsd-tools.js",
|
|
8
|
+
"pi-gsd": "./dist/pi-gsd-tools.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsup src/cli.ts --format cjs --out-dir dist --minify --no-splitting && mv dist/cli.js dist/gsd-tools.js && chmod +x dist/gsd-tools.js",
|
|
11
|
+
"build": "tsup src/cli.ts --format cjs --out-dir dist --minify --no-splitting && mv dist/cli.js dist/pi-gsd-tools.js && chmod +x dist/pi-gsd-tools.js",
|
|
12
12
|
"dev": "tsup src/cli.ts --format cjs --out-dir dist --watch",
|
|
13
13
|
"typecheck": "tsc --noEmit",
|
|
14
14
|
"postinstall": "node scripts/postinstall.js",
|
|
15
|
-
"prepublishOnly": "npm run build
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"skills",
|
package/scripts/postinstall.js
CHANGED
|
@@ -2,32 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* postinstall.js - GSD harness installer
|
|
4
4
|
*
|
|
5
|
-
* Runs automatically after `npm install
|
|
6
|
-
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* and CLI binary at the expected platform-native paths.
|
|
5
|
+
* Runs automatically after `npm install pi-gsd`.
|
|
6
|
+
* Copies the pi harness from this package's
|
|
7
|
+
* \`.gsd/harnesses/pi/\` into the consumer project's \`.pi/gsd/\`
|
|
8
|
+
* and installs the \`gsd-hooks.ts\` extension into \`.pi/extensions/\`.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
* .gsd/harnesses/
|
|
13
|
-
* agent/ → consumer project root: .agent/get-shit-done/
|
|
14
|
-
* claude/ → consumer project root: .claude/get-shit-done/
|
|
15
|
-
* codex/ → consumer project root: .codex/get-shit-done/
|
|
16
|
-
* cursor/ → consumer project root: .cursor/get-shit-done/
|
|
17
|
-
* gemini/ → consumer project root: .gemini/get-shit-done/
|
|
18
|
-
* github/ → consumer project root: .github/get-shit-done/
|
|
19
|
-
* opencode/ → consumer project root: .opencode/get-shit-done/
|
|
20
|
-
* windsurf/ → consumer project root: .windsurf/get-shit-done/
|
|
21
|
-
*
|
|
22
|
-
* Hook files are also copied from `.gsd/hooks/` into each harness
|
|
23
|
-
* that supports the GSD hook system.
|
|
24
|
-
*
|
|
25
|
-
* The script is intentionally defensive: it never overwrites files
|
|
26
|
-
* that already exist (use --force-reinstall env flag to override),
|
|
27
|
-
* and it skips silently if a harness source directory is absent
|
|
28
|
-
* from the package (forward-compatibility).
|
|
29
|
-
*
|
|
30
|
-
* @see README.md §3 (Installation) for usage details.
|
|
10
|
+
* Safe to re-run — files are skipped if already present (unless GSD_FORCE=1).
|
|
31
11
|
*/
|
|
32
12
|
|
|
33
13
|
const fs = require("fs");
|
|
@@ -36,8 +16,8 @@ const path = require("path");
|
|
|
36
16
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
37
17
|
|
|
38
18
|
const FORCE =
|
|
39
|
-
|
|
40
|
-
|
|
19
|
+
process.env.GSD_FORCE_REINSTALL === "1" ||
|
|
20
|
+
process.argv.includes("--force-reinstall");
|
|
41
21
|
|
|
42
22
|
/**
|
|
43
23
|
* Directory that contains this package's files.
|
|
@@ -61,22 +41,14 @@ const PROJECT_ROOT = process.env.INIT_CWD || process.cwd();
|
|
|
61
41
|
* hooks - whether this platform supports GSD hooks (copied from .gsd/hooks/)
|
|
62
42
|
*/
|
|
63
43
|
const HARNESSES = [
|
|
64
|
-
{ src: "
|
|
65
|
-
{ src: "agent", dest: ".pi", hooks: true },
|
|
66
|
-
{ src: "claude", dest: ".claude", hooks: true },
|
|
67
|
-
{ src: "codex", dest: ".codex", hooks: false },
|
|
68
|
-
{ src: "cursor", dest: ".cursor", hooks: false },
|
|
69
|
-
{ src: "gemini", dest: ".gemini", hooks: true },
|
|
70
|
-
{ src: "github", dest: ".github", hooks: false },
|
|
71
|
-
{ src: "opencode", dest: ".opencode", hooks: true },
|
|
72
|
-
{ src: "windsurf", dest: ".windsurf", hooks: false },
|
|
44
|
+
{ src: "pi", dest: ".pi", hooks: true, subdir: "gsd" },
|
|
73
45
|
];
|
|
74
46
|
|
|
75
47
|
/**
|
|
76
48
|
* Subdirectory name used inside each harness's dest folder for
|
|
77
49
|
* GSD-specific content (workflows, bin, references, templates …).
|
|
78
50
|
*/
|
|
79
|
-
|
|
51
|
+
// subdir is now per-harness (see harness config above)
|
|
80
52
|
|
|
81
53
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
82
54
|
|
|
@@ -90,32 +62,32 @@ const GSD_SUBDIR = "get-shit-done";
|
|
|
90
62
|
* @returns {{ copied: number, skipped: number }}
|
|
91
63
|
*/
|
|
92
64
|
function copyDir(src, dest, overwrite) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
65
|
+
let copied = 0;
|
|
66
|
+
let skipped = 0;
|
|
67
|
+
|
|
68
|
+
if (!fs.existsSync(src)) return { copied, skipped };
|
|
69
|
+
|
|
70
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
71
|
+
|
|
72
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
73
|
+
const srcEntry = path.join(src, entry.name);
|
|
74
|
+
const destEntry = path.join(dest, entry.name);
|
|
75
|
+
|
|
76
|
+
if (entry.isDirectory()) {
|
|
77
|
+
const sub = copyDir(srcEntry, destEntry, overwrite);
|
|
78
|
+
copied += sub.copied;
|
|
79
|
+
skipped += sub.skipped;
|
|
80
|
+
} else if (entry.isFile()) {
|
|
81
|
+
if (!overwrite && fs.existsSync(destEntry)) {
|
|
82
|
+
skipped++;
|
|
83
|
+
} else {
|
|
84
|
+
fs.copyFileSync(srcEntry, destEntry);
|
|
85
|
+
copied++;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { copied, skipped };
|
|
119
91
|
}
|
|
120
92
|
|
|
121
93
|
/**
|
|
@@ -126,168 +98,156 @@ function copyDir(src, dest, overwrite) {
|
|
|
126
98
|
* @param {string} msg
|
|
127
99
|
*/
|
|
128
100
|
function log(level, msg) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
101
|
+
const isTTY = process.stdout.isTTY;
|
|
102
|
+
const colours = {
|
|
103
|
+
ok: isTTY ? "\x1b[32m✓\x1b[0m" : "✓",
|
|
104
|
+
skip: isTTY ? "\x1b[33m–\x1b[0m" : "–",
|
|
105
|
+
warn: isTTY ? "\x1b[33m⚠\x1b[0m" : "⚠",
|
|
106
|
+
err: isTTY ? "\x1b[31m✗\x1b[0m" : "✗",
|
|
107
|
+
};
|
|
108
|
+
console.log(` ${colours[level] || " "} ${msg}`);
|
|
137
109
|
}
|
|
138
110
|
|
|
139
111
|
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
140
112
|
|
|
141
113
|
function main() {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
console.log(
|
|
280
|
-
" • Claude Code (.agent): run /gsd-new-project",
|
|
281
|
-
);
|
|
282
|
-
console.log(
|
|
283
|
-
" • Codex: run $gsd-new-project",
|
|
284
|
-
);
|
|
285
|
-
console.log(
|
|
286
|
-
" • GitHub Copilot: run /gsd:new-project",
|
|
287
|
-
);
|
|
288
|
-
console.log("");
|
|
289
|
-
console.log(" Docs: https://github.com/fulgidus/pi-gsd#readme");
|
|
290
|
-
console.log("");
|
|
114
|
+
// Skip when running inside the package's own development tree
|
|
115
|
+
// (i.e. when INIT_CWD === the package directory itself).
|
|
116
|
+
if (path.resolve(PROJECT_ROOT) === path.resolve(PKG_DIR)) {
|
|
117
|
+
log(
|
|
118
|
+
"skip",
|
|
119
|
+
"Running inside package source tree - skipping harness install.",
|
|
120
|
+
);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Skip when explicitly opted out
|
|
125
|
+
if (process.env.GSD_SKIP_INSTALL === "1") {
|
|
126
|
+
log("skip", "GSD_SKIP_INSTALL=1 - skipping harness install.");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const harnessesRoot = path.join(PKG_DIR, ".gsd", "harnesses");
|
|
131
|
+
const hooksRoot = path.join(PKG_DIR, ".gsd", "hooks");
|
|
132
|
+
|
|
133
|
+
console.log("");
|
|
134
|
+
console.log(" GSD - installing harness files into your project…");
|
|
135
|
+
if (FORCE)
|
|
136
|
+
console.log(" (force-reinstall mode: existing files will be overwritten)");
|
|
137
|
+
console.log("");
|
|
138
|
+
|
|
139
|
+
let totalCopied = 0;
|
|
140
|
+
let totalSkipped = 0;
|
|
141
|
+
let installed = 0;
|
|
142
|
+
|
|
143
|
+
for (const harness of HARNESSES) {
|
|
144
|
+
const srcHarness = path.join(harnessesRoot, harness.src);
|
|
145
|
+
const destHarness = path.join(PROJECT_ROOT, harness.dest);
|
|
146
|
+
|
|
147
|
+
// ── get-shit-done/ content ──────────────────────────────────────────────
|
|
148
|
+
const srcGsd = path.join(srcHarness, harness.subdir);
|
|
149
|
+
const destGsd = path.join(destHarness, harness.subdir);
|
|
150
|
+
|
|
151
|
+
if (!fs.existsSync(srcHarness)) {
|
|
152
|
+
log("skip", `${harness.dest}/${harness.subdir} (source absent - skipped)`);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const { copied, skipped } = copyDir(srcGsd, destGsd, FORCE);
|
|
157
|
+
totalCopied += copied;
|
|
158
|
+
totalSkipped += skipped;
|
|
159
|
+
|
|
160
|
+
if (copied > 0 || skipped === 0) {
|
|
161
|
+
log(
|
|
162
|
+
"ok",
|
|
163
|
+
`${harness.dest}/${harness.subdir} (${copied} file${copied === 1 ? "" : "s"} installed)`,
|
|
164
|
+
);
|
|
165
|
+
} else {
|
|
166
|
+
log(
|
|
167
|
+
"skip",
|
|
168
|
+
`${harness.dest}/${harness.subdir} (already up-to-date, ${skipped} file${skipped === 1 ? "" : "s"} skipped)`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ── gsd-file-manifest.json ──────────────────────────────────────────────
|
|
173
|
+
const manifestSrc = path.join(srcHarness, "gsd-file-manifest.json");
|
|
174
|
+
const manifestDest = path.join(destHarness, "gsd-file-manifest.json");
|
|
175
|
+
|
|
176
|
+
if (fs.existsSync(manifestSrc)) {
|
|
177
|
+
if (!FORCE && fs.existsSync(manifestDest)) {
|
|
178
|
+
totalSkipped++;
|
|
179
|
+
} else {
|
|
180
|
+
fs.mkdirSync(destHarness, { recursive: true });
|
|
181
|
+
fs.copyFileSync(manifestSrc, manifestDest);
|
|
182
|
+
totalCopied++;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ── hooks/ (platform-selective) ─────────────────────────────────────────
|
|
187
|
+
if (harness.hooks && fs.existsSync(hooksRoot)) {
|
|
188
|
+
const destHooks = path.join(destHarness, "hooks");
|
|
189
|
+
const h = copyDir(hooksRoot, destHooks, FORCE);
|
|
190
|
+
totalCopied += h.copied;
|
|
191
|
+
totalSkipped += h.skipped;
|
|
192
|
+
|
|
193
|
+
if (h.copied > 0) {
|
|
194
|
+
log(
|
|
195
|
+
"ok",
|
|
196
|
+
`${harness.dest}/hooks (${h.copied} hook${h.copied === 1 ? "" : "s"} installed)`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ── skills/ (opencode only - present in .gsd/harnesses/opencode/skills) ─
|
|
202
|
+
const srcSkills = path.join(srcHarness, "skills");
|
|
203
|
+
const destSkills = path.join(destHarness, "skills");
|
|
204
|
+
|
|
205
|
+
if (fs.existsSync(srcSkills)) {
|
|
206
|
+
const s = copyDir(srcSkills, destSkills, FORCE);
|
|
207
|
+
totalCopied += s.copied;
|
|
208
|
+
totalSkipped += s.skipped;
|
|
209
|
+
|
|
210
|
+
if (s.copied > 0) {
|
|
211
|
+
log(
|
|
212
|
+
"ok",
|
|
213
|
+
`${harness.dest}/skills (${s.copied} skill file${s.copied === 1 ? "" : "s"} installed)`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
installed++;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ── Pi extension (.pi/extensions/gsd-hooks.ts) ─────────────────────────────
|
|
222
|
+
// Install the GSD pi lifecycle extension (session_start, tool_call, tool_result hooks).
|
|
223
|
+
// The extension is auto-discovered by pi from .pi/extensions/ - no manual wiring needed.
|
|
224
|
+
installPiExtension(PROJECT_ROOT, PKG_DIR, FORCE, (copied) => {
|
|
225
|
+
if (copied) totalCopied++;
|
|
226
|
+
else totalSkipped++;
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
console.log("");
|
|
230
|
+
|
|
231
|
+
if (installed === 0) {
|
|
232
|
+
log("warn", "No harness source directories found inside the package.");
|
|
233
|
+
log(
|
|
234
|
+
"warn",
|
|
235
|
+
"The package may be incomplete. Try: npm install --force get-shit-done-cc",
|
|
236
|
+
);
|
|
237
|
+
console.log("");
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log(` GSD v${getPackageVersion()} installed successfully.`);
|
|
242
|
+
console.log(
|
|
243
|
+
` ${totalCopied} file${totalCopied === 1 ? "" : "s"} copied, ${totalSkipped} skipped.`,
|
|
244
|
+
);
|
|
245
|
+
console.log("");
|
|
246
|
+
console.log(" Next steps:");
|
|
247
|
+
console.log(" Run /gsd-new-project to initialise a project.");
|
|
248
|
+
console.log("");
|
|
249
|
+
console.log(" Docs: https://github.com/fulgidus/pi-gsd#readme");
|
|
250
|
+
console.log("");
|
|
291
251
|
}
|
|
292
252
|
|
|
293
253
|
/**
|
|
@@ -297,14 +257,14 @@ function main() {
|
|
|
297
257
|
* @returns {string}
|
|
298
258
|
*/
|
|
299
259
|
function getPackageVersion() {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
260
|
+
try {
|
|
261
|
+
const pkg = JSON.parse(
|
|
262
|
+
fs.readFileSync(path.join(PKG_DIR, "package.json"), "utf8"),
|
|
263
|
+
);
|
|
264
|
+
return pkg.version || "unknown";
|
|
265
|
+
} catch {
|
|
266
|
+
return "unknown";
|
|
267
|
+
}
|
|
308
268
|
}
|
|
309
269
|
|
|
310
270
|
/**
|
|
@@ -322,71 +282,71 @@ function getPackageVersion() {
|
|
|
322
282
|
* @param {function} callback Called with (copied: boolean)
|
|
323
283
|
*/
|
|
324
284
|
function installPiExtension(projectRoot, pkgDir, force, callback) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
285
|
+
const piDir = path.join(projectRoot, ".pi");
|
|
286
|
+
const extDir = path.join(piDir, "extensions");
|
|
287
|
+
const extDest = path.join(extDir, "gsd-hooks.ts");
|
|
288
|
+
const extSrc = path.join(pkgDir, ".gsd", "extensions", "gsd-hooks.ts");
|
|
289
|
+
|
|
290
|
+
if (!fs.existsSync(extSrc)) {
|
|
291
|
+
log("warn", ".pi/extensions/gsd-hooks.ts (source absent - skipped)");
|
|
292
|
+
callback(false);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (!force && fs.existsSync(extDest)) {
|
|
297
|
+
log("skip", ".pi/extensions/gsd-hooks.ts (already exists)");
|
|
298
|
+
callback(false);
|
|
299
|
+
} else {
|
|
300
|
+
try {
|
|
301
|
+
fs.mkdirSync(extDir, { recursive: true });
|
|
302
|
+
fs.copyFileSync(extSrc, extDest);
|
|
303
|
+
log(
|
|
304
|
+
"ok",
|
|
305
|
+
".pi/extensions/gsd-hooks.ts (GSD lifecycle extension installed)",
|
|
306
|
+
);
|
|
307
|
+
callback(true);
|
|
308
|
+
} catch (e) {
|
|
309
|
+
log(
|
|
310
|
+
"warn",
|
|
311
|
+
".pi/extensions/gsd-hooks.ts (install failed: " + e.message + ")",
|
|
312
|
+
);
|
|
313
|
+
callback(false);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Update .pi/settings.json to include the extension path in the extensions array.
|
|
319
|
+
// The file is already auto-discovered from .pi/extensions/, but explicit registration
|
|
320
|
+
// is added as a belt-and-suspenders measure.
|
|
321
|
+
const settingsFile = path.join(piDir, "settings.json");
|
|
322
|
+
try {
|
|
323
|
+
let settings = {};
|
|
324
|
+
if (fs.existsSync(settingsFile)) {
|
|
325
|
+
try {
|
|
326
|
+
settings = JSON.parse(fs.readFileSync(settingsFile, "utf8"));
|
|
327
|
+
} catch {
|
|
328
|
+
// Unreadable settings - start fresh object
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const extensions = Array.isArray(settings.extensions)
|
|
333
|
+
? settings.extensions
|
|
334
|
+
: [];
|
|
335
|
+
|
|
336
|
+
// Avoid duplicate entries
|
|
337
|
+
if (!extensions.includes(extDest)) {
|
|
338
|
+
settings.extensions = [...extensions, extDest];
|
|
339
|
+
fs.mkdirSync(piDir, { recursive: true });
|
|
340
|
+
fs.writeFileSync(
|
|
341
|
+
settingsFile,
|
|
342
|
+
JSON.stringify(settings, null, "\t"),
|
|
343
|
+
"utf8",
|
|
344
|
+
);
|
|
345
|
+
log("ok", ".pi/settings.json (extensions array updated)");
|
|
346
|
+
}
|
|
347
|
+
} catch (e) {
|
|
348
|
+
log("warn", ".pi/settings.json (could not update: " + e.message + ")");
|
|
349
|
+
}
|
|
390
350
|
}
|
|
391
351
|
|
|
392
352
|
main();
|
|
@@ -20,7 +20,7 @@ the normal phase sequence and accumulate context over time.
|
|
|
20
20
|
2. **Find next backlog number:**
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
NEXT=$(node ".pi/
|
|
23
|
+
NEXT=$(node ".pi/gsd/bin/pi-gsd-tools.cjs" phase next-decimal 999 --raw)
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
If no 999.x phases exist, start at 999.1.
|
|
@@ -28,7 +28,7 @@ the normal phase sequence and accumulate context over time.
|
|
|
28
28
|
3. **Create the phase directory:**
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
SLUG=$(node ".pi/
|
|
31
|
+
SLUG=$(node ".pi/gsd/bin/pi-gsd-tools.cjs" generate-slug "$ARGUMENTS")
|
|
32
32
|
mkdir -p ".planning/phases/${NEXT}-${SLUG}"
|
|
33
33
|
touch ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
|
|
34
34
|
```
|
|
@@ -52,7 +52,7 @@ the normal phase sequence and accumulate context over time.
|
|
|
52
52
|
5. **Commit:**
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
node ".pi/
|
|
55
|
+
node ".pi/gsd/bin/pi-gsd-tools.cjs" commit "docs: add backlog item ${NEXT} - ${ARGUMENTS}" --files .planning/ROADMAP.md ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
6. **Report:**
|