(motir-ai) MIRROR the two new planning rules into `SHARED_PLANNING_RULES` — the shipped planner learns them too, not just the manual one
Repo: motir-ai. One PR. The SHIPPED half of MOTIR-2083 — lift its two rules into the planner the product actually runs.
Why this card exists
A standing planning RULE has two homes, and a card naming only one is under-scoped:
motir-meta/prompts/plan-rules.md— the MANUAL planner.SHARED_PLANNING_RULESinsrc/llm/treeGeneration.ts— the SHIPPED planner. Its own comment calls it "the encoding ofplan-rules.md", and it is composed by both fresh tree generation and re-planning (src/jobs/handlers/replan.tsimports it). A rule missing there is missing from every plan the product generates.
Landing MOTIR-2083 alone would teach the manual planner while the product keeps planning the old way — the opposite of dogfooding. Precedent: MOTIR-1773 → MOTIR-1774, the same split for the Story-level journey audit.
The two rules to mirror
Lift the wording from MOTIR-2083 — it is written to be liftable without re-deriving intent. Condense for prompt budget, but do not drop either rule's operative TELL:
- An acceptance criterion must be satisfiable inside the card's own scope boundary. The tell: a criterion phrased as a WORLD-STATE ("the live project now shows Y") rather than an OUTPUT ("this code does Z") silently annexes whoever else has to act. When a card declares "this does not do X", every criterion on the far side of X needs an actor named — if that actor is a human or another card, the criterion belongs to that card.
- A bug found while working a story is parented BY that story,
blocked_by-wired to the card it holds up, in that story's sprint — regardless of where the defect conceptually lives or which story owns the surface. If the fix needs a design first, that design card goes in the same story too. The trap: letting the design's location choose the bug's parent.
Acceptance criteria
SHARED_PLANNING_RULEScarries both rules, in the constant's existing voice and numbering convention — not appended as a foreign block.- Both operative tells survive the condensation: the world-state-vs-output test, and design-location-never-chooses-the-parent.
- The wording is checked against the motir-meta original so the two homes do not drift; note in the PR body which lines correspond.
- The frozen-contract / doc guards that trip on edits to this file are updated in the same PR if they cover it (see [[motir-ai-jobkind-contract-drift-guard]] for the shape — verify whether this constant is covered before assuming either way).
- A vitest asserts both rules are present in the composed prompt for fresh generation AND re-plan —
replan.tsimports the same constant, and a rule that reaches only one path is half-landed. - PR title carries
MOTIR-<id>(motir-ai is a code repo — the status-sync rule).
⚠️ Working in treeGeneration.ts
grep silently finds nothing in this file — it has very long lines. Search with python or node instead, or you will conclude the constant does not exist. See [[motir-ai-grep-long-lines-gotcha]].
Context refs
src/llm/treeGeneration.ts—SHARED_PLANNING_RULES, the constant edited.src/jobs/handlers/replan.ts— the second consumer; the reason the test must cover both paths.- MOTIR-2083 — the motir-meta half, and the source wording.
motir-meta/prompts/_shared.md— theplan-rules.md⟷SHARED_PLANNING_RULESpairing this card honours.