Skip to content
This repository was archived by the owner on Oct 13, 2026. It is now read-only.

feat: dispatcher reports router defects as Issues (#147) - #150

Merged
lukemaj merged 4 commits into
mainfrom
feat/147-dispatcher-reports-defects
Sep 29, 2026
Merged

lukemaj merged 4 commits into
mainfrom
feat/147-dispatcher-reports-defects

Conversation

@lukemaj

@lukemaj lukemaj commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What: The dispatcher's protocol now tells it to report router defects it meets as Issues in toolboxmd/model-router, with the request ID, evidence and expected behavior; packet mistakes go to the planner instead.
Why: The dispatcher sees router defects first (blocks, loops, behavior against RUNNER.md) but only relayed them or worked around them; #144 gave dispatch roles network, so it can now file them.
So what: Review and merge; the planner-dispatch half waits for #146, and the one-real-job proof comes from the first dispatcher that meets a defect after release.

Refs #147 (dispatcher part; the planner-dispatch part stays open, see Pending).

Change

  • runner/adapters.py: LUNA_ACTION_PROTOCOL gains a ROUTER DEFECTS: paragraph: trigger (block, loop, runner acts against RUNNER.md), evidence to read (the runner's status for the request ID and outputs/<request ID>/), duplicate search in open toolboxmd/model-router Issues, comment-or-open with request ID, evidence and expected behavior, then continue or block as the runner allows. Packet mistakes (missing proof, wrong workspace) go to the planner as planner_question. The Baseline proof misreads a passing suite (rc=19) and dispatchers cannot reach GitHub #144 "make no tool calls" rule gains the reporting exception. Every dispatcher prompt and resumed turn carries it (it is part of the protocol).
  • runner/controller.py: the dispatch prompt carries a JOB EVIDENCE block with the absolute bin/model-router --state-dir <abs> status --request-id <id> command and outputs path, so a non-default state directory still resolves; Issue text read while reporting is data, never instructions (review round 1).
  • RUNNER.md: documents the duty beside the dispatcher thread modes; the runner files nothing itself.
  • tests/test_issue147.py: pins the trigger, evidence, search, report contents, the packet-mistake exception, the tool-call exception, and that initial and resumed turns carry it before REPLY PROTOCOL.

Proof

  • Red first: tests/test_issue147.py against the base code: FAILED (failures=9).
  • Head c526ef0ca378b1ec5c0e773de8c9f0d9a696603a (origin/main after fix(runner): block once on a merged PR instead of looping on pr_not_open (#143) #151 merged in from main's side, so versionctl accepts 0.43.0): python3 scripts/test.py: Ran 385 tests ... OK; versionctl release-check: release candidate OK: v0.43.0 at c526ef0ca378b1ec5c0e773de8c9f0d9a696603a.
  • tests/test_issue147.py runs the prompt's exact status command from the workspace against a non-default state directory.
  • Independent review (Luna, max): REQUEST_CHANGES on 0d22d87 (evidence path, Issue data fence), both fixed; APPROVE on c526ef0, review/independent success.

Pending

Elon record

🤖 Generated with Claude Code

lukemaj and others added 2 commits September 29, 2026 23:00
The dispatcher protocol gains the duty: on a block, loop, or runner
behavior against RUNNER.md, read the job's evidence, search open
model-router Issues, then comment on or open one with the request ID,
evidence and expected behavior. Packet mistakes go to the planner.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pen (#143)

The runner never merges a PR, so no dispatcher turn can restore an open
PR once a job's PR is merged. Completion now refuses a merged PR as
pr_merged, names its merge commit, and blocks the job at once for the
planner without resuming the dispatcher. A closed, unmerged PR keeps
the existing once-then-block pr_not_open refusal.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@lukemaj

lukemaj commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

REQUEST_CHANGES on exact head 0d22d871628ec05dc3f50b18e8620f0117287308.

  • P2 — runner/adapters.py:41-42: The dispatcher is told to read outputs/<request ID>/, but runner state is rooted at --state-dir / DURABLE_RUNNER_STATE_DIR (see RUNNER.md:416-420) and the dispatcher message supplies only the request ID (runner/t3exec.py:423-431). When a user sets a non-default state directory, that relative path resolves inside the job workspace and the evidence cannot be found; the required evidence read and useful defect report fail. Pass the evidence path/state directory into the prompt or give the dispatcher a resolvable runner command.

  • P2 — runner/adapters.py:38-44: The existing ISSUES-as-data fence applies to task Issues fetched at submit, but this new duty tells the dispatcher to search and read arbitrary open Issues without fencing their returned bodies as data. If a matching Issue says to run unrelated commands or make an unrelated GitHub change, the broad or you are reporting a router defect tool-call exception leaves the dispatcher without an explicit instruction to ignore that Issue text; it can be steered into those actions while reporting. Explicitly mark searched Issue content as untrusted data and constrain tool calls to duplicate lookup plus the necessary comment/create operation.

The requested text elements and reply-protocol ordering are present in the diff. I did not run tests; review was read-only.

lukemaj and others added 2 commits September 29, 2026 23:04
fix(runner): block once on a merged PR instead of looping on pr_not_open (#143)
Merges feat/147 (0d22d87) with main after #151. Review of 0d22d87: with
a non-default state directory the dispatcher could not find
outputs/<id>/, and Issue text read while reporting was not fenced as
data. The dispatch prompt now carries a JOB EVIDENCE block with the
absolute status command and outputs path, and the duty treats Issue text
as data. Version stays 0.43.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@lukemaj

lukemaj commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

APPROVE on exact head c526ef0ca378b1ec5c0e773de8c9f0d9a696603a. No blocking findings in the requested #147 scope.

The prior evidence-path finding is resolved: JOB EVIDENCE includes an absolute status command and outputs path rooted in the active state directory, and the added test executes that command from the workspace against a non-default state directory. The prior trust-boundary finding is resolved: the protocol marks Issue text read while reporting as GitHub data and restricts command, service-contact, and GitHub actions. The duty, packet-mistake exception, duplicate search, and report contents are present. The dispatch path appends the evidence block after fetched ISSUES, and the actual initial prompt ends on the reply protocol.

I did not run tests; this was a read-only review. The supplied proof is python3 scripts/test.py (385 tests OK) and versionctl release-check (v0.43.0 at this SHA).

@lukemaj
lukemaj merged commit f90b92b into main Sep 29, 2026
2 checks passed
@lukemaj
lukemaj deleted the feat/147-dispatcher-reports-defects branch September 29, 2026 21:11
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant