Commit c43a3eb
authored
fix(coding-agents): run the opencode survey under our own agent, not plan mode (#3460)
* fix(coding-agents): run the opencode survey under our own agent, not plan mode
Fixes #3450.
The codebase survey ran as `opencode run --agent plan`, chosen as the read-only
boundary for a session that reads untrusted repo files. But plan mode is not a
permission boundary for what the survey needs to do — it is a PROMPT. Captured
from a live opencode 1.18.9 session (fake model endpoint, so this is the request
opencode actually builds, not an inference from behaviour), every user message
carries:
CRITICAL: Plan mode ACTIVE - you are in READ-ONLY phase. STRICTLY FORBIDDEN:
ANY file edits, modifications, or system changes ... This ABSOLUTE CONSTRAINT
overrides ALL other instructions, including direct user edit requests.
while `hindsight_ingest_document` stays in the tool list — plan's ruleset denies
only `edit`. So the survey is handed a tool and told not to use it, and whether
the repo gets seeded depends on how literally the model reads "system changes".
#3450 saw it stall on ~half their repos, the agent asking for an approval plan
mode cannot grant even when the user says yes.
Wording cannot fix this: the reminder claims to override all other instructions,
and the reporter's transcript is the model saying exactly that back to them.
So the survey now runs under an agent this plugin defines itself, through
opencode's `config` hook — nothing lands in the user's opencode.json, and an
entry they defined under that name wins. Measured on the same rig:
--agent plan reminder in 9/9 captured requests
--agent hindsight-survey reminder in 0, tools offered: glob, grep, read,
hindsight_ingest_document
It is also a TIGHTER sandbox than plan mode, which is what makes it safe for
untrusted repo content. opencode drops denied tools from the model's tool list
entirely, so `"*": "deny"` plus four allows is the boundary: no write, no bash,
and no `task` — plan left all three reachable, and `task` reaches a subagent that
can write. Probed live by asking the survey agent to create a file and to run
touch: both refused, neither file appeared.
Verified end to end against a live opencode with no agent in the user's config,
so the definition could only come from the plugin: 4 ingest calls per run.
* fix(coding-agents): pin the opencode config hook to the SDK's own Hooks type
Code review on the parent commit: nothing checked that `config` is a hook name
opencode actually calls. plugin-entry.ts casts the whole runtime object to the
host's Hooks type — the other hooks take deliberately narrower params than the
SDK declares, so they cannot be checked — which means a misnamed or re-signatured
hook would compile, silently never fire, and leave the survey invoking an agent
the host never heard of.
Declaring just this hook as `Pick<Hooks, "config">` restores the check where it
matters. Confirmed by renaming it: tsc now fails with "Object literal may only
specify known properties, but 'configg' does not exist in type
Pick<Hooks, "config">".
The one cast that remains is `permission`, which the published type models with a
fixed key set (edit/bash/webfetch/…) while the runtime takes arbitrary action
names — opencode's own built-in `explore` agent is defined with `"*": "deny"`
plus per-tool allows. Casting the agent entry beats widening it to `unknown`,
which would drop the checking on `description`/`mode` as well.
Re-verified against live opencode 1.18.9 after the change: 4 ingest calls, same
as before. 499 tests, tsc and prettier clean.1 parent 4afe43e commit c43a3eb
4 files changed
Lines changed: 149 additions & 11 deletions
File tree
- hindsight-integrations/coding-agents/src
- core
- harness
Lines changed: 28 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
3 | 9 | | |
4 | 10 | | |
5 | 11 | | |
| |||
125 | 131 | | |
126 | 132 | | |
127 | 133 | | |
128 | | - | |
129 | | - | |
| 134 | + | |
| 135 | + | |
130 | 136 | | |
131 | 137 | | |
132 | 138 | | |
| |||
135 | 141 | | |
136 | 142 | | |
137 | 143 | | |
138 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
139 | 148 | | |
140 | 149 | | |
141 | 150 | | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
142 | 166 | | |
143 | 167 | | |
144 | 168 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
61 | 95 | | |
62 | 96 | | |
63 | 97 | | |
| |||
232 | 266 | | |
233 | 267 | | |
234 | 268 | | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
239 | 276 | | |
240 | 277 | | |
241 | | - | |
| 278 | + | |
242 | 279 | | |
243 | 280 | | |
244 | 281 | | |
| |||
Lines changed: 47 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
Lines changed: 30 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| 23 | + | |
22 | 24 | | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
26 | 55 | | |
27 | 56 | | |
28 | 57 | | |
| |||
64 | 93 | | |
65 | 94 | | |
66 | 95 | | |
| 96 | + | |
67 | 97 | | |
68 | 98 | | |
69 | 99 | | |
| |||
0 commit comments