pi-gsd 1.6.1 → 1.6.3
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* gsd-hooks.ts
|
|
3
|
-
* gsd-extension-version: 1.
|
|
2
|
+
* pi-gsd-hooks.ts — pi-gsd Extension
|
|
3
|
+
* pi-gsd-extension-version: 1.6.2
|
|
4
4
|
*
|
|
5
5
|
* Pi lifecycle extension for the Get Shit Done (GSD) workflow framework.
|
|
6
6
|
* Provides three non-blocking hooks:
|
|
@@ -128,7 +128,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
128
128
|
/\.env/,
|
|
129
129
|
/AGENTS\.md$/,
|
|
130
130
|
/settings\.json$/,
|
|
131
|
-
/gsd-hooks\.ts$/,
|
|
131
|
+
/pi-gsd-hooks\.ts$/,
|
|
132
132
|
];
|
|
133
133
|
if (allowed.some((p) => p.test(filePath))) return undefined;
|
|
134
134
|
|
|
@@ -517,7 +517,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
517
517
|
},
|
|
518
518
|
});
|
|
519
519
|
|
|
520
|
-
|
|
521
520
|
// ── tool_result: context usage monitor ───────────────────────────────────
|
|
522
521
|
const WARNING_THRESHOLD = 35; // warn when remaining % ≤ 35
|
|
523
522
|
const CRITICAL_THRESHOLD = 25; // critical when remaining % ≤ 25
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Runs automatically after `npm install pi-gsd`.
|
|
6
6
|
* Copies the pi harness from this package's
|
|
7
7
|
* \`.gsd/harnesses/pi/\` into the consumer project's \`.pi/gsd/\`
|
|
8
|
-
* and installs the \`gsd-hooks.ts\` extension into \`.pi/extensions/\`.
|
|
8
|
+
* and installs the \`pi-gsd-hooks.ts\` extension into \`.pi/extensions/\`.
|
|
9
9
|
*
|
|
10
10
|
* Safe to re-run — files are skipped if already present (unless GSD_FORCE=1).
|
|
11
11
|
*/
|
|
@@ -219,7 +219,7 @@ function main() {
|
|
|
219
219
|
installed++;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
// ── Pi extension (.pi/extensions/gsd-hooks.ts) ─────────────────────────────
|
|
222
|
+
// ── Pi extension (.pi/extensions/pi-gsd-hooks.ts) ─────────────────────────────
|
|
223
223
|
// Install the GSD pi lifecycle extension (session_start, tool_call, tool_result hooks).
|
|
224
224
|
// The extension is auto-discovered by pi from .pi/extensions/ - no manual wiring needed.
|
|
225
225
|
installPiExtension(PROJECT_ROOT, PKG_DIR, FORCE, (copied) => {
|
|
@@ -227,19 +227,32 @@ function main() {
|
|
|
227
227
|
else totalSkipped++;
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
-
// ── Pi prompt templates
|
|
231
|
-
|
|
230
|
+
// ── Pi prompt templates — cleanup stale local copies ───────────────────────
|
|
231
|
+
// Prompts are served directly from the npm package (user scope).
|
|
232
|
+
// Local copies in .pi/prompts/ cause collision warnings on every pi update.
|
|
233
|
+
// Remove any gsd-*.md files previously installed there.
|
|
234
|
+
// Also remove the old gsd-hooks.ts if present (renamed to pi-gsd-hooks.ts).
|
|
232
235
|
const promptsDest = path.join(PROJECT_ROOT, ".pi", "prompts");
|
|
233
|
-
if (fs.existsSync(
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
236
|
+
if (fs.existsSync(promptsDest)) {
|
|
237
|
+
const stale = fs
|
|
238
|
+
.readdirSync(promptsDest)
|
|
239
|
+
.filter((f) => f.startsWith("gsd-") && f.endsWith(".md"));
|
|
240
|
+
if (stale.length > 0) {
|
|
241
|
+
for (const f of stale) fs.rmSync(path.join(promptsDest, f));
|
|
242
|
+
log(
|
|
243
|
+
"ok",
|
|
244
|
+
`.pi/prompts (removed ${stale.length} stale local gsd-*.md — served from package instead)`,
|
|
245
|
+
);
|
|
241
246
|
}
|
|
242
247
|
}
|
|
248
|
+
const oldExt = path.join(PROJECT_ROOT, ".pi", "extensions", "gsd-hooks.ts");
|
|
249
|
+
if (fs.existsSync(oldExt)) {
|
|
250
|
+
fs.rmSync(oldExt);
|
|
251
|
+
log(
|
|
252
|
+
"ok",
|
|
253
|
+
".pi/extensions/gsd-hooks.ts (removed — renamed to pi-gsd-hooks.ts)",
|
|
254
|
+
);
|
|
255
|
+
}
|
|
243
256
|
|
|
244
257
|
console.log("");
|
|
245
258
|
|
|
@@ -299,17 +312,33 @@ function getPackageVersion() {
|
|
|
299
312
|
function installPiExtension(projectRoot, pkgDir, force, callback) {
|
|
300
313
|
const piDir = path.join(projectRoot, ".pi");
|
|
301
314
|
const extDir = path.join(piDir, "extensions");
|
|
302
|
-
const extDest = path.join(extDir, "gsd-hooks.ts");
|
|
303
|
-
const extSrc = path.join(pkgDir, ".gsd", "extensions", "gsd-hooks.ts");
|
|
315
|
+
const extDest = path.join(extDir, "pi-gsd-hooks.ts");
|
|
316
|
+
const extSrc = path.join(pkgDir, ".gsd", "extensions", "pi-gsd-hooks.ts");
|
|
304
317
|
|
|
305
318
|
if (!fs.existsSync(extSrc)) {
|
|
306
|
-
log("warn", ".pi/extensions/gsd-hooks.ts (source absent - skipped)");
|
|
319
|
+
log("warn", ".pi/extensions/pi-gsd-hooks.ts (source absent - skipped)");
|
|
307
320
|
callback(false);
|
|
308
321
|
return;
|
|
309
322
|
}
|
|
310
323
|
|
|
311
|
-
|
|
312
|
-
|
|
324
|
+
// Always update the extension — it is owned by pi-gsd, not the user.
|
|
325
|
+
// Compare pi-gsd-extension-version comments to detect staleness.
|
|
326
|
+
const extractVersion = (file) => {
|
|
327
|
+
try {
|
|
328
|
+
const match = fs
|
|
329
|
+
.readFileSync(file, "utf8")
|
|
330
|
+
.match(/pi-gsd-extension-version:\s*([\d.]+)/);
|
|
331
|
+
return match ? match[1] : null;
|
|
332
|
+
} catch {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const srcVersion = extractVersion(extSrc);
|
|
337
|
+
const destVersion = fs.existsSync(extDest) ? extractVersion(extDest) : null;
|
|
338
|
+
const needsUpdate = force || !destVersion || destVersion !== srcVersion;
|
|
339
|
+
|
|
340
|
+
if (!needsUpdate) {
|
|
341
|
+
log("skip", `.pi/extensions/pi-gsd-hooks.ts (up-to-date v${destVersion})`);
|
|
313
342
|
callback(false);
|
|
314
343
|
} else {
|
|
315
344
|
try {
|
|
@@ -317,13 +346,13 @@ function installPiExtension(projectRoot, pkgDir, force, callback) {
|
|
|
317
346
|
fs.copyFileSync(extSrc, extDest);
|
|
318
347
|
log(
|
|
319
348
|
"ok",
|
|
320
|
-
".pi/extensions/gsd-hooks.ts (GSD lifecycle extension installed)",
|
|
349
|
+
".pi/extensions/pi-gsd-hooks.ts (GSD lifecycle extension installed)",
|
|
321
350
|
);
|
|
322
351
|
callback(true);
|
|
323
352
|
} catch (e) {
|
|
324
353
|
log(
|
|
325
354
|
"warn",
|
|
326
|
-
".pi/extensions/gsd-hooks.ts (install failed: " + e.message + ")",
|
|
355
|
+
".pi/extensions/pi-gsd-hooks.ts (install failed: " + e.message + ")",
|
|
327
356
|
);
|
|
328
357
|
callback(false);
|
|
329
358
|
return;
|
|
@@ -348,9 +377,13 @@ function installPiExtension(projectRoot, pkgDir, force, callback) {
|
|
|
348
377
|
? settings.extensions
|
|
349
378
|
: [];
|
|
350
379
|
|
|
380
|
+
// Remove stale gsd-hooks.ts entry if present (renamed to pi-gsd-hooks.ts)
|
|
381
|
+
const oldExtPath = path.join(extDir, "gsd-hooks.ts");
|
|
382
|
+
const cleaned = extensions.filter((e) => e !== oldExtPath);
|
|
383
|
+
|
|
351
384
|
// Avoid duplicate entries
|
|
352
|
-
if (!
|
|
353
|
-
settings.extensions = [...
|
|
385
|
+
if (!cleaned.includes(extDest)) {
|
|
386
|
+
settings.extensions = [...cleaned, extDest];
|
|
354
387
|
fs.mkdirSync(piDir, { recursive: true });
|
|
355
388
|
fs.writeFileSync(
|
|
356
389
|
settingsFile,
|
|
@@ -358,6 +391,11 @@ function installPiExtension(projectRoot, pkgDir, force, callback) {
|
|
|
358
391
|
"utf8",
|
|
359
392
|
);
|
|
360
393
|
log("ok", ".pi/settings.json (extensions array updated)");
|
|
394
|
+
} else if (cleaned.length !== extensions.length) {
|
|
395
|
+
// Removed stale entry but extDest already present
|
|
396
|
+
settings.extensions = cleaned;
|
|
397
|
+
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, "\t"), "utf8");
|
|
398
|
+
log("ok", ".pi/settings.json (removed stale gsd-hooks.ts entry)");
|
|
361
399
|
}
|
|
362
400
|
} catch (e) {
|
|
363
401
|
log("warn", ".pi/settings.json (could not update: " + e.message + ")");
|
|
@@ -4,7 +4,7 @@ description: Check and repair GSD hook wiring for pi. Use when postinstall was s
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<objective>
|
|
7
|
-
Verify that the GSD pi extension (`gsd-hooks.ts`) is correctly installed in the current project.
|
|
7
|
+
Verify that the GSD pi extension (`pi-gsd-hooks.ts`) is correctly installed in the current project.
|
|
8
8
|
If the extension is missing, install it and update `.pi/settings.json`.
|
|
9
9
|
If already present, confirm hook wiring and report status.
|
|
10
10
|
Always route first-time users to `/gsd-new-project` at the end.
|
|
@@ -12,7 +12,7 @@ Always route first-time users to `/gsd-new-project` at the end.
|
|
|
12
12
|
|
|
13
13
|
<context>
|
|
14
14
|
**Why this skill exists:**
|
|
15
|
-
`bun install` does not run npm `postinstall` scripts, so `gsd-hooks.ts` may not be
|
|
15
|
+
`bun install` does not run npm `postinstall` scripts, so `pi-gsd-hooks.ts` may not be
|
|
16
16
|
automatically copied into the consumer project's `.pi/extensions/` directory.
|
|
17
17
|
This skill provides a manual fallback that performs the same wiring as `postinstall.js`.
|
|
18
18
|
|
|
@@ -23,34 +23,34 @@ This skill provides a manual fallback that performs the same wiring as `postinst
|
|
|
23
23
|
- `tool_result` → context-usage monitor with debounced warnings
|
|
24
24
|
|
|
25
25
|
**Extension source inside the pi-gsd package:**
|
|
26
|
-
`.gsd/extensions/gsd-hooks.ts`
|
|
26
|
+
`.gsd/extensions/pi-gsd-hooks.ts`
|
|
27
27
|
|
|
28
28
|
**Target location in the consumer project:**
|
|
29
|
-
`.pi/extensions/gsd-hooks.ts`
|
|
29
|
+
`.pi/extensions/pi-gsd-hooks.ts`
|
|
30
30
|
|
|
31
31
|
**settings.json entry (belt-and-suspenders - pi also auto-discovers from `.pi/extensions/`):**
|
|
32
|
-
`{ "extensions": ["<absolute-path-to-.pi/extensions/gsd-hooks.ts>"] }`
|
|
32
|
+
`{ "extensions": ["<absolute-path-to-.pi/extensions/pi-gsd-hooks.ts>"] }`
|
|
33
33
|
</context>
|
|
34
34
|
|
|
35
35
|
<process>
|
|
36
36
|
|
|
37
37
|
## Step 1 - Locate the pi-gsd package
|
|
38
38
|
|
|
39
|
-
Resolve the pi-gsd package root (where `gsd-hooks.ts` lives):
|
|
39
|
+
Resolve the pi-gsd package root (where `pi-gsd-hooks.ts` lives):
|
|
40
40
|
|
|
41
41
|
1. Try `node -e "console.log(require.resolve('pi-gsd/package.json'))"` - strip `/package.json` suffix to get PKG_DIR.
|
|
42
42
|
2. If that fails, try common global paths:
|
|
43
43
|
- `~/.bun/install/global/node_modules/pi-gsd`
|
|
44
44
|
- `/home/linuxbrew/.linuxbrew/lib/node_modules/pi-gsd`
|
|
45
45
|
- Output of `npm root -g` + `/pi-gsd`
|
|
46
|
-
3. Confirm the extension source exists at `<PKG_DIR>/.gsd/extensions/gsd-hooks.ts`.
|
|
46
|
+
3. Confirm the extension source exists at `<PKG_DIR>/.gsd/extensions/pi-gsd-hooks.ts`.
|
|
47
47
|
If the source cannot be found, report the error clearly and stop - do not proceed to Step 2.
|
|
48
48
|
|
|
49
49
|
## Step 2 - Check current project extension status
|
|
50
50
|
|
|
51
51
|
In the current working directory (the consumer project):
|
|
52
52
|
|
|
53
|
-
- **Check A:** Does `.pi/extensions/gsd-hooks.ts` exist?
|
|
53
|
+
- **Check A:** Does `.pi/extensions/pi-gsd-hooks.ts` exist?
|
|
54
54
|
- **Check B:** Does `.pi/settings.json` exist? If yes, does `extensions` array include an absolute path to the extension file?
|
|
55
55
|
- **Check C:** Does `.pi/extensions/` directory exist?
|
|
56
56
|
|
|
@@ -59,21 +59,21 @@ In the current working directory (the consumer project):
|
|
|
59
59
|
### If extension is MISSING (Check A failed):
|
|
60
60
|
|
|
61
61
|
1. Create `.pi/extensions/` directory if it does not exist.
|
|
62
|
-
2. Copy `<PKG_DIR>/.gsd/extensions/gsd-hooks.ts` → `.pi/extensions/gsd-hooks.ts`.
|
|
62
|
+
2. Copy `<PKG_DIR>/.gsd/extensions/pi-gsd-hooks.ts` → `.pi/extensions/pi-gsd-hooks.ts`.
|
|
63
63
|
3. Update `.pi/settings.json`:
|
|
64
|
-
- If the file does not exist, create it as `{ "extensions": ["<absolute-path>/.pi/extensions/gsd-hooks.ts"] }`.
|
|
64
|
+
- If the file does not exist, create it as `{ "extensions": ["<absolute-path>/.pi/extensions/pi-gsd-hooks.ts"] }`.
|
|
65
65
|
- If the file exists but `extensions` array is missing or does not include the path, add the absolute path.
|
|
66
66
|
- Preserve all other existing settings - merge, do not overwrite.
|
|
67
|
-
4. Report: `✓ GSD extension installed at .pi/extensions/gsd-hooks.ts`
|
|
67
|
+
4. Report: `✓ GSD extension installed at .pi/extensions/pi-gsd-hooks.ts`
|
|
68
68
|
5. Report: `✓ .pi/settings.json updated`
|
|
69
69
|
|
|
70
70
|
### If extension is PRESENT (Check A passed):
|
|
71
71
|
|
|
72
72
|
1. Confirm the file is non-empty (not a zero-byte stub).
|
|
73
|
-
2. Confirm it contains the marker comment `gsd-extension-version:` - indicating it is the genuine GSD extension, not a stale copy from another tool.
|
|
73
|
+
2. Confirm it contains the marker comment `pi-gsd-extension-version:` - indicating it is the genuine GSD extension, not a stale copy from another tool.
|
|
74
74
|
3. Check Check B - if `settings.json` is missing or the extension path is absent, add it now (same logic as missing case, step 3).
|
|
75
75
|
4. Report:
|
|
76
|
-
- `✓ GSD extension present at .pi/extensions/gsd-hooks.ts`
|
|
76
|
+
- `✓ GSD extension present at .pi/extensions/pi-gsd-hooks.ts`
|
|
77
77
|
- `✓ hooks: session_start (update-check), tool_call (workflow-guard), tool_result (context-monitor)`
|
|
78
78
|
- `✓ .pi/settings.json` - either "already registered" or "path added"
|
|
79
79
|
|
|
@@ -84,9 +84,9 @@ Print a concise status table:
|
|
|
84
84
|
```
|
|
85
85
|
GSD pi hook wiring status
|
|
86
86
|
──────────────────────────────────────────────────────────
|
|
87
|
-
Extension file .pi/extensions/gsd-hooks.ts ✓ / ✗
|
|
87
|
+
Extension file .pi/extensions/pi-gsd-hooks.ts ✓ / ✗
|
|
88
88
|
Settings entry .pi/settings.json extensions ✓ / ✗
|
|
89
|
-
Extension version gsd-extension-version: X.Y.Z (value)
|
|
89
|
+
Extension version pi-gsd-extension-version: X.Y.Z (value)
|
|
90
90
|
──────────────────────────────────────────────────────────
|
|
91
91
|
```
|
|
92
92
|
|