instar 1.2.5 → 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/dist/server/CapabilityIndex.d.ts +68 -0
- package/dist/server/CapabilityIndex.d.ts.map +1 -0
- package/dist/server/CapabilityIndex.js +711 -0
- package/dist/server/CapabilityIndex.js.map +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +11 -400
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +46 -46
- package/upgrades/1.2.6.md +42 -0
- package/upgrades/1.2.7.md +82 -0
- package/upgrades/side-effects/capabilities-introspection.md +119 -0
- package/upgrades/side-effects/safe-fs-agent-state-carveout.md +98 -0
|
@@ -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.
|