Skip to content

Commit 9bcda78

Browse files
authored
Merge pull request #386 from compoundingtech/agent/codex-protocol-admission
Fix Codex app-server ownership and protocol admission
2 parents 67b18b7 + 5bec5a4 commit 9bcda78

4 files changed

Lines changed: 1617 additions & 321 deletions

File tree

docs/vrs/05-harness-state/requirements.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ authorizes or changes delivery.
117117
nothing there awaits a human (matching the projection's
118118
`Held { Review }``active` / `blockedOn: none` row) — while
119119
`WaitingOnApproval` and `WaitingOnUserInput` report `active` with
120-
`blockedOn: human`. `Compaction` reports `active`, and
120+
`blockedOn: human`. `Compaction` and `UnknownProtocol` report `active`, and
121121
`NotLoaded`/`SystemError`/`AwaitingStatus` withhold rather than write.
122122
`Held` — a delivery predicate — never appears in the published vocabulary.
123123
- **OHS-R06 Heartbeat only on evidence:** A writer re-stamps the record on the
@@ -195,8 +195,9 @@ The measurements are #268's, taken 2026-08-16/17 on one host and carried with
195195
their original caveats: 1298 presence files all legacy one-line records, 4
196196
transitions per turn 0.1–0.4 ms apart, Claude hook timelines (blocked entry in
197197
2 of 9 captures, exit in 1), silent Claude death under SIGTERM/SIGKILL, and
198-
the Codex `activeFlags` schema present on all supported codex-cli versions
199-
(#268's first comment). The shipped code evidence is in-repo: the Codex state
198+
the Codex `activeFlags` schema present in the measured codex-cli versions
199+
(#268's first comment). The startup gate now checks that generated schema
200+
directly. The shipped code evidence is in-repo: the Codex state
200201
machine and its hold reasons, the unfiltered agent-dir watch beside the
201202
presence refresh that writes into it, and `src/harness_state.rs`, which
202203
implements the envelope this file ratifies.

docs/vrs/05-harness-state/spec.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,21 @@ comes first. The cross-check is a narrowing of the ungraceful-death window
183183
(provably dead sessions: pidfile present, process gone), not its closure —
184184
OHS-T04/OHS-R07 say exactly this, and no death tombstone is attempted: the
185185
kill that removes the registry entry leaves nothing behind to prove death
186-
with, and fabricating evidence is the one thing this design never does. A Codex
187-
binary whose delivery-critical schema projection does not match an admitted
188-
fingerprint produces no Codex observed state at all: provider launch is refused
189-
before the control channel starts. Fingerprint admission and live behavioral
190-
evidence remain separate.
186+
with, and fabricating evidence is the one thing this design never does.
187+
188+
Each controlled Codex startup generates the installed app-server schema. st2
189+
checks the required methods, response fields, blocking flags, and data shapes
190+
that native delivery uses. A compatible patch or minor release starts without
191+
a source change. A missing required element or a changed critical shape stops
192+
before the app-server starts. The wrapper sends one idempotent rejection report
193+
to the agent's declared supervisor. The version string is diagnostic data, not
194+
an admission proxy.
195+
196+
Additive item kinds and server-request methods do not stop startup. A listed
197+
element is reviewed and safe to ignore. An unlisted element creates an
198+
`UnknownProtocol` delivery hold. The next safe thread status releases the hold.
199+
This fail-closed runtime rule keeps the agent present and prevents a silent
200+
delivery into a new hold that st2 does not understand.
191201

192202
## Codex producer (OHS-R05)
193203

@@ -205,6 +215,7 @@ complement of steerable, a delivery predicate (decision 0001's boundary).
205215
| `Held { ConflictingTurn }` | `active` | `none` | `none` | `conflictingTurn` — two turns believed live is maximally active |
206216
| `Held { Review }` | `active` | `none` | `none` | `review` — review's enter and exit are model-emitted items inside a running turn; nothing awaits a human |
207217
| `Held { Compaction }` | `active` | `none` | `none` | `compaction` |
218+
| `Held { UnknownProtocol }` | `active` | `none` | `none` | `unknownProtocol` — an additive protocol element blocks delivery until a safe thread status arrives |
208219
| `Held { WaitingOnApproval }` | `active` | `human` | `permission` | `waitingOnApproval` |
209220
| `Held { WaitingOnUserInput }` | `active` | `human` | `question` | `waitingOnUserInput` |
210221
| `Held { NotLoaded }` | *withhold* ||| thread not loaded proves nothing about work |

docs/vrs/spec.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,9 +1065,9 @@ policy, compat field, or API version constant — but it does publish its
10651065
TypeScript declarations, and those govern this coupling.
10661066
`checks.pi-extension-types` type-checks the shipped extension against a pinned
10671067
pi release at build time, which is what makes the asset's otherwise-erased
1068-
`import type` load-bearing. This follows the repo's existing rule that st2 pins
1069-
where skew fails silently (`pty`, `codex-cli`) and not where it fails loudly
1070-
(`claude`); the extension's one silent surface was its idle proof, and using
1068+
`import type` load-bearing. This follows the repo's existing rule that st2 validates
1069+
where skew fails silently (`pty`, the Codex app-server schema) and not where it fails
1070+
loudly (`claude`); the extension's one silent surface was its idle proof, and using
10711071
that proof without calling it is now a build error.
10721072

10731073
A pi agent never enters the DING path. `deliver` and `ding` are mutually

0 commit comments

Comments
 (0)