instar 1.3.659 → 1.3.661

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.659",
3
+ "version": "1.3.661",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-25T01:38:40.089Z",
5
- "instarVersion": "1.3.659",
4
+ "generatedAt": "2026-06-25T07:21:02.386Z",
5
+ "instarVersion": "1.3.661",
6
6
  "entryCount": 202,
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": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
14
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
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": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
23
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
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": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
32
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
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": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
41
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
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": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
50
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
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": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
59
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:self-stop-guard": {
@@ -65,7 +65,7 @@
65
65
  "domain": "coherence",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/self-stop-guard.js",
68
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
68
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:post-action-reflection": {
@@ -74,7 +74,7 @@
74
74
  "domain": "evolution",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
77
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
77
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:external-communication-guard": {
@@ -83,7 +83,7 @@
83
83
  "domain": "safety",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
86
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
86
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-collector": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
95
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
95
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:scope-coherence-checkpoint": {
@@ -101,7 +101,7 @@
101
101
  "domain": "coherence",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
104
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
104
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:free-text-guard": {
@@ -110,7 +110,7 @@
110
110
  "domain": "safety",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
113
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
113
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
122
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
122
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:claim-intercept-response": {
@@ -128,7 +128,7 @@
128
128
  "domain": "coherence",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
131
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
131
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "hook:stop-gate-router": {
@@ -137,7 +137,7 @@
137
137
  "domain": "safety",
138
138
  "sourcePath": "src/core/PostUpdateMigrator.ts",
139
139
  "installedPath": ".instar/hooks/instar/stop-gate-router.js",
140
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
140
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
141
141
  "since": "2025-01-01"
142
142
  },
143
143
  "hook:auto-approve-permissions": {
@@ -146,7 +146,7 @@
146
146
  "domain": "safety",
147
147
  "sourcePath": "src/core/PostUpdateMigrator.ts",
148
148
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
149
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
149
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
150
150
  "since": "2025-01-01"
151
151
  },
152
152
  "job:health-check": {
@@ -1562,7 +1562,7 @@
1562
1562
  "type": "subsystem",
1563
1563
  "domain": "updates",
1564
1564
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1565
- "contentHash": "25307559192c0fd8e51ea087b3ba9ee4473424a330518b8899ce06bb4cdcdb80",
1565
+ "contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
1566
1566
  "since": "2025-01-01"
1567
1567
  },
1568
1568
  "subsystem:scheduler": {
@@ -0,0 +1,70 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Adds a new constitutional standard, **"Verify the State, Not Its Symbol"**, to
9
+ `docs/STANDARDS-REGISTRY.md` (Substrate family), and registers it as **P20** in
10
+ `docs/INSTAR-DESIGN-PRINCIPLES-AND-LESSONS.md` so the `/spec-converge` lessons-aware
11
+ reviewer fires on every future spec. Lesson L5 is re-pointed to P20 as its parent.
12
+
13
+ The standard names a class of blind spot that has bitten the fleet repeatedly under
14
+ different disguises: a detector, gate, verifier, or sentinel that trusts a *symbol*
15
+ of a state (a string on a pane, a marker, the presence or absence of a proxy signal)
16
+ instead of confirming the *state itself* — in both directions, where the presence of
17
+ a symbol is taken as the condition being true and the absence of a signal is taken as
18
+ the condition being true. When the evidence needed to decide is unavailable, the result
19
+ is **unknown**, and unknown must fail toward the least-harmful action for that specific
20
+ detector — which is not always "closed".
21
+
22
+ Documentation-only: this change adds no runtime, gate, or `src` surface. The companion
23
+ fix for the crystallizing instance (the RateLimitSentinel false-positive) is specified
24
+ and review-converged in `docs/specs/ratelimit-sentinel-false-positive-hardening.md`,
25
+ which this change also lands so the standard's enforcement-first citation resolves to a
26
+ real file; the implementation of that fix ships as a separate, tracked follow-on PR.
27
+
28
+ Fixed the "session paused" hang: an autonomous session would freeze indefinitely the first time a helper sub-agent (spawned via the Task/Agent tool) ran a shell command. Root cause: a sub-agent does NOT inherit the parent session's `--dangerously-skip-permissions` MODE — confirmed against Claude Code docs, it inherits only the permission RULES from `.claude/settings.json`. With no allow-rules configured, the sub-agent's first `Bash` call surfaced the interactive "This command requires approval" dialog, and in an unattended run there was no human to answer it, so the session sat modal-blocked forever (indistinguishable from "paused"). It affected the whole fleet because every agent shipped with an empty permissions block.
29
+
30
+ `PostUpdateMigrator.ensurePermissionAllowRules()` now runs inside `migrateSettings()` and adds a `permissions.allow` list for the built-in tools a sub-agent uses (`Bash`, `Read`, `Edit`, `Write`, `Glob`, `Grep`, `Task`, `NotebookEdit`, `WebFetch`, `WebSearch`, `TodoWrite`). Sub-agents inherit permission rules, so the allow-rule is the structural lever that reliably applies — unlike the existing `PermissionRequest` auto-approve hook, which does not reliably fire for sub-agent calls. The migration is idempotent (adds only missing tool names), never touches the operator's `deny`/`ask` lists, and deliberately excludes MCP tools (`mcp__*`) so external/network operations keep their external-operation-gate approval posture. Because it rides `migrateSettings()`, every existing agent picks it up on its next update and every new agent gets it at init (Migration Parity).
31
+
32
+ Safety is unchanged: the allow-rules only skip the duplicative human-in-the-loop prompt. The PreToolUse guard chain (`dangerous-command-guard`, `external-operation-gate`, `external-communication-guard`, `self-stop-guard`, …) still runs on every tool call and can still block — and the same `migrateSettings()` pass that adds the allow-rules also wires that guard chain (via `ensureInstarBashPreToolUseHooks`, before the allow-rules), so the guards and the allow-rules always arrive together.
33
+
34
+ ## What to Tell Your User
35
+
36
+ - **A new "verify the real state, not a sign of it" rule**: "I added a standard to how I'm
37
+ built so that my own watchers can't cry wolf at a word on the screen, or go silent because
38
+ they looked for proof in the wrong place. From now on, anything I build that watches for a
39
+ problem has to confirm the problem is really happening before it acts — and when it genuinely
40
+ can't tell, it errs toward the quiet, least-harmful choice instead of the loudest one. This
41
+ came straight out of the false 'you're throttled' alarms you saw tonight."
42
+
43
+ If your agent ever seemed to "pause" mid-task during an unattended/autonomous run — silently stuck and only resuming when you messaged it — this is a common cause: a helper it spawned hit an approval prompt nobody was there to answer. After this update (and a session restart so the new settings load), helper tasks no longer stall on those prompts, so autonomous runs keep moving. Your safety guards are unchanged — every command still passes the same pre-action checks; the only thing removed is the approval pop-up that had no one to answer it.
44
+
45
+ ## Summary of New Capabilities
46
+
47
+ | Capability | How to Use |
48
+ |-----------|-----------|
49
+ | "Verify the State, Not Its Symbol" standard (P20) | automatic — the `/spec-converge` lessons-aware reviewer now flags any future spec whose detector fires on a single uncorroborated symbol, reads a self-writable channel, or treats absence as the bad state |
50
+
51
+ - `PostUpdateMigrator.ensurePermissionAllowRules()` — adds inherited `permissions.allow` rules for sub-agent built-in tools to every agent's `.claude/settings.json` via the migration path (new agents at init, existing agents on update). Idempotent, non-clobbering of operator `deny`/`ask`, and scoped to local tools (MCP stays gated by the external-operation-gate).
52
+
53
+ ## Evidence
54
+
55
+ Earned from a live recurrence, not a hypothetical. On 2026-06-24 (topic 16566) the
56
+ RateLimitSentinel fired "this turn died on an API error" because the literal words
57
+ `API Error:` were on the session pane — placed there by the session *investigating* API
58
+ errors, with nothing actually failed — then cried wolf for ~11 minutes because its recovery
59
+ verifier looked for the session transcript in one Claude account home while the session ran
60
+ under another, reading absence-of-file as "never recovered". The detector that diagnosed the
61
+ bug was, live, tripped by the bug. The same class had recurred 4+ times before under different
62
+ disguises (2026-06-06 stale-transcript-pointer crying-wolf, the AUP-rejection wedge, the origin
63
+ of lesson L5), each patched point-wise without ever naming the class — the registry's promotion
64
+ signal. The companion code fix's reproduction + before/after is carried in its own spec and
65
+ follow-on PR; this PR is documentation-only and changes no runtime behavior to reproduce.
66
+
67
+ - **Reproduction (2026-06-24):** an unattended autonomous run sat silent for ~68 min; a screenshot showed the session modal-blocked on a sub-agent's `Bash` "This command requires approval" dialog. Confirmed the same class on a second agent (AI Guy). Settings inspection showed the `permissions` block was entirely absent (no allow-rules for sub-agents to inherit).
68
+ - **Mechanism confirmed:** Claude Code docs — sub-agents inherit permission RULES but not the permission MODE; PreToolUse hooks run BEFORE permission-rule evaluation and a hook exiting 2 blocks the call even for an allowed tool (so allow-rules cannot weaken the guards).
69
+ - **Tests:** `tests/unit/PostUpdateMigrator-permissionAllowRules.test.ts` — 6 tests: adds all sub-agent tools when absent; includes Bash; does NOT blanket-allow MCP; preserves operator allow entries with no duplicates; never touches deny/ask; idempotent on second pass. All passing. Adjacent `PostUpdateMigrator-cleanupPeriodDays.test.ts` (same migrateSettings path) still green. `npm run build` green.
70
+ - **Second-pass review:** independent reviewer concurred; verified the safety argument against the docs and confirmed the guard chain is wired in the same migration pass, before the allow-rules.
@@ -0,0 +1,41 @@
1
+ # Side-Effects Review — Verify the State, Not Its Symbol (constitution amendment)
2
+
3
+ **Change:** Documentation-only. Adds the constitutional standard "Verify the State, Not Its
4
+ Symbol" to `docs/STANDARDS-REGISTRY.md` (Substrate section), registers it as **P20** in
5
+ `docs/INSTAR-DESIGN-PRINCIPLES-AND-LESSONS.md` (the surface the `/spec-converge` lessons-aware
6
+ reviewer loads), re-points L5 to P20 as its parent, updates the Part-4 reviewer range to P1-P20,
7
+ and lands the supporting analysis spec + ELI16. **No runtime/`src` surface.** Operator-ratified
8
+ (Justin, topic 16566, 2026-06-24) after independent verification that it is a real gap.
9
+
10
+ 1. **Over-block** — None. No code path, gate, or filter changes; nothing new can reject input.
11
+ The only behavioral effect is additive: the spec-converge reviewer gains one more lens (P20)
12
+ to flag a future spec — advisory findings, never a hard block of runtime behavior.
13
+ 2. **Under-block** — The standard is enforced today only via the lessons-aware reviewer (advisory)
14
+ + the companion code fix (the crystallizing instance). The `no-uncorroborated-symbol-fire` CI
15
+ ratchet that would mechanically catch *new* violating callsites is named as the next enforcement
16
+ surface, not yet built — so a brittle detector added between now and that ratchet relies on the
17
+ reviewer catching it. Stated honestly in the standard's "Applied through", not hidden.
18
+ 3. **Level-of-abstraction fit** — Correct layer. It is a Substrate (model-level truth) standard, a
19
+ parent of the existing L5 lesson and the AUP-wedge note; placed beside its siblings
20
+ (No Silent Degradation, Distrust Temporary Success) and registered in the same P-catalog the
21
+ reviewer already consumes. No new abstraction invented.
22
+ 4. **Signal vs authority (P2)** — Compliant and explicitly differentiated: the standard's text
23
+ states it is *orthogonal* to Signal-vs-Authority (which governs who may BLOCK) — it governs the
24
+ *evidentiary correctness* a detector must have whether it is a signal-emitter or a gate. The
25
+ amendment itself holds no authority; it is documentation feeding an advisory reviewer.
26
+ 5. **Interactions** — Touches the shared P-catalog: P18/P19 already existed, so the new entry is
27
+ **P20** (verified free) and the Part-4 range bumped P1-P19 → P1-P20. L5 gains a parent pointer.
28
+ No collision with the unrelated registry "No Unbounded Loops" P19 reference (left intact). No
29
+ migration surface (these docs are not agent-installed files; Migration Parity N/A).
30
+ 6. **External surfaces** — None. Internal developer-facing docs only; no user/agent/API surface,
31
+ no template (`generateClaudeMd`) change, no config, no hook.
32
+ 7. **Multi-machine posture** — N/A (documentation). The standard it describes is, for detectors,
33
+ machine-local-by-design (each machine verifies its own sessions) — captured in the companion
34
+ fix's own side-effects review, not here.
35
+ 8. **Rollback cost** — Trivial: revert the doc commit. No data, no state, no deployed behavior to
36
+ unwind. The companion code fix ships and rolls back independently on its own branch.
37
+
38
+ **Second-pass review:** Not required — documentation-only, no block/allow decision, no session
39
+ lifecycle, no gate/sentinel/watchdog code. (The companion CODE fix
40
+ `ratelimit-sentinel-false-positive-hardening`, which DOES touch sentinels, carries its own
41
+ mandatory Phase-5 second-pass on its own branch.)
@@ -0,0 +1,109 @@
1
+ # Side-Effects Review — Subagent permission allow-rules (the "session paused" fix)
2
+
3
+ **Version / slug:** `subagent-permission-allow-rules`
4
+ **Date:** `2026-06-24`
5
+ **Author:** `Instar Agent (echo)`
6
+ **Second-pass reviewer:** `general-purpose reviewer subagent (Phase 5 — touches permission allow/deny surface)`
7
+
8
+ ## Summary of the change
9
+
10
+ Adds `PostUpdateMigrator.ensurePermissionAllowRules()` and wires it into `migrateSettings()` so every agent's `.claude/settings.json` gains a `permissions.allow` list for the built-in tools a Task/Agent-spawned sub-agent uses (`Bash`, `Read`, `Edit`, `Write`, `Glob`, `Grep`, `Task`, `NotebookEdit`, `WebFetch`, `WebSearch`, `TodoWrite`). Root cause: a sub-agent does NOT inherit the parent session's `--dangerously-skip-permissions` MODE — only the permission RULES from settings.json. With no allow-rules, a sub-agent's first Bash call surfaces the interactive approval dialog and an unattended autonomous session freezes on it forever (the "session paused" bug; reproduced on this agent and AI Guy). Files: `src/core/PostUpdateMigrator.ts` (new method + one call site in `migrateSettings`), `tests/unit/PostUpdateMigrator-permissionAllowRules.test.ts` (6 tests).
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `migrateSettings() → ensurePermissionAllowRules()` — **add** — populates `permissions.allow` for subagent tools, set-if-missing per tool name; idempotent; never touches `deny`/`ask`.
15
+ - The interactive permission PROMPT for sub-agent local-tool calls — **remove** (only the human-in-the-loop prompt; the programmatic PreToolUse guards are untouched).
16
+
17
+ ---
18
+
19
+ ## 1. Over-block
20
+
21
+ **What legitimate inputs does this change reject that it shouldn't?**
22
+
23
+ No new block surface — this change only ADDS allow-rules, it never adds a deny. It cannot reject anything that worked before; the worst case direction is "allows too much," covered under §2. Over-block not applicable.
24
+
25
+ ---
26
+
27
+ ## 2. Under-block
28
+
29
+ **What failure modes does this still miss / does it allow too much?**
30
+
31
+ The allow-rules skip the interactive prompt for the listed local tools, so a human is no longer asked before a sub-agent runs e.g. an arbitrary Bash command. This is intentional and acceptable because the real safety is the PreToolUse guard chain (`dangerous-command-guard.sh`, `external-operation-gate.js`, `external-communication-guard.js`, `self-stop-guard.js`) which runs on EVERY tool call regardless of allow-rules — the prompt was duplicative friction, not the protective layer. Deliberately NOT covered: MCP tools (`mcp__*`) are left out of the allow list so external/network operations keep their external-operation-gate plan/approval posture. A sub-agent calling an MCP tool could still prompt — but MCP calls are not the wedge this fixes, and broadening to MCP would weaken the external-op gate's intended approval step.
32
+
33
+ ---
34
+
35
+ ## 3. Level-of-abstraction fit
36
+
37
+ **Is this at the right layer?**
38
+
39
+ Yes. `permissions.allow` in settings.json is the exact Claude Code mechanism that sub-agents inherit (per docs), so the fix lives at the layer that actually controls the behavior. The alternative — the `PermissionRequest` auto-approve hook — sits at a layer that does not reliably reach sub-agent calls, which is why it failed. Putting the rule in `migrateSettings()` (rather than only `init`) is the correct layer for Migration Parity: it reaches both new agents (init → refreshHooksAndSettings → migrateSettings) and the existing fleet (update → migrateSettings) through one code path, mirroring the established `cleanupPeriodDays` migration.
40
+
41
+ ---
42
+
43
+ ## 4. Signal vs authority compliance
44
+
45
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
46
+
47
+ - [x] No — this change has no block/allow surface that adds brittle blocking authority. It REMOVES a human-in-the-loop prompt while leaving every existing smart/programmatic gate (the PreToolUse guards) fully in force.
48
+
49
+ This change adds zero new decision authority. It does not inspect command content, classify, or gate — it declares static allow-rules so the existing PreToolUse authorities are the sole deciders. There is no brittle detector holding block power here.
50
+
51
+ ---
52
+
53
+ ## 5. Interactions
54
+
55
+ - **Shadowing:** none. Allow-rules and the PreToolUse hooks are orthogonal — an allow-rule skips the prompt; the hooks still fire and can still block (exit 2 / deny). The allow-rule cannot shadow a guard.
56
+ - **Double-fire:** the `PermissionRequest` auto-approve hook (`ensurePermissionAutoApprove`) remains in place as defense-in-depth. With allow-rules present, the prompt typically never arises, so the hook is a redundant backstop, not a conflicting one — both pushing toward "allow" is harmless.
57
+ - **Races:** none. `migrateSettings()` is a synchronous, idempotent file patch run at init/update; it shares no runtime state with live sessions. The new rules take effect only on the next session start (settings load once at spawn).
58
+ - **Feedback loops:** none.
59
+
60
+ ---
61
+
62
+ ## 6. External surfaces
63
+
64
+ - Other agents on the machine: unaffected at runtime — this only changes a file each agent reads at its own session start.
65
+ - Install base: every existing agent gains the allow-rules on its next update; new agents at init. This is the intended fleet-wide fix.
66
+ - External systems: none. No Telegram/Slack/GitHub/Cloudflare surface changes.
67
+ - Persistent state: writes `permissions.allow` into each agent's local `.claude/settings.json`. Idempotent, additive, reversible.
68
+ - **Operator surface (Mobile-Complete Operator Actions):** no operator-facing action added or changed — this is internal config plumbing. Not applicable.
69
+
70
+ ---
71
+
72
+ ## 6b. Operator-surface quality (Operator-Surface Quality standard)
73
+
74
+ No operator surface — this change touches no dashboard renderer, approval page, or grant/revoke/secret-drop form. Not applicable.
75
+
76
+ ---
77
+
78
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
79
+
80
+ **machine-local BY DESIGN.** `.claude/settings.json` is a per-machine file that Claude Code reads from local disk at session start; the permission rules must exist on whichever machine actually spawns the session. There is no cross-machine state to replicate — each machine's `PostUpdateMigrator` runs the same idempotent migration locally on its own update/init, so the fleet converges to identical allow-rules without any replication path. It emits no user-facing notices (no one-voice concern), holds no durable cross-topic state (nothing strands on topic transfer), and generates no URLs.
81
+
82
+ ---
83
+
84
+ ## 8. Rollback cost
85
+
86
+ Pure additive config migration. Back-out: revert the code change and ship as the next patch — new/updated agents simply stop gaining the allow-rules. Already-migrated agents keep a `permissions.allow` block in their settings.json; it is harmless (it only ever skipped a prompt the operator didn't want in an unattended run) and an operator can delete it by hand if desired. No data migration, no agent-state repair, no user-visible regression during the rollback window.
87
+
88
+ ---
89
+
90
+ ## Conclusion
91
+
92
+ The review produced no design changes. The fix is minimal, additive, idempotent, and scoped to the exact mechanism (inherited permission rules) that controls sub-agent prompting. It preserves all real safety (the PreToolUse guard chain) and only removes the human-in-the-loop prompt that was freezing unattended autonomous runs. Clear to ship pending second-pass concurrence.
93
+
94
+ ---
95
+
96
+ ## Second-pass review (if required)
97
+
98
+ **Reviewer:** general-purpose reviewer subagent
99
+ **Independent read of the artifact: concur**
100
+
101
+ Concur with the review. The reviewer independently verified, against Claude Code docs, that PreToolUse hooks run BEFORE permission-rule evaluation and a hook exiting 2 blocks the call even when the tool is in `permissions.allow` — the docs describe exactly this pattern (Bash in allow + a PreToolUse guard) as the recommended architecture, so the safety argument holds. Key corroboration: the SAME `migrateSettings()` pass calls `ensureInstarBashPreToolUseHooks()` (which registers the full `INSTAR_BASH_PRETOOLUSE_HOOKS` guard chain) BEFORE `ensurePermissionAllowRules()`, so any agent that gains the allow-rules gains the blocking guards in the same migration — no race, no window where allow-rules exist without the guards. Idempotency, non-clobbering of operator deny/ask, mcp__* exclusion, and the absence of any shared-array mutation were all confirmed. Non-blocking note: the allow list is a fixed in-code array; a future new built-in subagent tool won't be covered until the list is updated — benign failure direction (it would prompt, not over-allow).
102
+
103
+ ---
104
+
105
+ ## Evidence pointers
106
+
107
+ - `tests/unit/PostUpdateMigrator-permissionAllowRules.test.ts` — 6 tests: adds all subagent tools when absent; includes Bash; does NOT blanket-allow MCP; preserves operator allow entries + no dupes; never touches deny/ask; idempotent on second pass. All passing.
108
+ - Adjacent regression: `tests/unit/PostUpdateMigrator-cleanupPeriodDays.test.ts` still green (same `migrateSettings` path).
109
+ - `npm run build` green on the worktree.