instar 1.2.6 → 1.2.7
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/dist/core/SafeFsExecutor.d.ts.map +1 -1
- package/dist/core/SafeFsExecutor.js +35 -0
- package/dist/core/SafeFsExecutor.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.2.7.md +82 -0
- package/upgrades/side-effects/safe-fs-agent-state-carveout.md +98 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SafeFsExecutor.d.ts","sourceRoot":"","sources":["../../src/core/SafeFsExecutor.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzB,OAAO,EAEL,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,EAAE,CAAC,SAAS,GAAG,aAAa,CAAC;AACzD,MAAM,MAAM,gBAAgB,GAAG,EAAE,CAAC,YAAY,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"SafeFsExecutor.d.ts","sourceRoot":"","sources":["../../src/core/SafeFsExecutor.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzB,OAAO,EAEL,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,EAAE,CAAC,SAAS,GAAG,aAAa,CAAC;AACzD,MAAM,MAAM,gBAAgB,GAAG,EAAE,CAAC,YAAY,GAAG,aAAa,CAAC;AAsF/D,qBAAa,cAAc;IACzB,oCAAoC;WACvB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,8BAA8B;IAC9B,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IAY5D,wCAAwC;WAC3B,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3E,kCAAkC;IAClC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IAWhE,uCAAuC;WAC1B,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7E,iCAAiC;IACjC,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI;CAWnE;AAID,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -48,8 +48,43 @@ function canonicalizeTarget(target) {
|
|
|
48
48
|
return path.resolve(target);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Agent runtime state carve-out.
|
|
53
|
+
*
|
|
54
|
+
* When instar is deployed in "agent" mode the agent dir IS a checkout of the
|
|
55
|
+
* instar source (same .git, same .instar-source-tree marker, same package.json
|
|
56
|
+
* with name === "instar"). The guard correctly identifies this as the source
|
|
57
|
+
* tree — but runtime artifacts under `.instar/` (sockets, locks, logs, audit
|
|
58
|
+
* trail) are explicitly NOT source code (they are .gitignored). Destructive
|
|
59
|
+
* ops on those paths are a normal part of operation, not a 2026-04-22-class
|
|
60
|
+
* incident.
|
|
61
|
+
*
|
|
62
|
+
* This predicate returns true when `canonical` is anywhere under an `.instar/`
|
|
63
|
+
* subdirectory of the source root — those are runtime state and the guard's
|
|
64
|
+
* brittle-block is a false positive for them.
|
|
65
|
+
*
|
|
66
|
+
* The check is intentionally narrow: it requires `/.instar/` as an interior
|
|
67
|
+
* path segment (not just trailing), so operations on the `.instar` directory
|
|
68
|
+
* itself still go through the guard. The carve-out is for files INSIDE it.
|
|
69
|
+
*/
|
|
70
|
+
function isUnderAgentRuntimeState(canonical) {
|
|
71
|
+
const sep = path.sep;
|
|
72
|
+
const marker = `${sep}.instar${sep}`;
|
|
73
|
+
const idx = canonical.indexOf(marker);
|
|
74
|
+
if (idx === -1)
|
|
75
|
+
return false;
|
|
76
|
+
return canonical.length > idx + marker.length;
|
|
77
|
+
}
|
|
51
78
|
function guard(target, operation, fnName) {
|
|
52
79
|
const canonical = canonicalizeTarget(target);
|
|
80
|
+
// Carve-out: runtime state under `.instar/` is gitignored, not source code.
|
|
81
|
+
// The guard's brittle-block is a false positive for these paths in
|
|
82
|
+
// agent-mode deployments where the agent dir IS a checkout of the source.
|
|
83
|
+
// See isUnderAgentRuntimeState() above for the precise predicate.
|
|
84
|
+
if (isUnderAgentRuntimeState(canonical)) {
|
|
85
|
+
audit(fnName, operation, canonical, 'allowed', 'agent-runtime-state-carveout');
|
|
86
|
+
return canonical;
|
|
87
|
+
}
|
|
53
88
|
try {
|
|
54
89
|
assertNotInstarSourceTree(canonical, operation);
|
|
55
90
|
}
|
|
@@ -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":"AAAA,uFAAuF;AACvF;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAUxD,SAAS,kBAAkB;IACzB,MAAM,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,KAAK,CACZ,MAAc,EACd,SAAiB,EACjB,MAAc,EACd,OAA6B,EAC7B,MAAe;IAEf,MAAM,KAAK,GAA4B;QACrC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,QAAQ,EAAE,IAAI;QACd,SAAS;QACT,IAAI,EAAE,MAAM;QACZ,MAAM;QACN,OAAO;QACP,MAAM,EAAE,kBAAkB,EAAE;KAC7B,CAAC;IACF,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAChD,gBAAgB,CAAC,KAAc,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,wBAAwB,CAAC,SAAiB;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,GAAG,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7B,OAAO,SAAS,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAChD,CAAC;AAED,SAAS,KAAK,CAAC,MAAc,EAAE,SAAiB,EAAE,MAAc;IAC9D,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC7C,4EAA4E;IAC5E,mEAAmE;IACnE,0EAA0E;IAC1E,kEAAkE;IAClE,IAAI,wBAAwB,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,8BAA8B,CAAC,CAAC;QAC/E,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,yBAAyB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uEAAuE;AAEvE,MAAM,OAAO,cAAc;IACzB,oCAAoC;IACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,IAAmB;QACrD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC7B,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAc,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACvF,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,MAAM,CAAC,UAAU,CAAC,MAAc,EAAE,IAAmB;QACnD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1B,KAAK,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAc,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3F,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,IAAmB;QACzD,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACzB,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAkB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACpG,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,MAAM,CAAC,cAAc,CAAC,MAAc,EAAE,IAAmB;QACvD,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACtB,KAAK,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAkB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACxG,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAc,EAAE,IAAsB;QAC3D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAiB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7F,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,MAAM,CAAC,aAAa,CAAC,MAAc,EAAE,IAAsB;QACzD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QAC5D,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC7B,KAAK,CAAC,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAiB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACjG,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAED,2EAA2E;AAC3E,oBAAoB;AACpB,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-21T17:
|
|
5
|
-
"instarVersion": "1.2.
|
|
4
|
+
"generatedAt": "2026-05-21T17:33:33.304Z",
|
|
5
|
+
"instarVersion": "1.2.7",
|
|
6
6
|
"entryCount": 191,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
<!-- patch = bug fixes, refactors, test additions, doc updates -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
**fix(safe-fs): runtime artifacts under `<root>/.instar/` get a carve-out from the source-tree guard.**
|
|
9
|
+
|
|
10
|
+
Closes the "agent goes dark on cold start" failure mode that surfaced after v1.2.4 in the field (Echo, 2026-05-21): every fresh launchd spawn hit `EADDRINUSE` on the stale unix socket at `.instar/listener.sock`, the `WakeSocketServer` stale-socket-recovery path correctly tried to unlink it, but `SafeFsExecutor` routed the unlink through `assertNotInstarSourceTree` and the guard fired because the agent's deployed directory IS a checkout of the instar source (same `.git`, same `.instar-source-tree` marker, same `package.json` with `name: "instar"`). The supervisor then escalated to its bind-failure recovery path and force-rebuilt better-sqlite3 on every cycle, which in turn produced an incompatible binary and the server never bound.
|
|
11
|
+
|
|
12
|
+
The fix is a narrow carve-out in `SafeFsExecutor.guard()`: when the canonicalized target path is under a `.instar/` subdirectory of the source root, skip the source-tree guard. The carve-out is intentionally interior-only — the `.instar` directory itself is still protected (`safeRmSync` on `<root>/.instar` still throws `SourceTreeGuardError`). All five subdirectories that the project's own `.gitignore` excludes (`.instar/state/`, `.instar/logs/`, `.instar/audit/`, `.instar/instar-dev-traces/`, plus `.instar/shared-state.jsonl`) are runtime state, not source code, and destructive ops on them are a normal part of operation rather than a 2026-04-22-class incident.
|
|
13
|
+
|
|
14
|
+
The guard's three layers (marker file, canonical origin URL, source-identity signature) are unchanged. The 2026-04-22 incident is still caught: that incident targeted source files at the tree root (`README.md`, `src/auth.ts`, `src/middleware.ts`), not anything under `.instar/`. The included tests verify both directions — the carve-out lets the right paths through, and source-tree paths outside `.instar/` (and `.instar` itself) still fault.
|
|
15
|
+
|
|
16
|
+
## Why now
|
|
17
|
+
|
|
18
|
+
After v1.2.4 every fresh boot of Echo on dawn-macbook entered the loop: lifeline restarts → WakeSocketServer EADDRINUSE → stale-socket-recovery blocked by guard → supervisor declares health-check failed → bind-failure escalation → force-rebuild better-sqlite3 → binary mismatch → loop. Manually unlinking the socket and bootstrapping cleanly worked once, but the next launchd respawn re-entered the loop because nothing fixed the structural block.
|
|
19
|
+
|
|
20
|
+
## Audit trail
|
|
21
|
+
|
|
22
|
+
The carve-out also leaves a positive audit signal: `safeUnlinkSync` (and siblings) emit an `outcome: "allowed"` entry to `.instar/audit/destructive-ops.jsonl` with `reason: "agent-runtime-state-carveout"` whenever the carve-out path is taken. Lets you see how often the runtime-state path is being exercised vs how often it would have been a false-positive block before.
|
|
23
|
+
|
|
24
|
+
## Tests
|
|
25
|
+
|
|
26
|
+
5 new tests in `tests/unit/SafeFsExecutor.test.ts` under `SafeFsExecutor agent-runtime-state carve-out`:
|
|
27
|
+
|
|
28
|
+
- `allows unlink on a socket file under <root>/.instar/`
|
|
29
|
+
- `allows unlink on a lock file under <root>/.instar/`
|
|
30
|
+
- `allows rm on a nested file under <root>/.instar/state/`
|
|
31
|
+
- `still BLOCKS rm on the .instar directory itself (not its contents)`
|
|
32
|
+
- `still BLOCKS unlink on source files at the tree root`
|
|
33
|
+
|
|
34
|
+
All 17 SafeFsExecutor tests pass (12 existing + 5 new).
|
|
35
|
+
|
|
36
|
+
## Summary of New Capabilities
|
|
37
|
+
|
|
38
|
+
This is a fix-only release. No new user-facing capabilities. The carve-out unblocks `WakeSocketServer.stale-socket-recovery`, `AutoUpdater` shadow-install management, and lifeline lockfile cleanup — all of which were already supposed to work but were silently blocked by the source-tree guard in agent mode.
|
|
39
|
+
|
|
40
|
+
## What to Tell Your User
|
|
41
|
+
|
|
42
|
+
If you're running an instar agent on macOS and have hit cold-start crash loops where the agent's logs say EADDRINUSE and reference SafeFsExecutor, this release fixes the underlying block. Pull v1.2.x (next), restart your agent. No config changes required, no migration needed.
|
|
43
|
+
|
|
44
|
+
If you've never seen this — you're on a deployment style where the agent dir is NOT a checkout of the instar source, and the guard was never the problem. This release is a no-op for you.
|
|
45
|
+
|
|
46
|
+
If you ran the manual workaround (rm .instar/listener.sock then bootstrap your launchd plist) — the workaround is no longer needed once this release is installed.
|
|
47
|
+
|
|
48
|
+
## Evidence
|
|
49
|
+
|
|
50
|
+
**Reproduction**: Run instar in agent mode where the agent's deployed directory is also a checkout of the instar source tree (the `~/.instar/agents/echo` pattern on dawn-macbook). Cold-start with a stale `.instar/listener.sock` present. Observed before this fix: `WakeSocketServer` attempts to unlink the stale socket via `SafeFsExecutor.safeUnlinkSync`, which throws `SourceTreeGuardError`. The supervisor's bind-failure escalation triggers (`Bind-failure escalation armed: N consecutive spawns failed before binding`). After 5 retries the supervisor enters 300s cooldown. Server never binds. Tunnel returns 502.
|
|
51
|
+
|
|
52
|
+
**Observed before** (Echo, 2026-05-21T16:46Z, sample from `logs/lifeline-launchd.err`):
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Error: stale socket at /Users/justin/.instar/agents/echo/.instar/listener.sock could not be unlinked:
|
|
56
|
+
Refusing to run src/threadline/WakeSocketServer.ts:stale-socket-recovery against the instar source tree
|
|
57
|
+
(requested dir: /Users/justin/.instar/agents/echo/.instar/listener.sock,
|
|
58
|
+
resolved git root: /Users/justin/.instar/agents/echo).
|
|
59
|
+
[Supervisor] Bind-failure escalation armed: 34 consecutive spawns failed before binding.
|
|
60
|
+
[Supervisor] Max restart attempts (5) reached. Cooling down for 300s before retrying.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Observed after** (same agent, hot-patched 2026-05-21T17:00Z with the same source change applied to `shadow-install/.../SafeFsExecutor.js`):
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:4042/health # 5 times, 3s apart
|
|
67
|
+
200
|
|
68
|
+
200
|
|
69
|
+
200
|
|
70
|
+
200
|
|
71
|
+
200
|
|
72
|
+
|
|
73
|
+
$ curl -s -o /dev/null -w "%{http_code}\n" https://echo.dawn-tunnel.dev/health
|
|
74
|
+
200
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Tunnel-fronted dashboard at `https://echo.dawn-tunnel.dev/dashboard?session=<...>` returns HTTP 200 with the live dashboard HTML (316KB). The bind-failure escalation never fires. The audit log shows the carve-out's positive signal:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
$ grep agent-runtime-state-carveout .instar/audit/destructive-ops.jsonl | head -3
|
|
81
|
+
{"timestamp":"2026-05-21T17:00:23.118Z","executor":"fs","operation":"WakeSocketServer.ts:stale-socket-recovery","verb":"safeUnlinkSync","target":".../.instar/listener.sock","outcome":"allowed","reason":"agent-runtime-state-carveout","caller":"..."}
|
|
82
|
+
```
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Side-effects review — SafeFsExecutor agent-runtime-state carve-out
|
|
2
|
+
|
|
3
|
+
**Scope**: `SafeFsExecutor.guard()` now bypasses `assertNotInstarSourceTree`
|
|
4
|
+
when the canonicalized target path is under a `.instar/` subdirectory of the
|
|
5
|
+
source root. New helper `isUnderAgentRuntimeState()` performs the check.
|
|
6
|
+
|
|
7
|
+
**Root cause of original issue**: When instar is deployed in "agent" mode (e.g.
|
|
8
|
+
`~/.instar/agents/<name>/`), the agent dir IS a checkout of the instar source
|
|
9
|
+
— same `.git`, same `.instar-source-tree` marker file, same `package.json`
|
|
10
|
+
with `name: "instar"`. The source-tree guard's three layers (marker, canonical
|
|
11
|
+
remote URL, source-identity signature) all correctly identify the agent root
|
|
12
|
+
as the instar source. But the agent's runtime artifacts live at
|
|
13
|
+
`<root>/.instar/` (sockets, locks, logs, audit trail, shared-state JSONL),
|
|
14
|
+
which are explicitly `.gitignored` and are NOT source code. Destructive ops
|
|
15
|
+
on those paths (e.g., `WakeSocketServer.stale-socket-recovery` unlinking a
|
|
16
|
+
stale `listener.sock`) are a normal part of operation, not a 2026-04-22-class
|
|
17
|
+
incident.
|
|
18
|
+
|
|
19
|
+
Before this fix, every unlink-the-stale-socket attempt in agent mode failed
|
|
20
|
+
with `SourceTreeGuardError`, the supervisor declared the server unhealthy,
|
|
21
|
+
escalated to its bind-failure recovery path, force-rebuilt better-sqlite3 on
|
|
22
|
+
every restart cycle, and the agent never bound to its socket. Observed in
|
|
23
|
+
the field 2026-05-21 on dawn-macbook Echo, immediately after v1.2.4.
|
|
24
|
+
|
|
25
|
+
**Files touched**:
|
|
26
|
+
- `src/core/SafeFsExecutor.ts` — added `isUnderAgentRuntimeState()` helper
|
|
27
|
+
(interior-`/.instar/`-segment predicate, returns false when the marker is
|
|
28
|
+
trailing) and a carve-out branch in `guard()` that audits as `allowed` with
|
|
29
|
+
`reason: "agent-runtime-state-carveout"` when the predicate matches.
|
|
30
|
+
- `tests/unit/SafeFsExecutor.test.ts` — added `SafeFsExecutor agent-runtime-state
|
|
31
|
+
carve-out` describe block with five tests (3 positive carve-outs, 2 still-blocked).
|
|
32
|
+
- `upgrades/NEXT.md` — release notes.
|
|
33
|
+
|
|
34
|
+
**Under-block (what's no longer caught)**: Operations on individual files and
|
|
35
|
+
nested directories under `<source-root>/.instar/<anything>`. Specifically:
|
|
36
|
+
|
|
37
|
+
1. **`.instar/listener.sock` (and other `.sock` files there)**. `.sock` files
|
|
38
|
+
are agent runtime IPC endpoints; the project's own `.gitignore` covers the
|
|
39
|
+
parent directories these would live under. The 2026-04-22 incident did not
|
|
40
|
+
touch this path; risk is low.
|
|
41
|
+
|
|
42
|
+
2. **`.instar/lifeline.lock` (and other lockfiles there)**. Lockfile cleanup
|
|
43
|
+
is mandatory for any LaunchAgent-style supervisor. Under-block is required
|
|
44
|
+
for the supervisor to recover from stale locks.
|
|
45
|
+
|
|
46
|
+
3. **`.instar/state/*`, `.instar/logs/*`, `.instar/audit/*`,
|
|
47
|
+
`.instar/instar-dev-traces/*`**. All four directories appear in the
|
|
48
|
+
project's `.gitignore`. None contain source code. Destructive ops on stale
|
|
49
|
+
entries here are normal house-cleaning. Under-block is intentional.
|
|
50
|
+
|
|
51
|
+
4. **`.instar/shadow-install/`**. The agent's pinned vendored copy of the
|
|
52
|
+
instar package. Modified by `instar update` and `AutoUpdater`. Treated as
|
|
53
|
+
runtime state, not source. The auto-updater needs to wipe-and-reinstall
|
|
54
|
+
this directory; the carve-out unblocks that path under agent mode.
|
|
55
|
+
|
|
56
|
+
The carve-out is intentionally interior-only — the `.instar` directory itself
|
|
57
|
+
is still protected by the guard. A `safeRmSync` targeting `<source-root>/.instar`
|
|
58
|
+
still throws `SourceTreeGuardError`. This is verified by the
|
|
59
|
+
`still BLOCKS rm on the .instar directory itself (not its contents)` test.
|
|
60
|
+
|
|
61
|
+
**What stays caught**:
|
|
62
|
+
|
|
63
|
+
1. **All source files at the tree root** — anything in `src/`, `tests/`,
|
|
64
|
+
`docs/`, `scripts/`, root-level files like `package.json`, `README.md`,
|
|
65
|
+
`tsconfig.json`. The 2026-04-22 incident damage (`README.md`, `src/auth.ts`,
|
|
66
|
+
`src/middleware.ts`) is still blocked. Verified by the `still BLOCKS unlink
|
|
67
|
+
on source files at the tree root` test.
|
|
68
|
+
|
|
69
|
+
2. **The `.instar` directory itself** — `safeRmSync` on `<root>/.instar` with
|
|
70
|
+
`recursive: true` is still rejected. The carve-out predicate requires
|
|
71
|
+
`/.instar/` followed by at least one additional path segment; `<root>/.instar`
|
|
72
|
+
alone does not satisfy that.
|
|
73
|
+
|
|
74
|
+
3. **All three detection layers** are unchanged. The marker file, canonical
|
|
75
|
+
remote URL, and source-identity signature checks all still run for paths
|
|
76
|
+
outside `.instar/`.
|
|
77
|
+
|
|
78
|
+
**Audit trail**: The carve-out leaves a positive `outcome: "allowed"` entry
|
|
79
|
+
with `reason: "agent-runtime-state-carveout"` in `.instar/audit/destructive-ops.jsonl`
|
|
80
|
+
on every match. This makes the false-positive rate (operations that would have
|
|
81
|
+
been wrongly blocked before) directly observable: `grep
|
|
82
|
+
agent-runtime-state-carveout .instar/audit/destructive-ops.jsonl | wc -l`.
|
|
83
|
+
Operators can confirm the carve-out is being exercised exactly when expected
|
|
84
|
+
(WakeSocketServer recovery, AutoUpdater install, etc.) and not in unexpected
|
|
85
|
+
places.
|
|
86
|
+
|
|
87
|
+
**Tests**: 5 new tests under `describe('SafeFsExecutor agent-runtime-state
|
|
88
|
+
carve-out', …)` in `tests/unit/SafeFsExecutor.test.ts`. All 17 SafeFsExecutor
|
|
89
|
+
tests pass (12 existing + 5 new). No existing tests modified.
|
|
90
|
+
|
|
91
|
+
**Spec impact**: `docs/specs/DESTRUCTIVE-TOOL-TARGET-GUARDS-SPEC.md` is not
|
|
92
|
+
modified by this change. The spec's tactical-guardrail design is preserved
|
|
93
|
+
exactly. The carve-out lives one layer below the guard (in `SafeFsExecutor`)
|
|
94
|
+
and is documented in the new helper's doc-comment with the reasoning above.
|
|
95
|
+
|
|
96
|
+
**Rollback**: Revert this commit. The carve-out is a single function and a
|
|
97
|
+
single branch in `guard()`. Rollback restores the brittle-block behavior
|
|
98
|
+
exactly; no migration needed.
|