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.
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:
select).notes.html #166 — a rule is only a rule if its reader can observe its input when it fires).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).
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).grep -c 'DISCRIMINAT' src/llm/planningRulePacks.ts ≥ 1 where it is 0 on origin/main today (measured 2026-08-18).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.notes.html number, and no motir-core symbol — greppable: the new segment contains no MOTIR- and no #30.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.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-ai/src/llm/planningRulePacks.ts — CORPUS_ORDER (~line 256), PLANNING_RULE_PACKS (~line 302), A_BUG_IS_PARENTED_BY_ITS_FINDING_STORY (the existing kind-bug member).