@lyupro/codex-bridge 0.5.1 → 0.5.3
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/CHANGELOG.md +420 -252
- package/README.md +21 -4
- package/bin/codex-bridge.mjs +4 -0
- package/cli/doctor.mjs +399 -293
- package/cli/frontmatter.mjs +137 -0
- package/cli/hook.mjs +2 -2
- package/cli/install-record.mjs +2 -2
- package/cli/install.mjs +14 -2
- package/cli/manifest.mjs +23 -22
- package/cli/permissions.mjs +2 -2
- package/cli/projects.mjs +3 -3
- package/cli/prune-plan.mjs +2 -2
- package/cli/prune.mjs +1 -1
- package/cli/read.mjs +2 -2
- package/cli/rules-owners.mjs +2 -2
- package/cli/run-lookup.mjs +3 -3
- package/cli/runs-inventory.mjs +3 -3
- package/cli/settings-merge.mjs +56 -11
- package/cli/stop.mjs +5 -5
- package/cli/unlock.mjs +7 -7
- package/package.json +2 -2
- package/scripts/check-file-size.mjs +1 -1
- package/scripts/run-tests.mjs +30 -1
- package/scripts/suite-count.mjs +65 -0
- package/src/agents/codex-build.md +265 -231
- package/src/agents/codex-review.md +219 -184
- package/src/agents/codex-scout.md +232 -200
- package/src/{hooks → home/hooks}/guard-tries.mjs +1 -1
- package/src/{hooks → home/hooks}/live-runs.mjs +43 -3
- package/src/home/hooks/order-gate.mjs +135 -0
- package/src/{hooks → home/hooks}/prune-guard.mjs +2 -2
- package/src/{hooks → home/hooks}/reply-guard.mjs +117 -97
- package/src/home/hooks/reply-parser.mjs +27 -0
- package/src/home/hooks/reply-verdicts.mjs +174 -0
- package/src/home/hooks/shell-write-intent.mjs +120 -0
- package/src/{hooks → home/hooks}/stop-guard.mjs +3 -3
- package/src/home/hooks/worktree-lock.mjs +109 -0
- package/src/home/hooks/worktree-witness.mjs +113 -0
- package/src/home/lib/dispatcher-order.mjs +36 -0
- package/src/{heartbeat.mjs → home/lib/heartbeat.mjs} +4 -1
- package/src/{hook-definitions.mjs → home/lib/hook-definitions.mjs} +11 -2
- package/src/home/lib/host-refusal.mjs +20 -0
- package/src/{json-file.mjs → home/lib/json-file.mjs} +4 -4
- package/src/{meta → home/lib/meta}/paths.mjs +20 -1
- package/src/{meta → home/lib/meta}/reply.mjs +1 -1
- package/src/{meta → home/lib/meta}/verdict.mjs +1 -1
- package/src/{no-self-execution.mjs → home/lib/no-self-execution.mjs} +7 -2
- package/src/{required-inputs.mjs → home/lib/required-inputs.mjs} +56 -5
- package/src/{retention.mjs → home/lib/retention.mjs} +1 -1
- package/src/{run-codex.mjs → home/lib/run-codex.mjs} +39 -11
- package/src/{run-config.mjs → home/lib/run-config.mjs} +2 -2
- package/src/{runner → home/lib/runner}/args.mjs +86 -10
- package/src/{runner → home/lib/runner}/attach.mjs +58 -9
- package/src/{runner → home/lib/runner}/codex-cmd.mjs +398 -392
- package/src/{runner → home/lib/runner}/launcher.mjs +33 -21
- package/src/home/lib/runner/order-owner.mjs +28 -0
- package/src/{runner → home/lib/runner}/run-env.mjs +1 -1
- package/src/home/lib/runner/sandbox-flags.mjs +27 -0
- package/src/home/lib/runner/task-file.mjs +92 -0
- package/src/home/lib/runner/task-input.mjs +26 -0
- package/src/{runner → home/lib/runner}/worker.mjs +1 -1
- package/src/home/lib/shell-unsafe.mjs +26 -0
- package/src/{write-meta.mjs → home/lib/write-meta.mjs} +12 -1
- package/src/hooks/order-gate.mjs +0 -73
- package/src/hooks/worktree-lock.mjs +0 -77
- /package/src/{run-config.json → home/config.json} +0 -0
- /package/src/{conventions.md → home/conventions.md} +0 -0
- /package/src/{cli-names.mjs → home/lib/cli-names.mjs} +0 -0
- /package/src/{meta → home/lib/meta}/chain.mjs +0 -0
- /package/src/{meta → home/lib/meta}/deadline.mjs +0 -0
- /package/src/{meta → home/lib/meta}/environment.mjs +0 -0
- /package/src/{meta → home/lib/meta}/events.mjs +0 -0
- /package/src/{meta → home/lib/meta}/outcome.mjs +0 -0
- /package/src/{meta → home/lib/meta}/pre-start.mjs +0 -0
- /package/src/{meta → home/lib/meta}/reason.mjs +0 -0
- /package/src/{meta → home/lib/meta}/run-state.mjs +0 -0
- /package/src/{meta → home/lib/meta}/startup.mjs +0 -0
- /package/src/{meta → home/lib/meta}/transport.mjs +0 -0
- /package/src/{process-identity.mjs → home/lib/process-identity.mjs} +0 -0
- /package/src/{runner → home/lib/runner}/continuation.mjs +0 -0
- /package/src/{runner → home/lib/runner}/conventions.mjs +0 -0
- /package/src/{runner → home/lib/runner}/git-state.mjs +0 -0
- /package/src/{runner → home/lib/runner}/project-dir.mjs +0 -0
- /package/src/{runner → home/lib/runner}/prompts.mjs +0 -0
- /package/src/{runner → home/lib/runner}/run-context.mjs +0 -0
- /package/src/{runner → home/lib/runner}/runs-root.mjs +0 -0
- /package/src/{runner → home/lib/runner}/schemas.mjs +0 -0
- /package/src/{runner → home/lib/runner}/scope-check.mjs +0 -0
- /package/src/{stop-contract.mjs → home/lib/stop-contract.mjs} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,252 +1,420 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
-
|
|
7
|
-
## [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- The
|
|
25
|
-
`
|
|
26
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- The
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
###
|
|
199
|
-
|
|
200
|
-
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
-
|
|
251
|
-
|
|
252
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.5.3] - 2026-08-23
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- The worktree lock knew writing by tool name, and a shell writes anyway. It denies edits inside a
|
|
12
|
+
repository held by a live `codex-build` run, but was registered only for
|
|
13
|
+
`Write|Edit|MultiEdit|NotebookEdit`; on 2026-08-16 a `python - <<PY` heredoc inside `Bash` walked
|
|
14
|
+
past it and appended to `CHANGELOG.md`, and the run reported `FAIL — out-of-scope changes (1)`
|
|
15
|
+
for work it had finished correctly. Two guards now cover the gap from both sides. The lock's
|
|
16
|
+
matcher takes in shell tools as well, and `shell-write-intent.mjs` refuses the obvious forms —
|
|
17
|
+
redirection, `tee`, `sed -i`, `cp`, `mv`, `rm`, `touch`, `truncate`, a heredoc fed to an
|
|
18
|
+
interpreter — before they run. Behind it, `worktree-witness.mjs` compares the tree after every
|
|
19
|
+
shell command against the run's recorded snapshot, drops everything inside the run's declared
|
|
20
|
+
scope, and names whatever is left: a run may only write inside its scope, so the rest is another
|
|
21
|
+
hand. The recogniser states in its own header that its list is not complete and cannot become one
|
|
22
|
+
— that is precisely why the witness stands behind it.
|
|
23
|
+
|
|
24
|
+
- The recogniser knew `sed` and did not know `sed.exe`. Its interpreter pattern had always allowed
|
|
25
|
+
the suffix — `python.exe` opens a heredoc like `python` does — but the command list compared bare
|
|
26
|
+
basenames, so the spelling this platform hands over walked past the guard while the identical
|
|
27
|
+
command without the suffix was refused. Found accepting a delegated run of 2026-08-17 that had
|
|
28
|
+
recorded the gap as intended behaviour: a test asserting `sed.exe -i` is not a write. A test that
|
|
29
|
+
states a defect is true keeps it, so the recogniser now strips the suffix and the case asserts the
|
|
30
|
+
refusal.
|
|
31
|
+
|
|
32
|
+
- Delegated read-only runs could not execute a single command. codex-cli 0.149.0 on Windows builds
|
|
33
|
+
its sandbox from `windows.sandbox` — `elevated` or `unelevated` — and the unelevated token refuses
|
|
34
|
+
CreateProcess outright: every command a run tried came back as
|
|
35
|
+
`Rejected("… rejected: blocked by policy")` before the process existed. The setting lives in the
|
|
36
|
+
operator's `config.toml`, which `--ignore-user-config` drops on purpose, so on 2026-08-23 every
|
|
37
|
+
`codex-scout` and `codex-review` run reported honestly that it could not read anything and was
|
|
38
|
+
then failed by its own quality gate for having no code references. `codex-build` kept working, and
|
|
39
|
+
that looked like "read-only is broken" — but it is the one agent that does not pass
|
|
40
|
+
`--ignore-user-config`, so it inherited the key from a line in a personal file the package does
|
|
41
|
+
not own; with that flag its `workspace-write` runs are refused just as flatly. Four probes on the
|
|
42
|
+
installed CLI, differing by this flag alone, separate the two. All three agents now pass
|
|
43
|
+
`-c windows.sandbox=elevated` on Windows, so isolation from the operator's config stays intact and
|
|
44
|
+
the sandbox each agent is entitled to is the one it actually gets. The value carries no quotes
|
|
45
|
+
because the command line goes through cmd.exe, where a double quote is refused before launch.
|
|
46
|
+
|
|
47
|
+
- A hook fix could not reach a host that already had the hook. Installation identifies our entry by
|
|
48
|
+
its command and ignores which matcher group it sits under — deliberately, because the matcher
|
|
49
|
+
grows whenever a host spelling is added and a lookup by matcher would register a duplicate and
|
|
50
|
+
orphan the old entry at uninstall — but nothing afterwards moved the entry to the matcher the
|
|
51
|
+
package declares now. A host installed before 2026-08-17 kept `Write|Edit|MultiEdit|NotebookEdit`
|
|
52
|
+
for the worktree lock while the package had been saying `…|Bash|PowerShell` for days:
|
|
53
|
+
`update --force` reported success and rewrote nothing, so the guard never saw a shell command and
|
|
54
|
+
two honest delegated runs were failed for a file written through their window. Merge now moves the
|
|
55
|
+
entry under the declared matcher, drops the group it emptied, leaves a group holding someone
|
|
56
|
+
else's hooks exactly as it was, and still cannot produce a second registration of our command for
|
|
57
|
+
one event.
|
|
58
|
+
|
|
59
|
+
- `doctor` stated the matcher this package expects as though it had read it. Its hook line was built
|
|
60
|
+
from the registry, so a host still registered under an older matcher was reported as healthy with
|
|
61
|
+
the new matcher's text — on 2026-08-17 it printed `…|Bash|PowerShell` over a `settings.json` that
|
|
62
|
+
said `Write|Edit|MultiEdit|NotebookEdit`, and the operator had no way to see that the worktree
|
|
63
|
+
lock could not see a shell command at all. Same shape as the 2026-08-10 defect in this file:
|
|
64
|
+
a check that compares the package with itself cannot fail. The line now prints the matcher the
|
|
65
|
+
host recorded, and a difference from the declared one is a `warn` naming both values and
|
|
66
|
+
`codex-bridge update --force`.
|
|
67
|
+
|
|
68
|
+
- The worktree lock refused four kinds of work it cannot protect. A miss by this guard is
|
|
69
|
+
survivable — the witness names the fact afterwards — but a false refusal has no backstop and
|
|
70
|
+
simply stops the orchestrator. An ignored path was refused, which made the plans and checklists a
|
|
71
|
+
live run is documented in unwritable, although a run is only ever failed for what
|
|
72
|
+
`git status` reports; an unexpanded shell variable was resolved against the working directory and
|
|
73
|
+
refused as a path inside the repository; a backtick in the TEXT of a heredoc was refused as a
|
|
74
|
+
path; and a comparison operator in code (`node -e "i>0?'yes':'no'"`) was read as a redirection.
|
|
75
|
+
The lock now passes a path git proves is ignored — and only that, so a missing repository or a
|
|
76
|
+
missing git keeps the refusal, while `.git` stays refused whatever git answers — a redirect
|
|
77
|
+
target wins over document text (the 2026-08-16 python heredoc is still refused), and a candidate
|
|
78
|
+
opening with `$`, `%` or a backtick, or holding a character no file name may contain, is not
|
|
79
|
+
reported as a target.
|
|
80
|
+
|
|
81
|
+
- Every number this package advertises about itself was wrong. The npm description said "5 guards,
|
|
82
|
+
604 tests" — a count three releases old, next to a registry that had grown a sixth hook the same
|
|
83
|
+
week — README said 705 while the suite ran 757, and CLAUDE.md said five guard hooks. Each was
|
|
84
|
+
caught by eye during a release, which is how the one in `package.json` survived three of them: a
|
|
85
|
+
number written in prose has no reader that can fail. The whole-suite run now compares the size
|
|
86
|
+
README claims against what the run reported and exits non-zero naming both, and a test holds the
|
|
87
|
+
guard count in README, CLAUDE.md and the package description against `HOOK_DEFINITIONS`. Deleting
|
|
88
|
+
the sentence fails the same way an outdated one does; a single-file run reports nothing to
|
|
89
|
+
compare and stays silent.
|
|
90
|
+
|
|
91
|
+
## [0.5.2] - 2026-08-16
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
|
|
95
|
+
- The guard punished the very refusal the package demands. A dispatcher whose command the host
|
|
96
|
+
denies is told by its own prompt to answer `FAIL`, name its order id and name `codex-bridge
|
|
97
|
+
install`; the guard knew only `RUN=` and `ATTACH=`, so that honest answer read as "no run
|
|
98
|
+
exists" and was blocked three times before the exhausted try budget let it through. A probe on
|
|
99
|
+
2026-08-16 with `Bash(codex-bridge:*)` denied spent 31.5k tokens on an answer worth ten, and the
|
|
100
|
+
counter recorded `{"state": 3}` against it. A host refusal is now a recognised shape beside the
|
|
101
|
+
two run lines: a reply that declares failure, names its order id and names the remedy passes on
|
|
102
|
+
the first try, before any check that looks for a folder on disk. A reply that declares failure and
|
|
103
|
+
names the remedy but omits the order id is blocked with that exact part named — the prompt asked
|
|
104
|
+
for it in prose, and prose is a request a model can silently skip.
|
|
105
|
+
|
|
106
|
+
- No Claude Code host had registered the three dispatchers since 2026-08-10. The stop-guidance
|
|
107
|
+
sentence added that day — `` before `TaskStop`: TaskStop removes the wrapper … `` — was
|
|
108
|
+
substituted into the `description:` line of each agent's frontmatter, and an unquoted YAML scalar
|
|
109
|
+
cannot contain a colon followed by a space: the frontmatter did not parse, so the agents did not
|
|
110
|
+
exist as far as the host was concerned. `doctor` reported every file present the whole time,
|
|
111
|
+
because it counted files instead of reading them. Installation now re-emits frontmatter as valid
|
|
112
|
+
YAML — any value a reader would not take as a plain scalar is quoted, the sentence survives
|
|
113
|
+
verbatim — `doctor` parses each installed definition and checks its `name`, and the suite parses
|
|
114
|
+
everything the installer would write.
|
|
115
|
+
|
|
116
|
+
- A run ordered under another run's order id is no longer answered with that run's verdict. On
|
|
117
|
+
2026-08-15 a build ordered as `plan42-run3` carried the id of `plan42-run2`, and the runner
|
|
118
|
+
printed run2's `OK`, run2's file list and run2's suite over a worktree where nothing had been
|
|
119
|
+
done — only a manual `git status` stopped a commit of work that did not exist. An order id names
|
|
120
|
+
one task: when the id already belongs to a run whose task text differs, the runner now refuses
|
|
121
|
+
with exit code `2` before printing anything, naming the folder that owns the id and the two
|
|
122
|
+
remedies (a new `--order-id`, or `--continue`). Repeats of the same task, continuations, and runs
|
|
123
|
+
recorded before the `task_hash` field attach exactly as before.
|
|
124
|
+
- The same collision is now refused one step earlier and checked one step later. `order-gate` denies
|
|
125
|
+
the dispatcher call itself when the ordered id already belongs to a run with a different task —
|
|
126
|
+
before any quota is spent — and `reply-guard` blocks a reply whose run records a different
|
|
127
|
+
`order_id` than the one the orchestrator ordered, read from the dispatcher's own transcript. Both
|
|
128
|
+
read the single definition of "the same task" the runner uses; a second copy of that rule would
|
|
129
|
+
drift silently, which is the failure this change exists to end. Every uncertain disk state — an
|
|
130
|
+
unreadable task file, a missing runs directory, a run folder written before its `status.json` —
|
|
131
|
+
passes, because a guard nobody can predict is a guard everyone works around.
|
|
132
|
+
- Delegating to a dispatcher no longer stops on a permission prompt. The shipped agent definitions
|
|
133
|
+
started a run by absolute path — `node "<installed dir>/run-codex.mjs" --agent … \ …` — and a host
|
|
134
|
+
matches permission rules against the beginning of a command line, so a rule written for this
|
|
135
|
+
package could never match it. The only way to start a run is now the package command,
|
|
136
|
+
`codex-bridge run`, on a single line: no interpreter, no path, no line continuation. The task
|
|
137
|
+
statement travels as `--task-file`, because a heredoc forces the invocation back into the
|
|
138
|
+
multi-line form that no rule can cover; stdin remains supported for the direct call, and giving
|
|
139
|
+
both channels is a refusal rather than a silent precedence.
|
|
140
|
+
- Installed hooks could not run at all. The installer reshaped the source tree — hooks to one
|
|
141
|
+
directory, their modules to another — so every hook's relative import was correct in the clone and
|
|
142
|
+
false on the host, and all five guards died on `ERR_MODULE_NOT_FOUND` from the day the package
|
|
143
|
+
moved to its branded folder. The suite stayed green because it exercises the clone, and `doctor`
|
|
144
|
+
called a hook healthy on the strength of a line in `settings.json` without ever starting the file.
|
|
145
|
+
The source now contains a literal image of the installed home, `src/home/`, and installation
|
|
146
|
+
copies it one to one.
|
|
147
|
+
- The reply guard no longer sends a refused dispatcher down the one road the host cannot allow.
|
|
148
|
+
Seven of its block texts said "Run run-codex.mjs and return its stdout verbatim" — the sentence
|
|
149
|
+
removed from every prompt in this release, because a command line naming a file can match no
|
|
150
|
+
permission rule. They were the worst place for it to survive: a dispatcher reads them at the one
|
|
151
|
+
moment it is looking for what to do next, having just had its answer rejected. All seven name
|
|
152
|
+
`codex-bridge run`. The invariant behind them was the actual defect and is now stated as a rule
|
|
153
|
+
rather than as a shape: no line of code in a hook may name the runner file, whole-line comments
|
|
154
|
+
excepted. The earlier expression-bound check could not see the text a session is shown when its
|
|
155
|
+
turn is ended, which is where the same sentence would have survived a fourth cleanup.
|
|
156
|
+
- `doctor` no longer calls a host healthy when an installed agent definition is not this package's.
|
|
157
|
+
Drift was advisory — a message, exit code 0 — while an unreadable definition was already fatal. A
|
|
158
|
+
checklist run planted the pre-0.5.2 invocation, a file path instead of the package command, in an
|
|
159
|
+
installed agent: `doctor` printed the drift and still exited 0, so a script or a CI step would
|
|
160
|
+
have called that host healthy while every delegation on it stopped at a permission prompt. Any
|
|
161
|
+
definition that differs from the package now exits 1 and names `codex-bridge update --force`.
|
|
162
|
+
|
|
163
|
+
### Added
|
|
164
|
+
|
|
165
|
+
- `codex-bridge run` — the public entry point for starting a delegated run, with the same flags,
|
|
166
|
+
stdout and exit codes as the historical file invocation.
|
|
167
|
+
- Both lines that identify a run to its caller carry the order they belong to:
|
|
168
|
+
`RUN=<path> order-id=<id>` and `ATTACH=<path> order-id=<id> started=<time>`. A reply naming a run
|
|
169
|
+
cannot be checked against the order that was placed unless the id travels with the folder.
|
|
170
|
+
- Two structural guards that make the above regressions loud instead of silent: the install plan
|
|
171
|
+
must stay isomorphic to the shipped home image, and every registered hook must actually start as
|
|
172
|
+
a child process with its imports resolved.
|
|
173
|
+
- `doctor` compares the version answering a hook against the installed copy, verifies the installed
|
|
174
|
+
agent definitions against the repository, and downgrades to a warning instead of reporting code it
|
|
175
|
+
never ran as healthy.
|
|
176
|
+
|
|
177
|
+
## [0.5.1] - 2026-08-12
|
|
178
|
+
|
|
179
|
+
### Fixed
|
|
180
|
+
|
|
181
|
+
- Installing or uninstalling no longer fails over a rules-registry lock that is busy for one more
|
|
182
|
+
millisecond. Windows answers a taken lock with three codes, and only one of them is `EEXIST`: a
|
|
183
|
+
lock file whose delete is still pending comes back `EPERM`, and a file another process still
|
|
184
|
+
holds comes back `EBUSY` — the acquisition loop treated both as fatal instead of waiting. All
|
|
185
|
+
three now mean "not yours yet", and the decision lives in one exported check, `isLockTaken()`.
|
|
186
|
+
|
|
187
|
+
### Changed
|
|
188
|
+
|
|
189
|
+
- The README's first screen names the problem the package solves, keeps the install command inside
|
|
190
|
+
the first 30 lines, adds a second badge row, and shows `doctor` output from a healthy host in
|
|
191
|
+
place of a screenshot.
|
|
192
|
+
- The reference documentation under `docs/` is English-only now (`overview.ru.md` became
|
|
193
|
+
`overview.md`), and the working folders — plans, checklists and audits — left the repository and
|
|
194
|
+
its history: a fresh clone contains the five reference documents and nothing else.
|
|
195
|
+
|
|
196
|
+
## [0.5.0] - 2026-08-11
|
|
197
|
+
|
|
198
|
+
### Added
|
|
199
|
+
|
|
200
|
+
- A fifth host guard now catches `TaskStop` while a live Codex run is still writing to the
|
|
201
|
+
repository, names the run and points to `codex-bridge stop <run>` before allowing a repeated
|
|
202
|
+
request. `doctor` and `projects` also surface active runs, so stopping a dispatcher wrapper is
|
|
203
|
+
no longer mistaken for stopping its detached worker.
|
|
204
|
+
- `codex-bridge hook <name>` gives Claude Code a stable way to invoke each installed guard, and
|
|
205
|
+
`meta.json` now records the package version that produced a run. The usage report can therefore
|
|
206
|
+
separate historical runs made outside this runner from runs that should satisfy its sandbox
|
|
207
|
+
contract.
|
|
208
|
+
|
|
209
|
+
### Changed
|
|
210
|
+
|
|
211
|
+
- **Breaking:** the installed package layout now uses `agents/codex-bridge/` instead of
|
|
212
|
+
`agents/codex/`, `commands/codex-bridge/` instead of `commands/codex/`, and
|
|
213
|
+
`~/.lyupro/.codex-bridge/lib/` for the runner and guards. Slash commands are now
|
|
214
|
+
`/codex-bridge:usage` and `/codex-bridge:env`, and hooks in `settings.json` use
|
|
215
|
+
`codex-bridge hook <name>` when the matching package version is available. Run
|
|
216
|
+
`codex-bridge update` to migrate an existing installation and retire the old layout.
|
|
217
|
+
- Runs started without an explicit `--slug` now derive a readable folder name from the required
|
|
218
|
+
order id instead of grouping unrelated work under the dispatcher name. Existing run folders
|
|
219
|
+
remain discoverable by their order id and task fingerprint.
|
|
220
|
+
- The README now leads with the package's guarantees, verification and update guidance, and
|
|
221
|
+
limitations before the command reference, and the repository now publishes a security policy
|
|
222
|
+
and private vulnerability-reporting route.
|
|
223
|
+
|
|
224
|
+
### Fixed
|
|
225
|
+
|
|
226
|
+
- Guards invoked through a global-install symlink no longer exit successfully without running;
|
|
227
|
+
the direct-invocation check now compares resolved files, so a silent guard cannot allow every
|
|
228
|
+
operation while `doctor` reports it healthy. Hook registration also chooses the short command
|
|
229
|
+
form only when the command on `PATH` is this package's exact version, rather than merely present.
|
|
230
|
+
- Retiring the previous layout no longer removes the shared Claude Code `agents/` and `commands/`
|
|
231
|
+
directories. Seeded operator files are moved only after byte verification, and an interrupted
|
|
232
|
+
migration is retried by the next `update` even when the new files are already current.
|
|
233
|
+
- A continuation grant that loses its `--continue` flag is now refused before attachment instead
|
|
234
|
+
of replaying an older run's verdict as though new work ran. Attachment output also states
|
|
235
|
+
explicitly that no new work was started.
|
|
236
|
+
- The test suite now isolates both installation roots, preventing tests from writing fixtures or
|
|
237
|
+
seeded configuration into the operator's real `~/.lyupro/.codex-bridge/` directory. Migration
|
|
238
|
+
dry runs also name the hook event and matcher instead of printing `undefined`.
|
|
239
|
+
|
|
240
|
+
## [0.4.0] - 2026-08-09
|
|
241
|
+
|
|
242
|
+
### Added
|
|
243
|
+
|
|
244
|
+
- Scope patterns are checked before Codex starts. A pattern that cannot match anything — an
|
|
245
|
+
absolute or drive-qualified path, backslash separators, a `..` segment, or a spelling no
|
|
246
|
+
repository file answers to — is refused with no run folder and no quota spent, for all three
|
|
247
|
+
dispatchers. The file list comes from `git ls-files --cached --others --exclude-standard`, so
|
|
248
|
+
ignored output does not count as repository content. A file the run is meant to create is
|
|
249
|
+
declared with `--scope-new`, accepted only by `codex-build` and recorded in `worker.json`.
|
|
250
|
+
- `codex-bridge permissions` reports, adds, and removes the optional shell permission rules for
|
|
251
|
+
both CLI names and the clone entry point. The exact allow and deny strings merge into
|
|
252
|
+
`settings.json`, preserve foreign rules, and are also removed by `uninstall`; `doctor` reports
|
|
253
|
+
an absent or partial set as an optional warning.
|
|
254
|
+
|
|
255
|
+
### Changed
|
|
256
|
+
|
|
257
|
+
- `codex-bridge sweep` is now `codex-bridge unlock`. The default scope is the current repository;
|
|
258
|
+
a bare project name remains addressable, and `--all` is now required for the whole store. The
|
|
259
|
+
report shows age, silence, and `alive` / `dead` / `foreign` / `unverified` identity verdicts;
|
|
260
|
+
confirmed-alive records are refused with `codex-bridge stop <run>` instead of being closed.
|
|
261
|
+
|
|
262
|
+
### Fixed
|
|
263
|
+
|
|
264
|
+
- Run records now verify that a pid still belongs to the process that started the run, using the
|
|
265
|
+
process start time and a fresh heartbeat before falling back to an OS probe. A reused or
|
|
266
|
+
unverified pid is never signalled by `stop`; `codex-bridge unlock` remains the non-killing way to
|
|
267
|
+
close a record whose process identity cannot be confirmed.
|
|
268
|
+
- JSON files written by PowerShell with a UTF-8 BOM are now read consistently by the CLI and
|
|
269
|
+
installed hooks, and one command run creates at most one settings backup without deleting older
|
|
270
|
+
backups.
|
|
271
|
+
- A run a guard refused before Codex ever started no longer costs the next attempt a round trip. Such a folder now closes as `aborted_pre_start` instead of the same `failed` a twenty-minute paid run gets, and the chain gate, the continuation limit and the tree baseline all skip it: the same order id starts as a first run, silently, with no `continue:` grant. Reported from a parallel `codex-build` launch — the second run was correctly refused with "two writing runs in one tree are prohibited", and its one-millisecond folder then made the retry demand a grant for work that never happened. Folders written before this release are recognised by what `meta.json` records — `exit`, `session_id`, `events_bytes`, `stderr_bytes`, `tokens_reported` — rather than by whether `events.jsonl` is still on disk, because retention deletes that file from paid runs too. The folder itself is kept: it is the audit trail of who was refused and why.
|
|
272
|
+
- `chainBaseline()` takes the first run of the chain that actually started, so a pre-start folder sorting first no longer leaves the next pass without the `state-before.txt` its work is measured against.
|
|
273
|
+
- `uninstall --dry-run` names each hook by its own matcher. Three of the four hooks are PreToolUse,
|
|
274
|
+
and a lookup by event alone reported `Agent|Task` for the worktree lock and the prune guard too —
|
|
275
|
+
in the one line an operator reads to see what a removal is about to touch. The removal itself was
|
|
276
|
+
never affected: hooks are found by command, not by matcher.
|
|
277
|
+
- The order gate's refusal now shows the line it found. A caller who wrote
|
|
278
|
+
`scope (you may create/modify ONLY these):` was told scope was missing, re-read their own prompt,
|
|
279
|
+
saw it written there, and had nothing to act on; an autonomous run rewrites the same text forever.
|
|
280
|
+
The refusal names the candidate line under the input it belongs to and says why it was not
|
|
281
|
+
accepted — a qualifier between the label and the colon, a value that is still a placeholder, or no
|
|
282
|
+
separator at all — and stays silent when no candidate exists, because then "the input is missing"
|
|
283
|
+
is the truth. The parser accepts exactly what it accepted before: deriving scope from prose would
|
|
284
|
+
give away the only guarantee that a run cannot touch files nobody listed.
|
|
285
|
+
|
|
286
|
+
## [0.3.1] - 2026-08-07
|
|
287
|
+
|
|
288
|
+
### Added
|
|
289
|
+
|
|
290
|
+
- The CLI answers to `codexb` as well as `codex-bridge`, and README now documents the global install that puts both names on `PATH`. Every spelling that can reach deletion comes from one frozen list, and the prune guard builds its matcher from that list rather than repeating the names — two independent lists drift silently, which is exactly how the installer and test hook lists had already drifted. The full name stays primary: the docs, checklists and three agent prompts are written with it.
|
|
291
|
+
- Every run carries the rules it is judged by. A seeded `conventions.md` beside `run-config.json` and an optional `.codex-conventions.md` in the repository being worked on are pasted into `task.md` verbatim, under one `## Conventions` section. Either file missing is not an error, and a blank one produces no section at all — rules handed over as an empty heading read as rules ignored. Until now project rules reached a run only when the orchestrator remembered to write "read CLAUDE.md" into the task, and six acceptance passes in a row caught the same class of violation: the rule existed, applied, and had not travelled. Pasting rather than referencing is the point — "read file X" is hope, and a run is free not to.
|
|
292
|
+
- `doctor` opens with the path of the package copy answering, marked `clone` or `installed package`, and reports whether the host conventions file was found, warning when it exists but is empty. A global install puts a second copy of the package beside any clone, and `update` copies host files from whichever copy launched it — so two diagnoses of the same host were previously indistinguishable.
|
|
293
|
+
|
|
294
|
+
### Fixed
|
|
295
|
+
|
|
296
|
+
- `codex-bridge projects` printed the `last run` column on two clocks. Folder names are written in local time and `meta.finished_at` is an ISO stamp in UTC, and each reached the column through its own branch, so a run whose folder says `144243` was listed as `12:46` — the operator's own zone offset, indistinguishable from a different run. Which run is newest was never affected, only how it printed.
|
|
297
|
+
|
|
298
|
+
## [0.3.0] - 2026-08-07
|
|
299
|
+
|
|
300
|
+
### Added
|
|
301
|
+
|
|
302
|
+
- `codex-bridge sweep [<project>]` closes running records whose runner pid is dead, across the whole store or one project. It changes state but deletes no run folder or transport, never touches a live pid, and lists every stalled-but-live run with the exact `codex-bridge stop <run>` line that ends it. A dead record can therefore be cleared without paying for another run, while a live worker remains the sole writer until `stop` kills it first.
|
|
303
|
+
- Every new run folder carries a `heartbeat` file, and `status.json` carries `stdio_drained`. The heartbeat records movement from Codex output and the still-running child rather than a timer that would keep an orphan alive; `stdio_drained` says whether stdout/stderr closed normally or the bounded drain grace had to end the run.
|
|
304
|
+
|
|
305
|
+
### Changed
|
|
306
|
+
|
|
307
|
+
- Hook liveness now requires `state: running`, a live runner pid and a heartbeat no older than five minutes. A stalled run therefore stops holding the worktree lock instead of holding it until the deadline; the refusal that remains — always about a working run — says how long ago it last made progress and prints `codex-bridge stop <run>` for taking the repository back early. Record cleanup and the second-writing-run check still judge by pid alone, so a stale but live run is released to the operator, not closed underneath its worker.
|
|
308
|
+
- The worker closes a run after `exit` with a bounded 30-second grace for stdio drain instead of waiting for `close`, which a grandchild can hold open forever. Healthy runs keep the event tail that carries their result and record `stdio_drained: true`; only the fallback records `false`.
|
|
309
|
+
- The three dispatcher prompts now open with one shared no-self-execution block rendered through `{{CODEX_NO_SELF_EXECUTION}}`. If `run-codex.mjs` does not start a run, the dispatcher must return `FAIL` and stop, and a reply with no run folder is blocked by the guard. The installed prompts change only when the host runs `codex-bridge update`; a host that does not update keeps the old prompts.
|
|
310
|
+
|
|
311
|
+
### Fixed
|
|
312
|
+
|
|
313
|
+
- A dispatcher that cannot start Codex can no longer read the code, write the files or fix the tests itself and claim a result. The guard also rejects a made-up reply with no `RUN=` or `ATTACH=` behind it: no run, no result.
|
|
314
|
+
|
|
315
|
+
## [0.2.0] - 2026-08-06
|
|
316
|
+
|
|
317
|
+
### Added
|
|
318
|
+
|
|
319
|
+
- `codex-bridge projects` gives the run store a way to look at itself: one line per project — runs, weight, tokens spent, how many are running right now, when the last one started — and one line per run under a project name, plus `--json` for scripts. The store had grown to 12 projects, 152 runs and 80 MB with no command that could answer "what has Codex been working on"; the only way in was a file manager. The count of live runs is computed by the same module the reply guard and the worktree lock use, because a second detector of a live run sitting next to the first would drift from it silently.
|
|
320
|
+
- `codex-bridge prune` reclaims that space, and it is built to be hard to fire by accident: without `-f` it prints a plan and deletes nothing, `-f` still asks before each step, and with no terminal it refuses outright — deletion is an operator action, and the bypass flag that would undo this is deliberately absent. A gentle prune removes transport only (event streams, stderr, the archived `raw.log` of older runs) and leaves accounting, reports and worktree snapshots in place, so a task can still be continued and still be read after its megabytes are gone; `--purge` is what takes a folder whole, and it is refused together with `--all-projects`, because deleting a dozen projects with one command has no second line of defence. A live run is never a target — it is recognised by its process, not by a status file, since the file that would be deleted is the verdict being written right now.
|
|
321
|
+
- Run transport is dropped automatically from runs older than 30 days when a new run starts, and the dispatcher's reply says how much was freed: a rare event that goes unexplained sends someone looking for a fault. Automatic cleanup can only shed weight — the code to remove `meta.json` or a folder does not exist on that path at all, so it cannot be switched on by mistake — and `retention` in `run-config.json` changes the age or turns it off. Both `install` and `doctor` say out loud that it is on, because an installer that quietly starts deleting files is a surprise, not a convenience.
|
|
322
|
+
- A fourth hook refuses `codex-bridge prune` in an agent's shell command before the deleting process exists. Mentioning the command is not calling it: heredoc bodies and quoted text are stripped before the check, after the guard rejected the very commit that introduced it over a command name in the message. `git prune` and `npm prune` are left alone — a guard that breaks unrelated work is a guard that gets removed, and then it protects nothing.
|
|
323
|
+
- `codex-bridge read <run>` renders a run's events as text on demand. Readability is now something the package produces when asked rather than a file it keeps, and a rendering that is not stored cannot disagree with the facts.
|
|
324
|
+
|
|
325
|
+
### Changed
|
|
326
|
+
|
|
327
|
+
- Runs go through `codex exec --json`, and `events.jsonl` is the single source of the quota signal, the token count, the session id and the failure reason. The stream is written by the CLI, not by the model, so a quotation out of a source file can no longer reach it. `tokens` is input plus output with the CLI's whole `usage` object beside it, and `session_id` comes from `thread.started` instead of a line matched in a log.
|
|
328
|
+
- The reason for a `FAIL` is taken from the run's own error event rather than from `stderr.log`. A live probe showed `stderr.log` is not empty even for a clean run — 488 bytes of execpolicy refusals, repository paths included — which made the reason a random blocked call instead of the real one. The transport branch keeps the reason the CLI itself gave with its status code: a `LIMIT` whose reason does not mention the quota is the same class of defect.
|
|
329
|
+
- A run that never began is one with no events *and* no stderr. Stderr with no events is a CLI that did not understand a flag — a different diagnosis, calling for a different action, and the two no longer collapse into one.
|
|
330
|
+
- `log_bytes` in `meta.json` is replaced by `events_bytes` and `stderr_bytes`.
|
|
331
|
+
|
|
332
|
+
### Removed
|
|
333
|
+
|
|
334
|
+
- `raw.log` is gone. Under `--json` it would have been a byte-for-byte copy of `events.jsonl` — a second source of truth with no role of its own — and the package already declared it ephemeral and safe to delete while resting the "abandoned at start" verdict on it. An artifact one is allowed to remove cannot be the ground of a verdict.
|
|
335
|
+
- The text detector of the quota signal is removed entirely rather than kept as a fallback. While the regular expressions live, so does the class of defect they caused.
|
|
336
|
+
|
|
337
|
+
### Fixed
|
|
338
|
+
|
|
339
|
+
- `LIMIT` is set only by an error event from the CLI carrying `status: 429` or an error type naming the limit. A `codex-build` run that had finished its work grepped the package's own test fixtures, printed a line where `ERROR` and `rate limit` stand together, and was closed as quota-exhausted — the work was complete and the suite was green, and the verdict threw it away.
|
|
340
|
+
- A run killed by its time budget says so. It records `stopped_on_deadline` and answers `FAIL — run stopped on its deadline`, instead of inventing a reason out of whatever text was nearest.
|
|
341
|
+
- A log file that cannot be written no longer leaves Codex orphaned. An unhandled stream error used to kill the worker while the CLI kept burning quota with nothing left to close it; now either stream failing takes down the process tree, so the run dies with its process rather than instead of it.
|
|
342
|
+
- A run that exited honestly is no longer marked as killed by its deadline. The timer judged by `close`, which a grandchild process can hold open long after the run is over; it now watches `exit`.
|
|
343
|
+
- A verdict is never shortened to fit the terminal. In a narrow window `running` was printed as `…nning`, which reads as a damaged run rather than one still in flight; a verdict is one word from a known set, like a number or a date, and the run name is what a narrow table gives up instead.
|
|
344
|
+
- The CLI's own warnings are no longer read as the model's complaint about the order. `codex-cli` announces a deprecated configuration key through the same event shape the model uses for a content error, before the turn even opens — so a failed run on such a host would have answered "`[features].codex_hooks` is deprecated" when asked why it failed. Only events after the first `turn.started` are the model's; a complaint about the order cannot predate the model's first thought.
|
|
345
|
+
|
|
346
|
+
## [0.1.4] - 2026-08-05
|
|
347
|
+
|
|
348
|
+
### Added
|
|
349
|
+
|
|
350
|
+
- A continuation has to prove the orchestrator ordered it. `--continue` is refused unless the task text carries a `continue:` grant naming the run being continued and why, and the refusal costs nothing: no run folder is created and Codex is never started. The grant is single-use by construction rather than by a counter — continuing the last run of a chain appends a later one, so the same line stops matching by itself. Until this release a dispatcher could decide on a second pass alone: one did, spent 75 691 tokens of the Codex subscription and created a module the order never asked for.
|
|
351
|
+
- A reply that stays silent about a live `codex-build` run of the same project is blocked. The guard reads the project's runs folder from disk instead of trusting the paths the reply chose to mention, so a second run can no longer be left working in the background while the verdict of the first is handed back. Runs of `codex-scout` and `codex-review` are not counted: they hold a read-only sandbox, and blocking a reply over one would spend the guard's budget on a run that touches nothing.
|
|
352
|
+
- A `PreToolUse` lock refuses file edits inside a repository held by a live `codex-build` run. Knowing that a run is live is not the same as being unable to disturb it — edits made during that window land in the runner's before/after snapshot and fail an honest run for work it never did. An edit made through `Bash` still walks past the lock; parsing a command line is not something a guard can do reliably.
|
|
353
|
+
|
|
354
|
+
### Fixed
|
|
355
|
+
|
|
356
|
+
- `doctor` names the file each hook was registered for. With two hooks on one event it matched the installation record by event alone and reported the worktree lock's matcher as pointing at `order-gate.mjs` — the one line where an operator can check what is installed, showing the wrong file.
|
|
357
|
+
- Hook presence is decided by this package's own command rather than by the matcher it currently sits under. The matcher is generated from the list of host tool names and grows whenever a spelling is added, so a host installed under the previous matcher would collect a duplicate hook on update and keep a hook pointing at a deleted file after uninstall.
|
|
358
|
+
|
|
359
|
+
## [0.1.3] - 2026-08-05
|
|
360
|
+
|
|
361
|
+
### Added
|
|
362
|
+
|
|
363
|
+
- Dispatcher calls are refused before a subagent exists. A `PreToolUse` gate rejects a `codex-*` call whose task text carries no order label — and, for `codex-build`, no scope — or whose value is still a template placeholder. Until this release the missing input was discovered by the runner, after the subagent had been created and paid for out of the Claude subscription.
|
|
364
|
+
- `codex-build` declares the outcome of its own run in a required `outcome` field. A run that could not do the work reports `fail`, and the verdict goes red with the reason even when the worktree is clean and verification is green — the shape that used to answer `OK`, because an empty delta is a legitimate outcome the runner cannot tell apart from a failure. Whether a run owed that declaration is read from the response schema it was handed, so runs recorded before this release keep the verdict of their own day.
|
|
365
|
+
|
|
366
|
+
### Changed
|
|
367
|
+
|
|
368
|
+
- Every dispatcher's description and prompt lists the inputs it requires, filled in at install time from the same table the gate enforces, and the runner's own refusals name the input, an example value and what to do about it. A caller no longer learns the contract by being refused.
|
|
369
|
+
- A failed `codex-build` reports what it left in the worktree, the way a quota-exhausted run already did. "The work was not done" is not "the tree is clean", and where no snapshot exists the line says so instead of claiming there were no changes.
|
|
370
|
+
- The installation record stores a list of hooks rather than a single hook, so a host can register more than one. Records written by earlier versions are read as a one-element list.
|
|
371
|
+
|
|
372
|
+
## [0.1.2] - 2026-08-04
|
|
373
|
+
|
|
374
|
+
### Fixed
|
|
375
|
+
|
|
376
|
+
- A damaged ownership registry no longer breaks the command that reads it. Every command parses the registry before its first write, `doctor` reports the damage as a failed check while still printing the other eight, and `uninstall` finishes removing the package but keeps the shared rules file, because ownership is unknown and disarming another installation is worse than leaving a file behind. Until this release an `uninstall` on a damaged registry stopped after the hook was gone, leaving the host with every package file and no reply guard.
|
|
377
|
+
- Owner updates are written through a temporary file under a lock, so two installers running at once merge instead of overwriting each other. The lock expires: an interrupted run used to leave it behind, and every later install and uninstall then died on it until someone deleted the file by hand.
|
|
378
|
+
- Installation claims its share of the rules file before writing anything. Claiming it last meant a failure at that step left a fully installed host missing from the registry, and the next uninstall elsewhere would delete the rules out from under it.
|
|
379
|
+
|
|
380
|
+
## [0.1.1] - 2026-08-04
|
|
381
|
+
|
|
382
|
+
### Fixed
|
|
383
|
+
|
|
384
|
+
- Two runners starting at the same moment in equally named repositories no longer fail on the exclusive writes that assign a runs directory: the runner that loses either race now reads the marker the winner wrote and takes the next candidate, which is the collision the marker was introduced to survive.
|
|
385
|
+
- A repeated order is answered from its newest run instead of the pass before it: while a continuation was in flight, repeating the command returned the previous run's verdict as if it described the current one.
|
|
386
|
+
- Uninstalling one installation no longer takes the Codex rules file away from every other installation on the machine. The file lives in `CODEX_HOME`, which is shared by every host, while ownership was recorded per host and two installations of the same version share a fingerprint — so removing a project-scope or throwaway host silently left the remaining ones running Codex without the execpolicy that forbids destructive repository work. Ownership is now tracked next to the file itself, and the last owner to leave is the one that removes it.
|
|
387
|
+
|
|
388
|
+
## [0.1.0] - 2026-08-04
|
|
389
|
+
|
|
390
|
+
### Added
|
|
391
|
+
|
|
392
|
+
- Three dispatcher agents for reconnaissance (`codex-scout`), scoped implementation (`codex-build`), and independent review (`codex-review`), each with a structured response contract.
|
|
393
|
+
- A delegating runner that separates the launcher from a detached worker, preserves run artifacts after a dropped call, and supports configurable artifact roots.
|
|
394
|
+
- A zero-dependency `codex-bridge` CLI with `install`, `uninstall`, `update`, and `doctor`, including user/project scopes, dry runs, force handling, idempotent installs, hook merging with backups, and manifest-based ownership tracking.
|
|
395
|
+
- A reply guard hook that blocks dispatcher replies that do not match the recorded run state or required response shape.
|
|
396
|
+
- Run-chain and busy-tree lock protections: repeated work is linked across runs, an unfinished chain requires explicit `--continue`, and concurrent writing runs for one repository are refused before Codex starts.
|
|
397
|
+
- Scope and coverage validation: implementation changes must stay within the declared scope, report/worktree mismatches fail the run, and reconnaissance reports must account for all requested subquestions.
|
|
398
|
+
- Package-managed Codex execution rules that forbid history-, branch-, index-, and worktree-destructive operations, writes inside `.git`, and other unsafe repository mutations while leaving the operator's existing rules untouched.
|
|
399
|
+
- A 400-line source-file size gate with explicit rationale required for exclusions.
|
|
400
|
+
- Asynchronous run start: the launcher reports the run folder and returns instead of holding the caller for the length of the run, and repeating the same order attaches to the run already in flight rather than paying for a second one.
|
|
401
|
+
- Per-mode time budgets that end a run and its whole process tree at a deadline, plus a `stop` subcommand for closing a run that wedged anyway.
|
|
402
|
+
- Explicit reconnaissance subquestions through a mandatory, repeatable `--question` flag, so coverage is counted against what was ordered rather than against prose the dispatcher rewrote.
|
|
403
|
+
- An `answerLanguage` configuration key that fixes the language of a run's answer instead of leaving it to the model.
|
|
404
|
+
|
|
405
|
+
### Changed
|
|
406
|
+
|
|
407
|
+
- Run identity now includes an orchestrator-issued mandatory `--order-id`, stored with run state and used alongside the task identity to detect repeats even when a run is renamed.
|
|
408
|
+
- A repeat of an order is now continued at most once, and only behind a run that already carries a verdict, so a dispatcher can no longer restart itself into a chain of paid runs.
|
|
409
|
+
- A run left behind by a dropped call is now closed with a `FAIL` verdict that names what it left in the worktree, instead of staying open with no account of its work.
|
|
410
|
+
- Runs now snapshot both branch and `HEAD` before and after execution; branch changes, detached `HEAD`, and commit drift are treated as failures, with preflight refusal for a subsequent run when an abandoned run left repository state out of sync.
|
|
411
|
+
- English-language prompts and runner/command output are shipped for the three dispatchers and their supporting commands.
|
|
412
|
+
- Installation updates track installed file contents so outdated package files can be refreshed without overwriting hand edits unless `--force` is requested.
|
|
413
|
+
|
|
414
|
+
### Fixed
|
|
415
|
+
|
|
416
|
+
- Prevented environment and service writes from being misreported as delegated work while keeping them visible in run results.
|
|
417
|
+
- Prevented different repositories with the same directory name from sharing run history.
|
|
418
|
+
- Prevented malformed state files, including files with a byte-order mark, from silently bypassing abandoned-run detection, busy-tree locking, and chain lookup.
|
|
419
|
+
- Fixed diagnostics to report the run folder actually used by the runner and to continue reporting remaining checks when a project marker is unreadable.
|
|
420
|
+
- Fixed reported file paths to keep the spelling on disk instead of the case-folded form used for matching, so a reply names a path that exists on case-sensitive filesystems.
|