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
144
planned
1,365
shipped

Motir · Roadmap

MOTIR-3934Done

`update_plan_proposal` does not resolve a `MOTIR-<n>` key in `patch.blockedByAdd/Remove` — it stores the raw string, and the dangling ref surfaces at APPROVE, which is the failure the correction door's own gate promised to prevent

Opened by Zhu Yue ·

⚠️ THIS CARD'S FIRST DIAGNOSIS WAS WRONG AND IS CORRECTED HERE. It was filed 2026-08-29 as "the plan PROJECTION ignores patch.blockedByRemove". That is false. The projection applies the removal correctly the moment the ref is resolvable; it could not match a raw "MOTIR-3884" string against a committed edge, and reported the edge as surviving — which was the honest answer to a dangling ref. The defect is one layer earlier, on the WRITE side. The wrong first reading is kept here because it is the reading the symptom invites, and the next person will reach for it too.

The defect

update_plan_proposal accepts a MOTIR-<n> key in patch.blockedByAdd / patch.blockedByRemove, stores it verbatim, and neither resolves nor refuses it. add_plan_items resolves the same input to a work-item id.

Measured 2026-08-29 on plan cmtetu5630015hwph1qdl39zv, four modify proposals in one plan, three appended and one corrected:

proposaldoorinputstored
MOTIR-3880add_plan_items["MOTIR-3879"]["cmteaay7i0045hwphi8hqc2yy"] ✅ resolved
MOTIR-3884add_plan_items["MOTIR-3881"]["cmteaay9t0047hwphhk88ri6f"] ✅ resolved
MOTIR-3886add_plan_items["MOTIR-3881"]["cmteaay9t0047hwphhk88ri6f"] ✅ resolved
MOTIR-3885update_plan_proposal["MOTIR-3884"]["MOTIR-3884"]raw

Two symptoms, one cause. validate_work_item(…, planId) reported valid: false naming an edge the plan removes; and approve refused outright:

INVALID_PLAN_REF_GRAPH · reason: dangling
Proposal …'s patch.blockedByRemove "MOTIR-3884" names no work item in this workspace.

Re-issuing the identical correction with ["cmteaayd0004ahwphr7rhtxe7"] — the same card, as an id — stored it resolved and flipped the projection to valid: true. So the projection and the approve check are both correct; the stored value was garbage.

Why this escaped the gate that was built for it

MOTIR-3533's story is "…and an unresolvable ref refused at append", and MOTIR-3542 is the vitest gate over "the append-time ref refusal". Both shipped. The refusal covers planItem: refs, and a MOTIR-<n> key is not one — the correction door says so in its own success message: "Structural fields (patch) were re-validated against this plan's own proposals, so every planItem: ref you sent resolves." An intra-plan ref is checked; a workspace key is passed through untouched.

So the tool's schema advertises three accepted forms — "work-item keys (ACME-7), real work-item ids, or planItem:<id> refs" — and one door honours all three while the other honours two and silently corrupts the third.

Why the failure lands where it hurts

It only fires on a re-plan that moves a card between parents. Most plans add edges and never remove one; the corrupt value is written by the correction door, which is reached when an author has already found a mistake and is fixing it. The error then arrives at APPROVE — in front of the reviewer, on a plan that has been read — which is precisely the moment the append-time refusal exists to move it away from.

And the wrong fix is attractive. The symptom presents as a projection bug (this card's own first diagnosis). "Fixing" the projection to subtract a raw key would make valid: true and leave a dangling ref that still fails at approve — or, worse, would be paired with a lenient approve that drops the removal silently.

Acceptance criteria

  • update_plan_proposal resolves patch.blockedByAdd / patch.blockedByRemove exactly as add_plan_items does — a MOTIR-<n> key, a work-item id and a planItem: ref all end up stored in the same normalised form, asserted by a test that writes the same edge through both doors and compares the stored value.
  • A ref that names nothing is refused at the correction call, with the same typed error add_plan_items raises — not accepted and discovered at approve.
  • The same normalisation and refusal apply to parentRef and blockedByRefs on the correction door; the test covers each field rather than only the one this bug was found on.
  • A regression test approves a plan whose correction used a MOTIR-<n> key — the end-to-end shape this bug is, which a unit test on the resolver alone would pass while approve still failed.
  • A removal naming an edge that does not exist stays a no-op rather than an error, so a defensive sweep is not punished.
  • ≥90% coverage on the files this PR touches.

Context refs

  • motir-coreupdate_plan_proposal / correctProposal, and the ref resolution add_plan_items uses
  • MOTIR-3533 — the story promising an unresolvable ref refused at append
  • MOTIR-3542 — its vitest gate, which covers planItem: refs only
  • MOTIR-3867 — the closest sibling, merged the same day: the projection reading patch.parentRef. Same family, adjacent field
  • motir-core/docs/decisions/agent-authored-plans.md AMENDMENT 8 — the correction doors' contract
  • Plan cmtetu5630015hwph1qdl39zv — the fixture, with three resolved rows and one raw one in the same plan

Discussion

No comments yet.

Adding to this discussion signs you in on app.motir.co and brings you back to this request.

Add a comment