instar 1.2.42 → 1.2.44
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/.claude/skills/build/SKILL.md +78 -8
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +51 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +15 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +197 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SafeFsExecutor.d.ts +18 -0
- package/dist/core/SafeFsExecutor.d.ts.map +1 -1
- package/dist/core/SafeFsExecutor.js +68 -0
- package/dist/core/SafeFsExecutor.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-e2e-pairing.cjs +102 -0
- package/src/data/builtin-manifest.json +19 -19
- package/src/templates/hooks/settings-template.json +5 -0
- package/upgrades/1.2.44.md +32 -0
- package/upgrades/side-effects/atomic-write-helper.md +30 -0
- package/upgrades/side-effects/build-methodology-bundle.md +34 -0
- package/upgrades/side-effects/e2e-pairing-gate.md +30 -0
- package/upgrades/side-effects/slopcheck-guard.md +36 -0
- package/upgrades/side-effects/verify-claim-skill.md +33 -0
|
@@ -174,6 +174,74 @@ export class SafeFsExecutor {
|
|
|
174
174
|
throw err;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
+
// ── Atomic write ────────────────────────────────────────────────────
|
|
178
|
+
//
|
|
179
|
+
// Crash-safe file writes for file-backed state. The failure these prevent:
|
|
180
|
+
// a direct `fs.writeFileSync` truncates the target THEN writes; if the
|
|
181
|
+
// process crashes (or the disk fills) mid-write, the file is left
|
|
182
|
+
// truncated or partially written — and for append-only event logs / JSON
|
|
183
|
+
// state, that means silent data loss when the next reader hits a parse
|
|
184
|
+
// error and falls back to an empty skeleton.
|
|
185
|
+
//
|
|
186
|
+
// The pattern: write to a sibling temp file in the SAME directory (so the
|
|
187
|
+
// rename stays on one filesystem and is therefore atomic per POSIX),
|
|
188
|
+
// fsync the data to durable storage, then rename over the target. A crash
|
|
189
|
+
// at any point leaves EITHER the old file intact OR the fully-written new
|
|
190
|
+
// file — never a half-written one.
|
|
191
|
+
//
|
|
192
|
+
// Cherry-picked into Instar 2026-05-23 from the GSD-Instar integration
|
|
193
|
+
// spike (gsd-executor Rule 2 finding: file-backed state lacked atomic
|
|
194
|
+
// writes). Not a destructive op, so it does not go through the
|
|
195
|
+
// source-tree guard — but it lives here as the natural home for safe-fs
|
|
196
|
+
// primitives and shares the audit trail.
|
|
197
|
+
/**
|
|
198
|
+
* Atomically write a string to `target`. Writes to a temp sibling, fsyncs,
|
|
199
|
+
* then renames over the target. Creates parent directories if missing.
|
|
200
|
+
*/
|
|
201
|
+
static atomicWriteFileSync(target, data, opts) {
|
|
202
|
+
const operation = opts?.operation ?? 'atomicWriteFileSync';
|
|
203
|
+
const resolved = path.resolve(target);
|
|
204
|
+
const dir = path.dirname(resolved);
|
|
205
|
+
// Ensure parent dir exists (matches the convenience of writeFileSync callers
|
|
206
|
+
// who often forget mkdir).
|
|
207
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
208
|
+
// Temp file in the SAME directory so rename is atomic (same filesystem).
|
|
209
|
+
const tmp = path.join(dir, `.${path.basename(resolved)}.${process.pid}.${Date.now()}.tmp`);
|
|
210
|
+
let fd;
|
|
211
|
+
try {
|
|
212
|
+
fd = fs.openSync(tmp, 'w', opts?.mode ?? 0o644);
|
|
213
|
+
fs.writeSync(fd, data);
|
|
214
|
+
fs.fsyncSync(fd); // flush data to durable storage before rename
|
|
215
|
+
fs.closeSync(fd);
|
|
216
|
+
fd = undefined;
|
|
217
|
+
fs.renameSync(tmp, resolved); // atomic replace
|
|
218
|
+
audit('atomicWriteFileSync', operation, resolved, 'allowed');
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
// Best-effort cleanup of the temp file; never mask the original error.
|
|
222
|
+
try {
|
|
223
|
+
if (fd !== undefined)
|
|
224
|
+
fs.closeSync(fd);
|
|
225
|
+
}
|
|
226
|
+
catch { /* ignore */ }
|
|
227
|
+
try {
|
|
228
|
+
if (fs.existsSync(tmp))
|
|
229
|
+
fs.unlinkSync(tmp);
|
|
230
|
+
}
|
|
231
|
+
catch { /* ignore */ }
|
|
232
|
+
audit('atomicWriteFileSync', operation, resolved, 'denied', `write-error: ${err.message}`);
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Atomically write `value` as pretty-printed JSON to `target`.
|
|
238
|
+
* Convenience wrapper around atomicWriteFileSync — the common case for
|
|
239
|
+
* Instar's `.instar/state/*.json` files.
|
|
240
|
+
*/
|
|
241
|
+
static atomicWriteJsonSync(target, value, opts) {
|
|
242
|
+
const json = JSON.stringify(value, null, opts?.indent ?? 2);
|
|
243
|
+
this.atomicWriteFileSync(target, json, { operation: opts?.operation ?? 'atomicWriteJsonSync', mode: opts?.mode });
|
|
244
|
+
}
|
|
177
245
|
}
|
|
178
246
|
// Re-export the guard error so call-site catch blocks don't have to import
|
|
179
247
|
// from two modules.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SafeFsExecutor.js","sourceRoot":"","sources":["../../src/core/SafeFsExecutor.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SafeFsExecutor.js","sourceRoot":"","sources":["../../src/core/SafeFsExecutor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// safe-git-allow: pre-commit-bootstrap — read-only `git diff --cached` to scan staged file list; runs before TS compile so cannot use SafeGitExecutor funnel.
|
|
3
|
+
/**
|
|
4
|
+
* E2E-pairing gate — pre-commit check.
|
|
5
|
+
*
|
|
6
|
+
* Cherry-pick from the GSD-Instar integration spike. The spike's Tier-3
|
|
7
|
+
* "feature is alive" finding: features that ship with API routes but no
|
|
8
|
+
* E2E lifecycle test silently return 503 in production. CLAUDE.md calls
|
|
9
|
+
* the Tier-3 test "the single most important test for any feature with
|
|
10
|
+
* API routes" — but nothing structurally enforced its presence.
|
|
11
|
+
*
|
|
12
|
+
* This gate: if a commit stages a non-test `src/server/*.ts` file, it must
|
|
13
|
+
* also stage at least one `tests/e2e/*.test.ts` file. Otherwise the commit
|
|
14
|
+
* is blocked with a remediation message.
|
|
15
|
+
*
|
|
16
|
+
* This is a SIGNAL with commit-time authority — it errs toward false
|
|
17
|
+
* positives (a server refactor that genuinely needs no new e2e test is
|
|
18
|
+
* rarer than a feature shipped without one). Two escape hatches keep it
|
|
19
|
+
* from being tyrannical:
|
|
20
|
+
* 1. Env bypass: INSTAR_SKIP_E2E_PAIRING=1 git commit ...
|
|
21
|
+
* 2. Marker: include "E2E-PAIRING: EXEMPT — <reason>" in any staged
|
|
22
|
+
* server file (for genuine refactors / type-only / comment changes).
|
|
23
|
+
*
|
|
24
|
+
* Exit codes:
|
|
25
|
+
* 0 — pass (no server change, or e2e test paired, or exempt)
|
|
26
|
+
* 1 — block (server change with no paired e2e test and no exemption)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const { execSync } = require('node:child_process');
|
|
30
|
+
|
|
31
|
+
if (process.env.INSTAR_SKIP_E2E_PAIRING === '1') {
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function stagedFiles() {
|
|
36
|
+
try {
|
|
37
|
+
const out = execSync('git diff --cached --name-only --diff-filter=ACMR', { encoding: 'utf-8' });
|
|
38
|
+
return out.split('\n').map(s => s.trim()).filter(Boolean);
|
|
39
|
+
} catch {
|
|
40
|
+
// If we can't read the index, don't block the commit.
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function stagedContent(file) {
|
|
46
|
+
try {
|
|
47
|
+
return execSync(`git show :${file}`, { encoding: 'utf-8' });
|
|
48
|
+
} catch {
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const files = stagedFiles();
|
|
54
|
+
|
|
55
|
+
// Server source files (excluding tests + type-declaration files).
|
|
56
|
+
const serverChanges = files.filter(f =>
|
|
57
|
+
/^src\/server\/.*\.ts$/.test(f) &&
|
|
58
|
+
!/\.test\.ts$/.test(f) &&
|
|
59
|
+
!/\.d\.ts$/.test(f)
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (serverChanges.length === 0) {
|
|
63
|
+
process.exit(0); // No server change — nothing to enforce.
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Paired E2E test staged in the same commit?
|
|
67
|
+
const hasE2e = files.some(f => /^tests\/e2e\/.*\.test\.ts$/.test(f));
|
|
68
|
+
if (hasE2e) {
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Exemption marker in any staged server file?
|
|
73
|
+
const exemptMarker = /E2E-PAIRING:\s*EXEMPT\s*[—-]/;
|
|
74
|
+
for (const f of serverChanges) {
|
|
75
|
+
if (exemptMarker.test(stagedContent(f))) {
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Block.
|
|
81
|
+
console.error('');
|
|
82
|
+
console.error('╔════════════════════════════════════════════════════════════════════╗');
|
|
83
|
+
console.error('║ E2E-PAIRING GATE — server change without a paired E2E test ║');
|
|
84
|
+
console.error('╚════════════════════════════════════════════════════════════════════╝');
|
|
85
|
+
console.error('');
|
|
86
|
+
console.error(' Staged server source files:');
|
|
87
|
+
for (const f of serverChanges) console.error(` ${f}`);
|
|
88
|
+
console.error('');
|
|
89
|
+
console.error(' No tests/e2e/*.test.ts file is staged in this commit.');
|
|
90
|
+
console.error('');
|
|
91
|
+
console.error(' CLAUDE.md: the Tier-3 "feature is alive" E2E test is the single most');
|
|
92
|
+
console.error(' important test for any feature with API routes. Features that ship');
|
|
93
|
+
console.error(' with routes but no E2E lifecycle test silently return 503 in prod.');
|
|
94
|
+
console.error('');
|
|
95
|
+
console.error(' Fix one of:');
|
|
96
|
+
console.error(' 1. Add/modify a tests/e2e/*.test.ts that boots the real server path');
|
|
97
|
+
console.error(' and hits the route, then stage it.');
|
|
98
|
+
console.error(' 2. Genuine refactor / type-only / comment change? Add a comment');
|
|
99
|
+
console.error(' "E2E-PAIRING: EXEMPT — <reason>" to a staged server file.');
|
|
100
|
+
console.error(' 3. One-off bypass: INSTAR_SKIP_E2E_PAIRING=1 git commit ...');
|
|
101
|
+
console.error('');
|
|
102
|
+
process.exit(1);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-23T03:
|
|
5
|
-
"instarVersion": "1.2.
|
|
4
|
+
"generatedAt": "2026-05-23T03:52:30.990Z",
|
|
5
|
+
"instarVersion": "1.2.44",
|
|
6
6
|
"entryCount": 191,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"domain": "identity",
|
|
12
12
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
13
13
|
"installedPath": ".instar/hooks/instar/session-start.sh",
|
|
14
|
-
"contentHash": "
|
|
14
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
15
15
|
"since": "2025-01-01"
|
|
16
16
|
},
|
|
17
17
|
"hook:dangerous-command-guard": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"domain": "safety",
|
|
21
21
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
22
22
|
"installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
|
|
23
|
-
"contentHash": "
|
|
23
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
24
24
|
"since": "2025-01-01"
|
|
25
25
|
},
|
|
26
26
|
"hook:grounding-before-messaging": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"domain": "safety",
|
|
30
30
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
31
31
|
"installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
|
|
32
|
-
"contentHash": "
|
|
32
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
33
33
|
"since": "2025-01-01"
|
|
34
34
|
},
|
|
35
35
|
"hook:compaction-recovery": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"domain": "identity",
|
|
39
39
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
40
40
|
"installedPath": ".instar/hooks/instar/compaction-recovery.sh",
|
|
41
|
-
"contentHash": "
|
|
41
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
42
42
|
"since": "2025-01-01"
|
|
43
43
|
},
|
|
44
44
|
"hook:external-operation-gate": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"domain": "safety",
|
|
48
48
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
49
49
|
"installedPath": ".instar/hooks/instar/external-operation-gate.js",
|
|
50
|
-
"contentHash": "
|
|
50
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
51
51
|
"since": "2025-01-01"
|
|
52
52
|
},
|
|
53
53
|
"hook:deferral-detector": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"domain": "safety",
|
|
57
57
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
58
58
|
"installedPath": ".instar/hooks/instar/deferral-detector.js",
|
|
59
|
-
"contentHash": "
|
|
59
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:post-action-reflection": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "evolution",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:external-communication-guard": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "safety",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:scope-coherence-collector": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "coherence",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:free-text-guard": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "safety",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:claim-intercept": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "coherence",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept-response": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:auto-approve-permissions": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "safety",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"job:health-check": {
|
|
@@ -360,7 +360,7 @@
|
|
|
360
360
|
"type": "skill",
|
|
361
361
|
"domain": "skills",
|
|
362
362
|
"sourcePath": ".claude/skills/build/SKILL.md",
|
|
363
|
-
"contentHash": "
|
|
363
|
+
"contentHash": "bdd16b784c3482372d442ff5986b271213f3d2a705784c7dbbd4345f217be2b2",
|
|
364
364
|
"since": "2025-01-01"
|
|
365
365
|
},
|
|
366
366
|
"skill:instar-project": {
|
|
@@ -1040,7 +1040,7 @@
|
|
|
1040
1040
|
"type": "template",
|
|
1041
1041
|
"domain": "safety",
|
|
1042
1042
|
"sourcePath": "src/templates/hooks/settings-template.json",
|
|
1043
|
-
"contentHash": "
|
|
1043
|
+
"contentHash": "2cc950f0635f9c3412b768610f690288b466e7ace280285aee2481fbe514f230",
|
|
1044
1044
|
"since": "2025-01-01"
|
|
1045
1045
|
},
|
|
1046
1046
|
"template:skill-usage-telemetry.sh": {
|
|
@@ -1472,7 +1472,7 @@
|
|
|
1472
1472
|
"type": "subsystem",
|
|
1473
1473
|
"domain": "updates",
|
|
1474
1474
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1475
|
-
"contentHash": "
|
|
1475
|
+
"contentHash": "2a4639dfdecd37347736d04e008f4a201cd17e9660fa1584df2a43dae2d7e4be",
|
|
1476
1476
|
"since": "2025-01-01"
|
|
1477
1477
|
},
|
|
1478
1478
|
"subsystem:scheduler": {
|
|
@@ -31,6 +31,11 @@
|
|
|
31
31
|
"command": "node .instar/hooks/instar/deferral-detector.js",
|
|
32
32
|
"timeout": 5000
|
|
33
33
|
},
|
|
34
|
+
{
|
|
35
|
+
"type": "command",
|
|
36
|
+
"command": "node .instar/hooks/instar/slopcheck-guard.js",
|
|
37
|
+
"timeout": 5000
|
|
38
|
+
},
|
|
34
39
|
{
|
|
35
40
|
"type": "command",
|
|
36
41
|
"command": "node .instar/hooks/instar/external-communication-guard.js",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: minor -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**feat(build): /build methodology bundle — four GSD cherry-picks + defense-in-depth doc.**
|
|
8
|
+
|
|
9
|
+
Four enhancements to the /build skill, all from the GSD-Instar spike, bundled in one PR because they all touch the /build SKILL.md:
|
|
10
|
+
|
|
11
|
+
- **Phase 0.5: MUST-HAVES (goal-backward)** — before planning HOW, state WHAT must be observably true: truths (consumer-perspective), artifacts (exist + substantive + wired), and key_links (grep patterns proving real wiring). Each truth becomes a Phase 3 verification gate. Prevents shipping a component that compiles + passes unit tests but is never instantiated.
|
|
12
|
+
- **STRIDE threat pass** (LARGE builds only) — a small threat register where each mitigation binds to a specific test. Skipped for SMALL builds.
|
|
13
|
+
- **Atomic-commit discipline** in Phase 2 EXECUTE — one commit per plan step, stage specific files by name (never `git add -A`), `{type}({scope}): {summary}` format, verify no accidental deletions. Replaces the old single-mega-commit guidance (which was unreviewable).
|
|
14
|
+
- **SUMMARY.md deviation-tracking** in Phase 5 COMPLETE — enumerate deviations from plan, categorized by the executor Rule 1/2/3/4, plus the must-haves verification result and any infrastructure-backed deferrals.
|
|
15
|
+
|
|
16
|
+
Also adds `docs/patterns/defense-in-depth-insert-and-projection.md` — the insert-time + projection-time pattern the spike surfaced (with the Topic Intent Layer affirmation cap as the worked example).
|
|
17
|
+
|
|
18
|
+
## Evidence
|
|
19
|
+
|
|
20
|
+
4 unit tests for the migration (migrateBuildSkillMethodology): stock skill updated, idempotent, customized skill untouched, no-throw on missing. TypeScript clean.
|
|
21
|
+
|
|
22
|
+
Migration parity: installBuildSkill is install-if-missing, so existing agents get the methodology via a content-sniffed idempotent migration (only updates a stock /build skill lacking the "Phase 0.5: MUST-HAVES" marker; leaves customized skills alone).
|
|
23
|
+
|
|
24
|
+
Side-effects review: `upgrades/side-effects/build-methodology-bundle.md`.
|
|
25
|
+
|
|
26
|
+
## What to Tell Your User
|
|
27
|
+
|
|
28
|
+
Your /build skill got sharper. It now asks "what must be true when this is done?" before planning, commits work in reviewable per-task chunks instead of one giant commit, and writes a short deviation log at the end so you can see exactly what changed from the original plan. On big builds it also does a quick threat pass. Nothing you have to do differently — /build just does more of the right thing automatically.
|
|
29
|
+
|
|
30
|
+
## Summary of New Capabilities
|
|
31
|
+
|
|
32
|
+
Four /build methodology sections + one pattern doc + one content-update migration + 4 migration tests. Framework-agnostic (prompt-skill content + a migration). The methodology is the GSD planner/executor discipline imported as Instar's own.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Side-Effects Review — Atomic-Write Helper
|
|
2
|
+
|
|
3
|
+
**Source:** Cherry-pick from GSD-Instar spike (gsd-executor Rule 2 finding)
|
|
4
|
+
**Author:** Echo · autonomous run · 2026-05-23
|
|
5
|
+
|
|
6
|
+
## 1. Over-block
|
|
7
|
+
N/A — additive library function, blocks nothing.
|
|
8
|
+
|
|
9
|
+
## 2. Under-block
|
|
10
|
+
N/A — not a gate.
|
|
11
|
+
|
|
12
|
+
## 3. Level-of-abstraction fit
|
|
13
|
+
Lives in SafeFsExecutor alongside the other safe-fs primitives. Natural home. Static methods matching the existing `safeRmSync` etc. style.
|
|
14
|
+
|
|
15
|
+
## 4. Signal-vs-authority compliance
|
|
16
|
+
N/A — not a gate/filter. Pure fs primitive.
|
|
17
|
+
|
|
18
|
+
## 5. Cross-feature interactions
|
|
19
|
+
- Additive — no existing callsite changes. Existing `fs.writeFileSync` callers are untouched; they can migrate to the atomic helper incrementally.
|
|
20
|
+
- Shares the destructive-ops audit trail (appendAuditEntry) — adds `atomicWriteFileSync` / `atomicWriteJsonSync` verbs to the JSONL. No schema change, just new verb values.
|
|
21
|
+
- Temp file naming uses pid + timestamp in the same directory; concurrent writes to the same target from different processes each use a distinct temp, then race on rename (last-rename-wins, which is the correct atomic semantics — no corruption, just last-writer-wins).
|
|
22
|
+
|
|
23
|
+
## 6. Rollback cost
|
|
24
|
+
Trivial. Two new static methods + one test file. Revert the commit; any caller that adopted it would need reverting too, but at ship time there are zero adopters (the helper is introduced here; migration of existing callsites is a separate follow-up).
|
|
25
|
+
|
|
26
|
+
## 7. Migration parity
|
|
27
|
+
N/A — `SafeFsExecutor` is a compiled-in library module, not an agent-installed file (`.claude/settings.json` hook, config default, CLAUDE.md section, hook script, or skill). Ships with the package on `npm i instar@next`. No PostUpdateMigrator entry needed.
|
|
28
|
+
|
|
29
|
+
## Conclusion
|
|
30
|
+
Ship. Purely additive crash-safety primitive. Zero blast radius at introduction. Adopting it across existing `.instar/state/*.json` writers (TopicIntent store, etc.) is a separate follow-up that each gets its own review.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Side-Effects Review — /build Methodology Bundle
|
|
2
|
+
|
|
3
|
+
**Source:** Cherry-picks from GSD-Instar spike (gsd-planner + gsd-executor methodology)
|
|
4
|
+
**Author:** Echo · autonomous run · 2026-05-23
|
|
5
|
+
|
|
6
|
+
## 1. Over-block
|
|
7
|
+
None — these are prompt-skill methodology sections, not gates. They add steps the agent runs, not blocks. The Phase 0.5 "quality gate" (must-haves.md exists before Phase 1) is a soft self-check inside the skill, not an external block.
|
|
8
|
+
|
|
9
|
+
## 2. Under-block
|
|
10
|
+
The methodology is advisory within /build. An agent could skip Phase 0.5. Enforcement of the spirit lives elsewhere (e2e-pairing pre-commit gate, /verify-claim, response-review). This bundle imports the DISCIPLINE; the structural gates are separate cherry-picks.
|
|
11
|
+
|
|
12
|
+
## 3. Level-of-abstraction fit
|
|
13
|
+
All four changes are content edits to the /build SKILL.md — the natural home for build methodology. The defense-in-depth doc lives in docs/patterns/ alongside other pattern docs. The migration follows the existing migrateSkillPortHardcoding content-sniff pattern.
|
|
14
|
+
|
|
15
|
+
## 4. Signal-vs-authority compliance
|
|
16
|
+
Compatible. Phase 0.5 must-haves PRODUCE the verification signals that Phase 3 (authority: the agent + reviewers) acts on. STRIDE mitigations bind to tests (the authority). The defense-in-depth doc explicitly reconciles itself with signal-vs-authority. No brittle filter is given blocking authority.
|
|
17
|
+
|
|
18
|
+
## 5. Cross-feature interactions
|
|
19
|
+
- Phase 0.5 key_links + /verify-claim (separate PR) compose: must-haves define the wiring; /verify-claim checks it.
|
|
20
|
+
- Atomic-commit discipline aligns with the e2e-pairing pre-commit gate (per-task commits make the gate's per-commit check meaningful).
|
|
21
|
+
- SUMMARY deviation-tracking references the executor Rule 1/2/3/4 vocabulary (consistent with the deferral-detector + the GSD methodology framing).
|
|
22
|
+
- The old Phase 5 `git add -A` guidance is REPLACED (it contradicted the new atomic-commit discipline) — a deliberate fix, not just an addition.
|
|
23
|
+
- Migration only touches a stock /build skill; customized skills are fingerprint-guarded.
|
|
24
|
+
|
|
25
|
+
## 6. Rollback cost
|
|
26
|
+
Moderate-low. Revert the SKILL.md edits + the migration method + the doc + the migration test. Existing agents that already ran the migration would keep the updated SKILL.md (harmless — the new sections are additive guidance). The migration is idempotent and conservative, so a revert-then-re-apply is safe.
|
|
27
|
+
|
|
28
|
+
## 7. Migration parity
|
|
29
|
+
- New agents: bundled SKILL.md (copied by installBuildSkill on fresh init) carries the sections.
|
|
30
|
+
- Existing agents: migrateBuildSkillMethodology() content-sniffs for the Phase 0.5 marker and re-copies the bundled SKILL.md if absent AND the file matches the stock fingerprint. Wired into the migration sequence after migrateSkillPortHardcoding. Idempotent + fingerprint-guarded (verified by 4 tests).
|
|
31
|
+
- The defense-in-depth doc is a repo doc, not an agent-installed file — ships with the package, no migration needed.
|
|
32
|
+
|
|
33
|
+
## Conclusion
|
|
34
|
+
Ship. Bundling the four /build-touching items into one PR is correct (separate PRs would self-conflict on SKILL.md). The methodology is the spike's planner+executor discipline imported as Instar's own. Migration parity covered with a conservative content-sniff migration + 4 tests. Seven-dimension review clean.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Side-Effects Review — E2E-Pairing Pre-Commit Gate
|
|
2
|
+
|
|
3
|
+
**Source:** Cherry-pick from GSD-Instar spike (Tier-3 "feature is alive" finding)
|
|
4
|
+
**Author:** Echo · autonomous run · 2026-05-23
|
|
5
|
+
|
|
6
|
+
## 1. Over-block
|
|
7
|
+
Could block legitimate server refactors / type-only changes that genuinely need no new e2e test. Mitigations: (a) `E2E-PAIRING: EXEMPT — <reason>` marker, (b) `INSTAR_SKIP_E2E_PAIRING=1` env bypass. Both are documented in the block message itself.
|
|
8
|
+
|
|
9
|
+
## 2. Under-block
|
|
10
|
+
Could pass a commit that stages a trivial/empty e2e test just to satisfy the gate. Accepted: the gate enforces PRESENCE, not quality. Quality is the reviewer's job + the existing CI E2E run. Presence-enforcement alone closes the "forgot the e2e test entirely" gap, which is the actual failure mode.
|
|
11
|
+
|
|
12
|
+
## 3. Level-of-abstraction fit
|
|
13
|
+
Pre-commit gate alongside check-rule3-coverage.cjs, protect-migration-guarantee.js, instar-dev-precommit.js. Same layer (instar dev discipline), same .husky/pre-commit wiring, same read-only-staged-diff pattern.
|
|
14
|
+
|
|
15
|
+
## 4. Signal-vs-authority compliance
|
|
16
|
+
This is a SIGNAL with commit-time authority (it blocks). Per signal-vs-authority: brittle low-context filters should only block when the defended-against failure is corruption-class and the false-positive cost is low. A route shipped without an e2e test silently 503s in prod (corruption-class); the false-positive cost is one comment marker or one env var (low). The two escape hatches keep the human/agent as the final authority. Compliant.
|
|
17
|
+
|
|
18
|
+
## 5. Cross-feature interactions
|
|
19
|
+
- Runs last in .husky/pre-commit, after lint + instar-dev-precommit + rule3 + migration-guarantee. Independent — reads staged diff, no shared state.
|
|
20
|
+
- Does not interact with CI (CI runs the actual E2E suite; this gate just enforces a test FILE is staged).
|
|
21
|
+
- Edge: a commit that splits a feature across two commits (server in commit 1, e2e test in commit 2) would block commit 1. Mitigation: the EXEMPT marker or env bypass for the intermediate commit; or stage both together. This is a deliberate nudge toward atomic feature commits.
|
|
22
|
+
|
|
23
|
+
## 6. Rollback cost
|
|
24
|
+
Trivial. One script + one line in .husky/pre-commit + one test file. Revert the commit; the gate stops running.
|
|
25
|
+
|
|
26
|
+
## 7. Migration parity
|
|
27
|
+
N/A — this is an instar-dev-repo gate (`.husky/pre-commit`), NOT an agent-installed file. It ships with the source repo and governs instar contributors' commits. Agents never receive `.husky/` hooks. No PostUpdateMigrator entry needed.
|
|
28
|
+
|
|
29
|
+
## Conclusion
|
|
30
|
+
Ship. Structurally enforces the Tier-3 discipline the spike identified as most-forgotten. Two escape hatches prevent tyranny. Trivial rollback. Seven-dimension review clean.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Side-Effects Review — Slopcheck Guard Hook
|
|
2
|
+
|
|
3
|
+
**Source:** Cherry-pick from GSD-Instar spike (gsd-executor Rule 3 exclusion)
|
|
4
|
+
**Author:** Echo · autonomous run · 2026-05-23
|
|
5
|
+
|
|
6
|
+
## 1. Over-block
|
|
7
|
+
Could over-fire on legitimate installs of new-but-real packages. Mitigation: NEVER blocks — signal-only nudge. Worst case is one extra checklist the agent reads and proceeds past. Familiar packages (in any manifest/lockfile) are silently skipped.
|
|
8
|
+
|
|
9
|
+
## 2. Under-block
|
|
10
|
+
Could miss a slopsquat if it happens to share a token with something in a lockfile. Mitigation: the lockfile presence check is deliberately loose (favors NOT nagging on known-safe). The nudge is a backstop, not the only defense — the agent still reasons about each install. Acceptable: under-block here means "no extra nudge", not "install proceeds unchecked" (the agent always sees the command).
|
|
11
|
+
|
|
12
|
+
## 3. Level-of-abstraction fit
|
|
13
|
+
PreToolUse Bash hook alongside dangerous-command-guard, deferral-detector, grounding-before-messaging. Same layer, same idiom, same generator pattern (PostUpdateMigrator getter).
|
|
14
|
+
|
|
15
|
+
## 4. Signal-vs-authority compliance
|
|
16
|
+
Compliant. Pure pattern-match + lockfile lookup = low-context filter emitting a signal (additionalContext). The agent (full-context authority) decides whether to install. Never blocks.
|
|
17
|
+
|
|
18
|
+
## 5. Cross-feature interactions
|
|
19
|
+
- dangerous-command-guard (PreToolUse Bash, blocking) runs first and independently — no overlap (it blocks destructive commands; slopcheck nudges on installs).
|
|
20
|
+
- deferral-detector (PreToolUse Bash) matches communication commands — no overlap with install commands.
|
|
21
|
+
- The hook reads project manifests read-only; no mutation, no shared state.
|
|
22
|
+
- Edge: `echo npm install foo` would trigger the nudge (regex matches anywhere). Harmless — signal-only, rare, and erring toward caution on anything that looks like an install is the safe direction.
|
|
23
|
+
|
|
24
|
+
## 6. Rollback cost
|
|
25
|
+
Trivial. One generator method, one settings-template entry, one migrateSettings ensure-block, one manifest entry, one known-list entry, one test file. Revert the commit; the hook stops generating and existing copies become inert.
|
|
26
|
+
|
|
27
|
+
## 7. Migration parity
|
|
28
|
+
Full coverage:
|
|
29
|
+
- New agents: settings-template.json PreToolUse Bash entry.
|
|
30
|
+
- Existing agents: explicit ensure-block in migrateSettings() adds the slopcheck entry to the Bash matcher if absent (idempotent — checks `hasSlopcheck` first).
|
|
31
|
+
- Hook script: always-overwritten by migrateHooks() (built-in hook).
|
|
32
|
+
- builtin-manifest.json: registered.
|
|
33
|
+
- known-builtin-hooks list: registered (orphan-cleanup safe).
|
|
34
|
+
|
|
35
|
+
## Conclusion
|
|
36
|
+
Ship. Real supply-chain defense Instar lacked. Signal-only, trivial rollback, full migration parity. Seven-dimension review clean.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Side-Effects Review — /verify-claim Skill
|
|
2
|
+
|
|
3
|
+
**Source:** Cherry-pick from GSD-Instar spike (gsd-verifier 4-level protocol)
|
|
4
|
+
**Author:** Echo · autonomous run · 2026-05-23
|
|
5
|
+
|
|
6
|
+
## 1. Over-block
|
|
7
|
+
N/A — a prompt skill, blocks nothing. Worst case: the agent runs a few extra grep/test commands before claiming done. That's the intended cost.
|
|
8
|
+
|
|
9
|
+
## 2. Under-block
|
|
10
|
+
The skill is advisory — an agent could skip invoking it. Mitigation: it's wired into the recommended /build Phase 3 flow and the "before claiming shipped" trigger. Not a hard gate (that would be the e2e-pairing pre-commit hook + response-review). This is the verification METHODOLOGY made callable; enforcement lives elsewhere.
|
|
11
|
+
|
|
12
|
+
## 3. Level-of-abstraction fit
|
|
13
|
+
A user-invocable skill alongside the other built-in skills in installBuiltinSkills(). Same inline-content pattern, same install mechanism, same idempotency guarantee.
|
|
14
|
+
|
|
15
|
+
## 4. Signal-vs-authority compliance
|
|
16
|
+
N/A in the gate sense — it's a methodology the agent runs. It PRODUCES signals (the per-level status), and the agent (authority) acts on them. Aligned with the spike's whole verdict: import the methodology, let the agent wield it.
|
|
17
|
+
|
|
18
|
+
## 5. Cross-feature interactions
|
|
19
|
+
- Complements the e2e-pairing pre-commit gate (that enforces an e2e test FILE exists; this verifies a claim is actually wired). Different layers, no overlap.
|
|
20
|
+
- Complements response-review (Stop hook). /verify-claim is invoked DURING work; response-review checks the outbound message.
|
|
21
|
+
- Referenced from /build Phase 3 VERIFY as the per-must-have check.
|
|
22
|
+
- Pure additive skill — no existing skill changes.
|
|
23
|
+
|
|
24
|
+
## 6. Rollback cost
|
|
25
|
+
Trivial. One entry in the installBuiltinSkills record + one test file. Revert the commit; the skill stops being installed for new agents. Existing agents that already have the SKILL.md keep an inert copy (harmless).
|
|
26
|
+
|
|
27
|
+
## 7. Migration parity
|
|
28
|
+
Adding a NEW skill needs no migration per the Migration Parity Standard: installBuiltinSkills() is called from refreshHooksAndSettings() on every update and is non-destructive (only writes missing SKILL.md files). Existing agents get verify-claim on their next update. Idempotency verified in the test (does not overwrite a customized copy).
|
|
29
|
+
|
|
30
|
+
Note: a follow-up should add /verify-claim to the CLAUDE.md template's capability list (Agent Awareness Standard) so agents surface it conversationally — tracked, not blocking this PR.
|
|
31
|
+
|
|
32
|
+
## Conclusion
|
|
33
|
+
Ship. The spike's #1 cherry-pick by leverage. Pure additive prompt skill, trivial rollback, no migration needed. Seven-dimension review clean.
|