You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TestE2E_ToolCallApprovalRoundTrip intermittently receives the live SSE tool.approval_required event and immediately POSTs /v1/runs/{id}/approve, but the API returns 404 (ErrNoPendingApproval). This occurred under the authoritative full race regression while promoting PR #1059. Repeated isolated runs often pass, which is consistent with a scheduling race rather than a deterministic endpoint failure.
Expected behavior
Publication of tool.approval_required must be a readiness guarantee: once any API, TUI, or native GUI client can observe the event, the approval is already durably/in-memory registered and an immediate approve or deny request cannot return ErrNoPendingApproval. Timeout, cancellation, duplicate resolution, and checkpoint-backed behavior must remain correct.
Reproduction
Preconditions: run a tool call under approval: all with a live SSE consumer and an in-memory approval broker.
Observed command: DEVELOPER_DIR=/Library/Developer/CommandLineTools TMPDIR=/private/tmp GOCACHE=<isolated> ./scripts/test-regression.sh; race stage failed at TestE2E_ToolCallApprovalRoundTrip with POST approve: expected 200, got 404.
Small deterministic red: add a broker seam that blocks before pending registration, deliver the emitted event to a client, and prove the immediate approve currently returns ErrNoPendingApproval/404. Also cover deny and the checkpoint-backed broker.
User and operational impact
The harness can show an actionable approval prompt in API/TUI/native GUI and then reject the user's immediate action. This can strand or time out runs and makes conversation-forward UI approval unreliable. No data corruption is known; retry is timing-dependent and is not an acceptable workaround.
Suspected seam and search evidence
Owning seam: internal/harness/runner_step_engine.go emits EventToolApprovalRequired before calling ApprovalBroker.Ask. Both InMemoryApprovalBroker.Ask in internal/harness/approval_broker.go and checkpointApprovalBroker.Ask in internal/harness/checkpoint_brokers.go register pending state only after Ask begins. HTTP handlers in internal/server/http_runs.go map ErrNoPendingApproval to 404. Searches covered ApprovalBroker, all ApprovalRequest constructors, approval event consumers, checkpoint brokers, HTTP approve/deny handlers, runner approval tests, and the E2E SSE path.
Current hypothesis: event publication races broker registration. The API handler and test are behaving consistently with the current contract; retrying or weakening the assertion would hide the product bug.
Blast-radius impact map
Callers and data flow: runner tool-call approval and plan-exit approval paths; both broker implementations.
Config/env/defaults: none; no configuration change expected.
API/CLI/wire formats/tools: approve/deny endpoints and SSE event readiness semantics; event schema should remain compatible.
Persistence/schema/cache: checkpoint records are affected behaviorally; no schema change expected.
Security/auth/permissions/privacy: approval gates must not execute without approval; authentication behavior is unchanged.
TUI/web/macOS/other clients: all clients that react immediately to tool.approval_required.
Provider/model/tool catalog: ordinary tool approval and plan-exit approval; no provider schema change.
Deployment/observability/runbooks: add regression evidence and engineering-log symptom/cause/fix.
Compatibility: preserve ApprovalBroker behavior for existing brokers or migrate every implementation/caller atomically.
Existing tests/fixtures: approval broker, checkpoint broker, runner approval, plan mode, server handlers, E2E.
Documentation: active plan/impact map/log indexes as required by repository process.
Regression test first
Add deterministic tests proving pending state exists before the approval-required event is externally observable for in-memory and checkpoint-backed brokers, plus an HTTP/SSE regression where immediate approve and immediate deny return 200. The red must fail because the event arrives before the broker registration barrier is released, not because of sleeps or load. Preserve the existing E2E round trip and run it under race.
Fix boundaries
In scope: repair the runner/broker contract so registration happens-before event publication, preserve blocking wait/timeout/cancellation semantics, update every implementation/caller, and add permanent regressions.
Out of scope: UI redesign, retrying 404 in clients, weakening the E2E assertion, unrelated TUI PR #1059 behavior, or changing approval policy semantics.
Repair the existing approval abstraction; do not add a parallel approval mechanism.
Diagnostic and observability evidence
Record the exact red test, event/API ordering, status code, targeted normal/race results, full regression, and a live SSE approve/deny canary. No sensitive data is involved.
Verification plan
Deterministic red for event-before-registration.
Targeted approval broker, checkpoint broker, runner approval, plan mode, server, and E2E tests.
Targeted tests with -race and repetition.
./scripts/test-regression.sh with isolated Go cache and CommandLineTools.
Hosted fast and race workflows on the exact PR head.
Live harnessd SSE flow: observe prompt, approve immediately, conversation completes; repeat for deny.
Merge as an isolated baseline bug PR before dependent UI/TUI promotions. Monitor hosted regression and live approval responses. Roll back the single repair commit if approval registration, cancellation, or timeout regresses; no data migration or repair is expected.
Documentation and handoff
Update the active plan and impact map, docs/logs/engineering-log.md with symptom/cause/fix, relevant observational/system/long-term logs, and folder indexes required by documentation maintenance.
Definition of done
Deterministic reproduction recorded and red before the fix
Pending approval is registered before the event is observable
Immediate approve and deny work for in-memory and checkpoint-backed paths
Timeout, cancellation, duplicate resolution, plan-exit, and security semantics remain green
Targeted normal/race/repetition and full regression pass
Hosted exact-head fast/race checks pass
Live harness/API SSE conversation proof passes
Engineering log, plan, impact map, indexes, rollout, and rollback are current
Process acknowledgement
I will preserve the failing regression test, update the issue if the root cause changes, and record any newly discovered bug as its own issue.
Work type
Bug / regression
Observed behavior
TestE2E_ToolCallApprovalRoundTripintermittently receives the live SSEtool.approval_requiredevent and immediately POSTs/v1/runs/{id}/approve, but the API returns 404 (ErrNoPendingApproval). This occurred under the authoritative full race regression while promoting PR #1059. Repeated isolated runs often pass, which is consistent with a scheduling race rather than a deterministic endpoint failure.Expected behavior
Publication of
tool.approval_requiredmust be a readiness guarantee: once any API, TUI, or native GUI client can observe the event, the approval is already durably/in-memory registered and an immediate approve or deny request cannot returnErrNoPendingApproval. Timeout, cancellation, duplicate resolution, and checkpoint-backed behavior must remain correct.Reproduction
Preconditions: run a tool call under
approval: allwith a live SSE consumer and an in-memory approval broker.Observed command:
DEVELOPER_DIR=/Library/Developer/CommandLineTools TMPDIR=/private/tmp GOCACHE=<isolated> ./scripts/test-regression.sh; race stage failed atTestE2E_ToolCallApprovalRoundTripwithPOST approve: expected 200, got 404.Small deterministic red: add a broker seam that blocks before pending registration, deliver the emitted event to a client, and prove the immediate approve currently returns
ErrNoPendingApproval/404. Also cover deny and the checkpoint-backed broker.User and operational impact
The harness can show an actionable approval prompt in API/TUI/native GUI and then reject the user's immediate action. This can strand or time out runs and makes conversation-forward UI approval unreliable. No data corruption is known; retry is timing-dependent and is not an acceptable workaround.
Suspected seam and search evidence
Owning seam:
internal/harness/runner_step_engine.goemitsEventToolApprovalRequiredbefore callingApprovalBroker.Ask. BothInMemoryApprovalBroker.Askininternal/harness/approval_broker.goandcheckpointApprovalBroker.Askininternal/harness/checkpoint_brokers.goregister pending state only afterAskbegins. HTTP handlers ininternal/server/http_runs.gomapErrNoPendingApprovalto 404. Searches coveredApprovalBroker, allApprovalRequestconstructors, approval event consumers, checkpoint brokers, HTTP approve/deny handlers, runner approval tests, and the E2E SSE path.Current hypothesis: event publication races broker registration. The API handler and test are behaving consistently with the current contract; retrying or weakening the assertion would hide the product bug.
Blast-radius impact map
tool.approval_required.ApprovalBrokerbehavior for existing brokers or migrate every implementation/caller atomically.Regression test first
Add deterministic tests proving pending state exists before the approval-required event is externally observable for in-memory and checkpoint-backed brokers, plus an HTTP/SSE regression where immediate approve and immediate deny return 200. The red must fail because the event arrives before the broker registration barrier is released, not because of sleeps or load. Preserve the existing E2E round trip and run it under race.
Fix boundaries
In scope: repair the runner/broker contract so registration happens-before event publication, preserve blocking wait/timeout/cancellation semantics, update every implementation/caller, and add permanent regressions.
Out of scope: UI redesign, retrying 404 in clients, weakening the E2E assertion, unrelated TUI PR #1059 behavior, or changing approval policy semantics.
Repair the existing approval abstraction; do not add a parallel approval mechanism.
Diagnostic and observability evidence
Record the exact red test, event/API ordering, status code, targeted normal/race results, full regression, and a live SSE approve/deny canary. No sensitive data is involved.
Verification plan
-raceand repetition../scripts/test-regression.shwith isolated Go cache and CommandLineTools.Rollout and rollback
Merge as an isolated baseline bug PR before dependent UI/TUI promotions. Monitor hosted regression and live approval responses. Roll back the single repair commit if approval registration, cancellation, or timeout regresses; no data migration or repair is expected.
Documentation and handoff
Update the active plan and impact map,
docs/logs/engineering-log.mdwith symptom/cause/fix, relevant observational/system/long-term logs, and folder indexes required by documentation maintenance.Definition of done
Process acknowledgement
I will preserve the failing regression test, update the issue if the root cause changes, and record any newly discovered bug as its own issue.