mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(agent): verify staged text on a live codex pane and refuse popups
Stage now re-reads the pane after typing (every 50 ms, up to 1 s) and issues a receipt only for a frame with the same generation, the input revision its own write moved, and a composer hash equal to the message's. Codex repaints 30 to 60 ms after the keys, so the first capture was often stale and stage refused with the text already typed. Every refusal after typing now says the message may be in the composer and points at the Ctrl+U recovery. A visible-frame capture reads the screen and the caret in one tmux invocation, with the old two calls as the fallback. Codex draws its suggestion popups above the composer and keeps the footer, so a staged /stat verified and submit ran /status. Stage now refuses a leading / or ! and a last word starting with @ or $ before typing, and stage and submit refuse a frame with popup rows just above the composer. The pattern and characters are registry data (composerPopupLine, composerCommandPrefixes, composerCompletionSigils), read from the codex 0.162.0 bottom_pane sources. Submit waits until 250 ms after the staged keys: codex turns an Enter within 120 ms of a typed burst into a newline. POST .../input answers 409 with its seq returned while a guarded submit holds the input lease, instead of 200 for bytes it never wrote. Also align the attribution memo comment with the code (a verified file whose incremental scan fails is not re-walked, since the full walk reads a superset), and list stage as a fromUser source in CLAUDE.md.
This commit is contained in:
1 parent
c78635a3d3
commit
2832a037d6
27 files changed
+849
-74
No files matched your search
@@ -78,15 +78,32 @@ wrapped, remote/container and shell composers are refused. A customized footer o
|
||||
unsupported character-width rendering can also make verification unavailable.
|
||||
Self-targets are refused by the CLI.
|
||||
|
||||
Stage also refuses, before typing, a message that would change what Enter does:
|
||||
one starting with `/` (a Codex slash command; with its command list open, Enter
|
||||
would run the highlighted command instead) or `!` (a shell command), and one whose
|
||||
**last** word starts with `@` (file/mention search) or `$` (skills). Those popups
|
||||
follow the caret, which stage leaves at the end, so `look at @src/app.ts please`
|
||||
is fine. Send slash and shell commands with `codeman agent send`, and end a
|
||||
message with an ordinary word when it mentions a file. A frame showing a
|
||||
suggestion popup above the composer is refused at stage and submit too.
|
||||
|
||||
The receipt stores a hash and ephemeral identities, never prompt content. It
|
||||
expires after two minutes; capacity is 1024 live receipts. Stage delivery can
|
||||
precede the next screen paint: a receipt acknowledges typing, while submit still
|
||||
requires the fully painted exact composer. If typing fails or is ambiguous, stage
|
||||
issues no receipt; inspect the pane before trying again.
|
||||
expires after two minutes; capacity is 1024 live receipts. After typing, stage
|
||||
re-reads the pane (every 50 ms, up to one second, since Codex repaints a little
|
||||
after the keys) and issues a receipt only for a frame that shows exactly the
|
||||
message with the caret after it. Any refusal after the keys went out (typing
|
||||
failed or was ambiguous, the pane or input changed, or no frame verified in time)
|
||||
says the message may already be in the composer: no receipt was issued. Do not
|
||||
stage again on top of it; follow [Recover a stranded draft](#recover-a-stranded-draft) below first.
|
||||
|
||||
While a submit's Enter is in flight (milliseconds), `send` and other input to that
|
||||
session answer `409 CONFLICT` with nothing written; retry the input.
|
||||
|
||||
Submit checks the caller, session, hash, expiry, pane lifecycle, input revision,
|
||||
geometry, exact composer and caret, then sends one conditional Enter at the session's input
|
||||
boundary. Competing Codeman writes are refused during dispatch. Browser/API/key
|
||||
boundary. It first waits until 250 ms have passed since stage typed (Codex turns an
|
||||
Enter that follows typed text within 120 ms into a newline), so submitting right
|
||||
after stage is fine. Competing Codeman writes are refused during dispatch. Browser/API/key
|
||||
input and managed restarts invalidate receipts even when the visible text or pid
|
||||
is restored. Direct tmux edits are outside that input serialization; captures
|
||||
remain evidence at the time observed, rather than terminal isolation.
|
||||
@@ -98,10 +115,10 @@ Enter was delivered; use inspection or a suitable wait signal to observe native
|
||||
acceptance. A `409` or broken connection means inspect first. Do not automatically
|
||||
stage/submit again or send an unguarded Enter to recover.
|
||||
|
||||
## Recover after a refused submit
|
||||
## Recover a stranded draft
|
||||
|
||||
A consumed receipt cannot be reused. First observe whether the prompt was
|
||||
accepted: use transcript evidence/wait signals and a fresh terminal capture
|
||||
A consumed receipt cannot be reused, and a stage refused after typing issued
|
||||
none. First observe whether the prompt is still in the composer or was accepted: use transcript evidence/wait signals and a fresh terminal capture
|
||||
(`GET /api/v1/sessions/:id/terminal?tail=8192`). If the target is working, has
|
||||
accepted the prompt, shows a dialog, or delivery is ambiguous, keep observing;
|
||||
do not clear or resend anything. A transcript prompt row alone is not proof
|
||||
|
||||
@@ -551,8 +551,8 @@ that half is the CLI's behavior, not something this API guarantees.
|
||||
|
||||
- **This is not the composer-clearing tool.** Esc (and Ctrl+U) do **not** clear a
|
||||
typed-but-unsubmitted Claude prompt, verified live. Do not submit an unverified
|
||||
draft merely to clear it. For a refused guarded local Codex submit, use the
|
||||
verified-unsent recovery in [inspection and staging](inspection-and-staging.md#recover-after-a-refused-submit);
|
||||
draft merely to clear it. For a refused guarded local Codex stage or submit, use the
|
||||
verified-unsent recovery in [inspection and staging](inspection-and-staging.md#recover-a-stranded-draft);
|
||||
when the composer is unclear, ask the user to clear it in the terminal.
|
||||
- The interrupted turn already burned its tokens. Interrupting early saves the rest.
|
||||
- `POST /api/sessions/:id/send-key` is a different endpoint and cannot do this: its
|
||||
|
||||
Reference in new issue
Block a user