Planning bug MIRROR: (motir-ai) carry the widened deferral surfaces + the placeholder triggers into `SHARED_PLANNING_RULES`
The second home of the rule MOTIR-3175 lands in motir-meta. A standing planning RULE has two homes — the manual planner's packs and SHARED_PLANNING_RULES, the constant the SHIPPED planner is always given — and a rule in one home teaches one planner. This work item carries the wording across. One repo, one PR.
The gap is measured, not assumed
motir-ai/src/llm/planningRulePacks.ts on origin/main @ 21ae185: 159 898 bytes, 523 lines, 33 rule constants. The deferral family is present and healthy — it lives inside DEPENDENCY_GRAPH_IS_THE_BUILD_SEQUENCE, located by bisecting the deferral hits (offsets 22 856–27 267) against the `const NAME = `` declaration offsets, not by guessing from the family's name (the pointer in the corpus for the sweep family is wrong in exactly that way, and a wrong constant in the right file reads as a real absence).
Substring counts over the whole constant, so a zero stands against a populated baseline:
| probe | count |
|---|---|
deferral | 15 |
A DEFERRAL IS A CARD | 1 |
its own card | 5 |
stays for now | 1 |
whoever picks this up | 1 |
design asset | 8 |
code comment | 0 |
placeholder | 1 (and not in this family) |
And the surface list is quoted verbatim from the constant: "read them in a card body, in a decision document's section, and in any boundary / 'what this does NOT change' / 'out of scope' block" — a design asset is not among them, exactly as in core.md. The gap is the same gap in both homes.
What to carry, and what NOT to
- Carry the widened SURFACES (a design asset /
design-notes.md, and a source comment shipped beside the placeholder it describes) into the existing trigger sentence insideDEPENDENCY_GRAPH_IS_THE_BUILD_SEQUENCE— the constant already has the §-level "when the DEFERRING ARTIFACT IS A DOCUMENT" limb, and this is one clause on the same limb, not a new paragraph. - Carry the PLACEHOLDER phrasings into the constant's trigger list, beside "stays for now" / "the route stays" / "unchanged", with the discriminating tell (the sentence describes the CURRENT artifact rather than a future decision).
- Carry the apply-across-the-app inverse-enumeration limb to whichever constant owns gate 8's sweep — locate it by probing for its own tells, not by its family name (the sweep family is split across
RECONCILE_EXISTING_NOT_DONE_WORK/op-replanandVERIFY_EVERY_PRECONDITION/phase-deepen); bisect the hit's offset against the declaration list and put the clause in the constant that actually carries the neighbouring text. - Do NOT carry any of the incident narrative: the mirror holds triggers and imperatives, no warrants, no
MOTIR-keys, no dates, nonotes.htmlcitations — and the guards enforce it. Repo-name genericity istests/planningRulePacks.test.ts§ GENERICITY, per pack; the source-citation ban istests/treeGeneration.test.ts:615(plus the per-rule case at:463, which also bansopen-coreandMOTIR-\d). They are different files — do not cite one for the other. - Keep the mirror's PACKING. If the two homes disagree about which pack a rule sits in, carry the WORDS and leave the placement alone.
Acceptance criteria
- The widened surfaces and the placeholder trigger phrasings are in
DEPENDENCY_GRAPH_IS_THE_BUILD_SEQUENCE, in the constant's own register (imperative, generic, no warrant). - The inverse-enumeration limb is in the constant that carries the neighbouring sweep text, named in the PR body with the offset/bisect evidence that identified it — a card that names a constant it did not locate is the failure this criterion exists to stop.
- No wording names Motir, its repositories, its brand, a work-item key, a date or a source file — the shipped planner plans other people's products. Both guard suites pass unchanged:
tests/planningRulePacks.test.tsandtests/treeGeneration.test.ts. - The composition still resolves:
SHARED_PLANNING_RULES,PLANNING_RULE_PACKS,resolvePlanningRulePacksandlegalPlanningRuleCellsall build, and the pack tags inCORPUS_ORDERare unchanged. - The PR body records the BEFORE size (159 898 bytes / 523 lines / 33 constants @
21ae185) and the after, because the constant is injected into every plan the product generates and its growth is a cost. - Landed on a branch + PR against
motir-ai.
Context refs
motir-ai/src/llm/planningRulePacks.ts— the mirror;DEPENDENCY_GRAPH_IS_THE_BUILD_SEQUENCEis the deferral family's constant.motir-ai/src/llm/treeGeneration.ts— re-exports only; the definition moved. A citation of the old path still resolves, which is how a false absence gets manufactured.motir-ai/tests/planningRulePacks.test.ts·motir-ai/tests/treeGeneration.test.ts— the two guard suites, in that order for genericity and source-citations.- MOTIR-3175 — the motir-meta wording this lifts (
blocked_by); write nothing here that re-derives its intent. - ⚠️
grepfinds nothing intreeGeneration.ts(very long lines) — search it with python/node.