instar 1.3.659 → 1.3.660
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/PostUpdateMigrator.d.ts +30 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +69 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/upgrades/1.3.660.md +27 -0
- package/upgrades/side-effects/subagent-permission-allow-rules.md +109 -0
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-25T07:17:11.166Z",
|
|
5
|
+
"instarVersion": "1.3.660",
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
1565
|
+
"contentHash": "4c5fa1d050d577392ce8e682974c6d495df23727ff7622a0ed01ff8fd6663c48",
|
|
1566
1566
|
"since": "2025-01-01"
|
|
1567
1567
|
},
|
|
1568
1568
|
"subsystem:scheduler": {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
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.
|
|
9
|
+
|
|
10
|
+
`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).
|
|
11
|
+
|
|
12
|
+
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.
|
|
13
|
+
|
|
14
|
+
## What to Tell Your User
|
|
15
|
+
|
|
16
|
+
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.
|
|
17
|
+
|
|
18
|
+
## Summary of New Capabilities
|
|
19
|
+
|
|
20
|
+
- `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).
|
|
21
|
+
|
|
22
|
+
## Evidence
|
|
23
|
+
|
|
24
|
+
- **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).
|
|
25
|
+
- **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).
|
|
26
|
+
- **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.
|
|
27
|
+
- **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,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.
|