Skip to content

refactor: share dispatch/catalog/candidate seams across CLI and policy - #73

Merged
hexuria merged 1 commit into
mainfrom
cleanup/p2-smells
Oct 18, 2026
Merged

hexuria merged 1 commit into
mainfrom
cleanup/p2-smells

Conversation

@hexuria

@hexuria hexuria commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Summary

Post-release smell cleanup (the deferred P2 items from the M2–M8 review). No behavior change, no new dependencies, all opt-in feature boundaries unchanged.

  • OfferedAction::key() — the single KEY:<id>:<key> parser (was key_of duplicated in runner + MCP)
  • KeybindingInfo::catalog_from + AgentClient::keybinding_catalog own the {"keybindings":[…]} envelope parse; the runner still fetches via self.rpc so the M6.4 call budget keeps counting it
  • op_for_decision — one decision→Op table (fingerprint gating included) shared by run --goal and MCP act
  • top_candidates — one abstain-row builder; receipts and the MCP envelope keep their own serialized key names
  • dispatch::{STALE_TARGET, TARGET_GONE, is_stale_dispatch_error} — the two wire prefixes + classifier replace three separate string-prefix matches
  • RunReceipt.outcome_kind (serde(skip)) so the CLI reuses RunOutcome::exit_code instead of re-matching the label string
  • ActionKind::is_control delegates to OperationKind::is_control; Select/ScrollDown/ScrollUp documented as goal-side verb vocabulary (they score and cap but are never offerable — wiring them up is feature work, deferred)
  • HistoryEntry::to_json — the shared {op,id,effect} row for the choose request and jev state.recent_actions
  • resolve_intent — cfg-split doc duplicate collapsed into one fn
  • tests/common::Todo — the headless-todo harness shared by run_goal/run_escalate/run_jev/mcp_instinct (was copied 4x)

Net: −141 lines; the two dispatch tables can no longer drift apart.

Test plan

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets — clean (default, instinct, jev)
  • cargo test --workspace — green in all three configs
  • receipts_are_byte_identical_across_runs and the call-budget tripwire still pass

Generated with Devin

Post-release smell cleanup — no behavior change, no new deps.

- OfferedAction::key() is the one KEY:<id>:<key> parser (was key_of x2)
- KeybindingInfo::catalog_from + AgentClient::keybinding_catalog own
  the {"keybindings":[...]} envelope parse (runner keeps self.rpc so
  the M6.4 call budget still counts it)
- op_for_decision is the single decision→Op table for `run --goal`
  and MCP `act`, fingerprint gating included
- top_candidates builds the shared abstain row; receipts and the MCP
  envelope keep their own key names
- dispatch::is_stale_dispatch_error + STALE_TARGET/TARGET_GONE consts
  replace prefix literals at all three classification sites
- RunReceipt carries outcome_kind so exit codes reuse
  RunOutcome::exit_code instead of re-matching labels
- ActionKind::is_control delegates to OperationKind::is_control;
  OperationKind's Select/ScrollDown/ScrollUp documented as goal-side
  vocabulary (no ActionKind maps to them)
- HistoryEntry::to_json is the shared {op,id,effect} wire row for
  choose + jev state
- resolve_intent collapses its cfg-split duplicate doc blocks
- tests/common::Todo shared by the four CLI integration tests

Verified: fmt clean, clippy -D warnings clean, workspace tests pass in
default/instinct/jev configs.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@hexuria
hexuria merged commit 3add51d into main Oct 18, 2026
5 checks passed
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.

2 participants