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-2989

(motir-ai) Mirror W9 into `SHARED_PLANNING_RULES` — a defect card's mechanism owes the measurement that rules the alternatives out

Blocked
Description

Repo: motir-ai. One PR. Type: content · Executor: coding_agent. The MIRROR half of MOTIR-2987 (W9) — blocked_by it, because this card LIFTS that card's landed wording rather than re-deriving the rule.

A standing planning RULE has TWO homes (_shared.md: plan-rules/*SHARED_PLANNING_RULES). motir-ai/src/llm/planningRulePacks.ts is "the encoding of plan-rules.md" and is composed by BOTH fresh generation and re-planning (src/jobs/handlers/replan.ts imports it), so a rule that lands only in motir-meta teaches the manual planner and leaves every plan the PRODUCT generates unchanged. And the hosted planner has no motir run guard behind it — a customer's plan gets the prose or it gets nothing.

⚠️ AMENDED 2026-08-18 by the close-out of MOTIR-2998, in the same pass that amended MOTIR-2987. The family gained a FOURTH instance (notes.html #311 / MOTIR-2994) carrying a THIRD tell, so clause 4 below now names three. This card still LIFTS from W9's landed text rather than from this summary — the list here is the completeness check, not the source.

What to land

A new segment constant in planningRulePacks.ts, tagged kind-bug in CORPUS_ORDER, placed adjacent to A_BUG_IS_PARENTED_BY_ITS_FINDING_STORY (the pack's only other member today). Name it for the rule, e.g. A_MECHANISM_OWES_ITS_DISCRIMINATOR.

Lift the wording from MOTIR-2987's landed plan-rules/kind-bug.md text, converted to the corpus's own register (the constants are UPPERCASE-lead, single-paragraph, no markdown tables, no plan-rules/ file paths — the hosted planner has no pack files to open). The clauses that must survive the conversion:

  1. The trigger — a defect card about to state a MECHANISM for an observed failure.
  2. The question"this output is also consistent with …", finished; and which FIELD would tell the readings apart (one more column, one more log line, one more select).
  3. The mandate — when the evidence admits more than one reading, acceptance criterion #1 is the discriminating measurement, and every criterion downstream of it is stated as conditional on its answer.
  4. The three tells — a card that both DEMANDS a measurement and PRESCRIBES the repair has answered its own question; a shape asserted over a SET is N claims and is usually backed by one (the members enumerated by a tool print its VERDICT, not its reason); and — added 2026-08-18, see the amendment note below — a card that RECORDS an earlier reading of its own evidence being wrong and then states the corrected reading in the same declarative voice, where the repair is one clause: say which reading it is, "inferred, unreproduced". All three are properties of the card's own text, so all three are observable by the hosted planner at authoring time and none is narrowed out (notes.html #166 — a rule is only a rule if its reader can observe its input when it fires).
  5. The criteria-not-adjectives clause and the named FALSIFIED exit — a hedge in the prose does not reach the criteria, because a run is measured against the criteria; a card whose every criterion is downstream of an unfalsified mechanism has no legal exit when the mechanism is wrong.

Write it GENERICALLY — the shipped planner plans other people's products, so no MOTIR-<n>, no notes.html number, no motir-core symbol, and no reference to our lock ordering. The ×4 warrant and the fixture table stay in motir-meta; only the standing directive is mirrored (the same split CORPUS-MAINTENANCE.md applies to every decision RECORD).

Acceptance criteria

  1. src/llm/planningRulePacks.ts gains the segment, and CORPUS_ORDER gains its ['kind-bug', <CONST>] row. PLANNING_RULE_PACKS['kind-bug'] therefore contains it — assert that, not just that the constant exists, because the pack TAG is the routing and nothing else conserves it (MOTIR-2973).
  2. grep -c 'DISCRIMINAT' src/llm/planningRulePacks.ts ≥ 1 where it is 0 on origin/main today (measured 2026-08-18).
  3. A phrase assertion in tests/treeGeneration.test.ts pins the rule's load-bearing clause (the first-criterion mandate), in the same form as the existing per-rule assertions — SHARED_PLANNING_RULES has no historical baseline (MOTIR-2967), so a phrase assertion is the only thing that would notice the rule being re-worded away.
  4. The text names no MOTIR key, no notes.html number, and no motir-core symbol — greppable: the new segment contains no MOTIR- and no #30.
  5. ORDERING: criteria 1–4 are checkable on THIS card's own PR diff against motir-ai's origin/main at merge; none reads on post-merge state, and none reads on the motir-meta half, which is MOTIR-2987's PR in a different repo.

Context refs

  • MOTIR-2987 — the motir-meta half; read its landed kind-bug.md text on origin/main, not this card's summary, so the two homes do not drift at birth.
  • MOTIR-2977 — the planning-bug record that produced the pair.
  • motir-ai/src/llm/planningRulePacks.tsCORPUS_ORDER (~line 256), PLANNING_RULE_PACKS (~line 302), A_BUG_IS_PARENTED_BY_ITS_FINDING_STORY (the existing kind-bug member).
  • MOTIR-2914 (Mirror W5) and MOTIR-2963 (Mirror W8) — the two nearest precedents for a mirror card's shape.