Skip to content

fix(botmux): do not read provider results for unaccepted dispatches - #8684

Open
Duang777 wants to merge 1 commit into
loopx-project:mainfrom
Duang777:codex/botmux-status-unaccepted-dispatch-20261113
Open

Duang777 wants to merge 1 commit into
loopx-project:mainfrom
Duang777:codex/botmux-status-unaccepted-dispatch-20261113

Conversation

@Duang777

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

  • Outcome basis / optional anchor: self-found core defect. No public issue; the request in this PR is the basis.
  • Goal/source and gap: _status_botmux_runtime in loopx/control_plane/goals/botmux_runtime.py asked the provider for the session trigger-result whenever the dispatch had an active key. On a reused session that result describes the previous accepted turn, not a dispatch whose local receipt is attempting or rejected.
  • Observable before → after, with the validation row that proves it: After a second trigger was rejected with 409, status returned completed, ok=True, readback_verified=True, and status --execute raised invalid botmux dispatch transition: rejected->completed. After: rejected, ok=False, readback_verified=False; an attempting receipt is promoted to unknown and persisted. Rows: regression_parity, unit.
  • Issue/task and intended base: none. Base is main at 7bb1b01.

Author Declaration

  • Written by: agent, Claude Sonnet 5.5, for @Duang777

Implemented against

  • Specification and revision: no written specification; the request in this PR is the basis.
  • Criteria:
Criterion (spec clause) Disposition Symbol / path Test or command
Status must not vouch for a dispatch the provider did not accept implemented _status_botmux_runtime tests/control_plane/test_botmux_goal_channel_runtime.py::test_status_never_vouches_for_rejected_dispatch_on_reused_session, ::test_status_promotes_unresolved_attempt_on_reused_session_without_provider_result
  • Self-check before submission: reproduced the defect on the unfixed code, then confirmed the new test fails before and passes after. Did not run the full suite or CI-equivalent gates locally. The botmux tests ran with a stub loopx.cli because the local tree could not import the real one; test_runtime_cli_parses_setup_doctor_trigger_and_status was deselected.

Scope And Continuation

  • Completed scope and remaining work: complete within this scope. After a transport failure an unknown receipt on a reused session has the same ambiguity and unknown->completed is allowed; disambiguating needs a per-turn provider lookup.
  • Slice boundary / successor: N/A, one independent defect.

Validation

  • Tested revision: 6681ca1ad179e20a16bf3599ba9f41a9576e3969 for the diff; local runs used a working tree whose touched files were blob-identical to main 7bb1b01 before the change.
  • Run state: finished
  • Input classes: synthetic
Check kind Result Public-safe evidence / limitation
regression_parity passed Both new tests fail on the unfixed code and pass with the fix.
unit passed test_botmux_goal_channel_runtime.py and tests/test_state_migration.py together: 25 passed, 1 deselected; ruff check clean.
  • Coverage and gaps: Not run against a real botmux backend; the provider is mocked.

Frontend / Visual Evidence

  • UI impact: none

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

  • Direction / acceptance reference, when applicable: Core control-plane hardening.

Shared-authority RFC fixture impact

N/A

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including .loopx/, .codex/goals/, and live ACTIVE_GOAL_STATE.md).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • Existing English/Chinese RFC pairs (including ledger entries) both have a diff, and the local premerge check passes, or no paired RFC changed. No RFC changed.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

🤖 Generated with Claude Code

On a reused botmux session the status read asked the provider for the
session's trigger-result whenever the session held an active dispatch key,
even when that dispatch's local receipt was still `attempting` (crash before
the provider replied) or `rejected`. The session result then describes the
previous, completed turn, so status reported the never-accepted dispatch as
`completed` with `readback_verified: true`, and `--execute` crashed with
"invalid botmux dispatch transition: rejected->completed" (or
attempting->completed), leaving the receipt unresolved forever.

Resolve ATTEMPTING and REJECTED receipts from the local receipt alone, the
same path used when no session exists: attempting is promoted to unknown and
rejected is reported as rejected.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: duang777 <duangjl007@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant