fix(sling): reject phantom/stale dispatch under --force (gc-dv3psyz)#2
Open
vbtcl wants to merge 1 commit into
Open
Conversation
The control-dispatcher wasted polecat sessions via three failure modes flagged by boson/witness: (1) a dot-stripped child bead ID (bo-x.11 -> bo-x11) dispatched a polecat onto an empty branch for a non-existent bead; (2) a stale snapshot re-dispatched an already-routed bead, putting two polecats on one bead; (3) a resolved/closed bead was re-dispatched. Root cause: sling preflight treated --force as a blanket override that also disabled the bead-existence check and the fresh-state idempotency check. --force is meant to override *policy* (suspended agent, empty pool, cross-rig, assignee idempotency) — not *correctness* (does the bead exist? is it already resolved/queued?). Fix (internal/sling preflight): - Existence is validated for every real bead-ID route, even under --force. A same-rig ID that does not resolve is rejected (no phantom dispatch). A cross-rig bead not visible locally is still allowed under --force (the documented "remote view not yet synced" escape hatch), downgraded to a warning. Inline-text and formula routes are unaffected (they create their own bead). - New dispatchSkipReason guard runs for plain --force bead routes and skips, as an idempotent no-op, a bead that is closed (resolved) or already routed to this exact target and awaiting pickup — the stale snapshot / double-dispatch cases --force must never bypass. Assignee- based idempotency that --force is designed to override is unchanged. Tests: rewrote the two tests that locked in the old phantom-allowing behavior; added closed-skip and already-routed-skip coverage; updated the API + CLI analogs and the --force help text. internal/sling, internal/api, internal/dispatch, internal/sourceworkflow and cmd/gc all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem (gc-dv3psyz)
boson/witness flagged the control-dispatcher wasting polecat sessions via three failure modes:
bo-oi9tk.11lost its dot →bo-oi9tk11, and a polecat was dispatched onto an empty branch for a bead that doesn't exist.bo-oi9tk.11: dag + rictus).Root cause
internal/slingpreflight treated--forceas a blanket override that also disabled the bead-existence check and the fresh-state idempotency check.--forceis meant to override policy (suspended agent, empty pool, cross-rig, assignee idempotency) — not correctness (does the bead exist? is it already resolved/queued?).Fix
--force. A same-rig ID that doesn't resolve is rejected (no phantom dispatch). A cross-rig bead not visible locally is still allowed under--force(the documented "remote view not yet synced" escape hatch), downgraded to a warning. Inline-text and formula routes are unaffected — they create their own bead.dispatchSkipReasonguard runs for plain--forcebead routes and skips — as an idempotent no-op — a bead that is closed (resolved) or already routed to this exact target and awaiting pickup (the stale-snapshot / double-dispatch cases). The assignee-based idempotency that--forceis designed to override is unchanged.Acceptance criteria mapping
shouldValidateExistingBeadruns under--forcedispatchSkipReasonfresh-reads closed / already-queuedTests
Rewrote the two tests that locked in the old phantom-allowing behavior; added closed-skip and already-routed-skip coverage; updated the API + CLI analogs and the
--forcehelp text.go test ./internal/sling/ ./internal/api/ ./internal/dispatch/ ./internal/sourceworkflow/ ./cmd/gc/— all pass.gofmt/go vetclean; fullgo build ./...green.🤖 Generated with Claude Code