Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-4189To Do

Planning bug: the dispatched agent's re-plan door was planned as a CLI shell-out, while every other instruction in the SAME protocol is an MCP tool call

Three cards in a row chose the wrong SURFACE for an agent-facing capability, and no gate could see it, because every one of them was internally consistent. Found in conversation on 2026-09-02 while reviewing MOTIR-4172, which had just been corrected once already for the same underlying reason.

What was planned

MOTIR-4083 makes a dispatched agent compose a six-field SettledRequirement; MOTIR-4172 carries it to the job envelope. The carrier was authored three times, and the first two are the bug:

  1. Six string flags--outcome, --behaviour, … on motir plan.
  2. One --requirement <path|-> JSON option on motir plan, correcting (1) because parsePlanArgs has no flag grammar by design and the fields are multi-paragraph prose.
  3. An optional requirement object on the submit_plan_session MCP tool — the correction this bug records.

(1) and (2) fought the same problem and neither questioned the premise. Getting a structured, multi-paragraph value through argv is awkward — and the awkwardness was read as a design constraint to route around (a file, then a - for stdin) rather than as evidence that the door was wrong.

The fact that settles it, and it was one grep away

lib/dispatch/promptTemplate.ts — the agent's entire contract, server-assembled — instructs five Motir MCP tools: publish_design_result (:274), mark_integrated (:879, :991), link_pull_request (:944, :1117), transition_status (:1121, :1193), create_work_item (:1261). At :1200, and nowhere else, it tells the agent to shell out to a binary — and that line is step 5 of a branch whose step 4 is a transition_status call, four lines above it.

The permission was already granted: submit_plan_session asserts ai:plan (lib/mcp/toolPermissions.ts:235), which CLI_TOKEN_GRANT carries. The sandboxed agent could always have called it. And runSubmitPlanSession (lib/mcp/tools/planSession.ts:257) is planChangeSessionsService.submit(…) — hop 6 of the seven-hop chain 4172 was written around, so five of those hops existed only to serve the wrong door.

Why nothing caught it

  • The premise was inherited, not decided. docs/decisions/run-findings-protocol.md names motir plan --detach <KEY> twice (:126, :182) and never argues for it — it argues, at length and correctly, that approval must NOT be an MCP tool (Q2: "MCP is the AGENT's surface"). The one sentence in the corpus about this boundary is about the case that goes the other way, so a reader checking the ADR finds the split named and confirmed, pointing away from the question.
  • ONE SUBTASK = ONE REPO passes. Both doors are motir-core, so the repo gate is silent.
  • Precondition verification passes. Every symbol the CLI-door card named exists; the chain was traced hop by hop on origin/main and every hop was real. The card was wrong about which chain it should be tracing, and tracing a chain correctly cannot detect that.
  • The self-correction reinforced it. Correction (2) reads as diligence — it quotes parsePlanArgs's own header, gives three reasons, and pins the fix. A card that has already visibly corrected itself once is the card nobody re-opens.

The RULE this is a case of

A capability whose ACTOR is a dispatched agent belongs on the agent's surface. If the instruction lands in promptTemplate.ts, the door is an MCP tool — not a CLI command the agent is told to shell out to.

The CLI is a client for a person or their CI; a dispatched agent is an MCP client that happens to have a shell. The tell is mechanical and needs no judgement: read the branch of the prompt the new capability lands in and count the tool calls against the shell-outs. A lone shell-out among tool calls is an actor mismatch, and the awkwardness of the argument surface — a value that will not fit through argv, a temp file invented to carry it, a - for stdin — is the SYMPTOM, not the design problem.

And the corollary that would have caught it two corrections earlier: when a card is being corrected for the SECOND time on the same axis, the axis itself is the thing to question. Both wrong answers were about how to get a struct through a command line; neither asked whether it should be going through one.

Acceptance criteria

  • The rule above is written into the planning corpus — both homes: a prompts/plan-rules/ pack and SHARED_PLANNING_RULES in motir-ai, or an explicit note on this card saying which home it is narrowed to and why.
  • The rule is stated as a mechanical check on promptTemplate.ts (count tool calls against shell-outs in the branch the capability lands in), not as a principle a reader has to apply.
  • The second-correction corollary is recorded with it, since it is what makes the rule fire earlier than the surface audit does.
  • The cards this bug corrects — MOTIR-4172, MOTIR-4083, MOTIR-4085 — are already re-authored; this card owns only the RULE.

Advisory dispositions (validate_work_item, 2026-09-02)

valid: true, no blockers. Three likely-missing-edge advisories, all from the same acceptance criterion, and none is an edge this card owes:

  • MOTIR-4172 · MOTIR-4083 · MOTIR-4085 (all todo) — the criterion names them to say the corrections have already been made (their bodies were re-authored on 2026-09-02, in the same pass that filed this card); it does not wait on them. The severity is right — an AC naming a not-done card is a missing edge until proven otherwise — and this is the proof: what this card consumes from those three is their re-authored TEXT, which exists now; their remaining todo is about building the code, which this card never reads. Wiring blocked_by would also be cross-parent three times over (this card sits under MOTIR-1465, they sit under MOTIR-3942), satisfying gate 4 by breaking gate 7.
  • The reverse edge is the one that would be wrong. This card's deliverable is a RULE in the planning corpus; making three code cards wait on a corpus edit would gate shipped work on a lesson, which is the inversion MOTIR-1465 exists to avoid.