MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-2099

(motir-ai) MIRROR the design-allocation-emits-consumer-edges corollary into `SHARED_PLANNING_RULES` — the shipped planner must wire the edges a shared design implies

Done
Description

Repo: motir-ai. One PR. The SHIPPED half of a rule that currently lives only in the manual planner.

Why this card exists

A standing planning RULE has two homes, and landing only one teaches the manual planner while the product keeps planning the old way:

  1. motir-meta/prompts/plan-rules.md — the MANUAL planner.
  2. SHARED_PLANNING_RULES in src/llm/treeGeneration.ts — the SHIPPED planner. Its own comment calls it "the encoding of plan-rules.md", and it is composed by both fresh tree generation and re-planning (src/jobs/handlers/replan.ts imports it).

Precedent, twice: MOTIR-1773MOTIR-1774, and MOTIR-2083MOTIR-2089 (merged today, PR #186 — the template for this card).

⚠️ PRECONDITION — the source wording is on an UNMERGED motir-meta PR

The corollary this mirrors ships in motir-meta PR #100 (docs/design-allocation-emits-consumer-edges), which is not yet merged. There is no work item to wire a blocked_by to — the motir-meta half was authored as guard #4's mandated corpus record during motir run MOTIR-2080, not as its own card. Before running this card, confirm PR #100 is merged and lift the wording from prompts/plan-rules.md on origin/main — if it is still open, the source text may still change. Do not transcribe from this description; it is a summary, not the source.

The rule to mirror

It is a corollary to the existing UI-composition rule already in SHARED_PLANNING_RULES (the host surface a UI card renders inside is a blocked_by, not a relates_to) — mirror it as such, adjacent to that rule, not as a free-standing block:

A design that allocates ONE surface across N consuming cards emits N−1 edges BETWEEN those consumers, and the design's own blocks fan-out is not them. Wiring design blocks A + design blocks B asserts only that both need the drawing; the graph then reads A and B as parallel and releases both the moment the design merges, while the design's own allocation table says one renders INSIDE the other's output. So read a design's allocation as a source of EDGES, not just of scope: for each row, name the element and the card that builds it, and wherever one row's element renders inside, beneath, or gated by another row's, wire a blocked_by between those two consumers — in the SAME pass that creates them.

Two operative tells that must survive condensation:

  • The host is not only a page. In the commonest form the host is a branch or a state of a component that ALREADY SHIPS, so nothing looks absent and the existing rule's noun list ("the page / panel / canvas it renders inside") under-covers it. The question is not "does the page exist?" but "does the exact state my element lives in exist, and who builds it?"
  • Cite a sibling by its id, never by description. A prose pointer ("see the sibling bug on …") is invisible to the graph AND to the prose-vs-graph advisory, which keys on MOTIR-<n> — so an unlinked prose reference yields no blocker and no advisory, and validation returns a clean valid: true.

Acceptance criteria

  • SHARED_PLANNING_RULES carries the corollary in the constant's existing voice and placement convention — adjacent to the UI-composition / host-surface rule it extends, not appended as a foreign block.
  • Both operative tells survive the condensation: the host-is-a-STATE-of-a-shipped-surface test, and cite-a-sibling-by-id-never-by-prose.
  • The wording is generic — no project, repo, file path, or MOTIR-<n> key in the rule text (the same constraint MOTIR-2089 tested for).
  • The wording is checked against the motir-meta original on origin/main so the two homes do not drift; the PR body notes which lines correspond.
  • A vitest asserts the rule is present in the composed prompt for fresh generation AND re-planreplan.ts imports the same constant, and a rule that reaches only one path is half-landed.
  • Any frozen-contract / doc guard covering this file is updated in the same PR — verify whether this constant is covered before assuming either way.
  • 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.

Scope boundary

This card mirrors the RULE only. It does not touch src/seed/lessons.base.ts: that corpus is the LESSON tier and is batch-seeded, currently citing up to notes.html #158 against a corpus at #213 — bringing it current is its own card, not this one.

Context refs

  • src/llm/treeGeneration.tsSHARED_PLANNING_RULES, the constant edited.
  • src/jobs/handlers/replan.ts — the second consumer; the reason the test must cover both paths.
  • tests/treeGeneration.test.ts — the existing rule-presence tests to extend (MOTIR-2089 added 11 there).
  • motir-meta PR #100 → prompts/plan-rules.md (the corollary) and notes.html #213 (the incident it was drawn from).
  • MOTIR-2080 — the run that surfaced it; MOTIR-2081 the sibling it should have been wired to.
  • motir-meta/prompts/_shared.md — the plan-rules.mdSHARED_PLANNING_RULES pairing this card honours.