(motir-ai) MIRROR the both-content-axes rule into `SHARED_PLANNING_RULES` — the WHY belongs in `explanationMd`, never as a "## Why this card exists" heading in the description
Repo: motir-ai. One PR. The SHIPPED half of the plan-runbook change landed in motir-meta PR #103 (docs/plan-runbook-explanation-axis) — a standing planning RULE has two homes, and that PR only filled the first.
The rule to mirror
A work item carries two first-class Markdown bodies: descriptionMd ("what to do" — the spec) and explanationMd ("why it matters" — the standing rationale), rendered as two sibling sections on the item detail page. The runbook now makes authoring BOTH a per-card gate (#16 in plan-rules.md, the both content axes rule section).
SHARED_PLANNING_RULES (src/llm/treeGeneration.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 missing there is missing from every plan the product generates. Lift the wording from the motir-meta original — it is written to be lifted without re-deriving intent — condensing for prompt budget but keeping the operative tell.
⚠️ What is ALREADY there — do not duplicate it
EXPLANATION_INSTRUCTION (MOTIR-1468) already tells the planner to draft a per-node explanationMd, and buildGenerationTools makes it a REQUIRED propose_node property — but only when opts.generateExplanations is set; when the flag is OFF that block is absent from the prompt entirely, by design (the prompt stays byte-identical to pre-1468).
So the half that is MISSING — and that belongs in the always-injected SHARED_PLANNING_RULES, not in the flag-gated block — is the description-side prohibition: the descriptionMd is the WHAT/how spec, and the strategic WHY does not go inside it. A ## Why this card exists heading in a description is the tell that the rationale was written into the wrong axis — it leaves the Explanation section reading empty while diluting the spec the executor reads. That prohibition holds whether or not explanations are ON: with the flag OFF the WHY is simply not authored, never smuggled into the description.
Acceptance criteria
SHARED_PLANNING_RULESstates the two-axis split (description = WHAT to do; explanation = WHY it matters) and the description-side prohibition, in the constant's existing voice and numbering — not appended as a foreign block.- The operative tell survives the condensation: a "why this card exists" heading inside a
descriptionMdis the wrong axis. - It does NOT restate
EXPLANATION_INSTRUCTION's drafting directive (that stays flag-gated) — a reader must be able to tell which text is always-on and which is opt-in. - A vitest asserts the new rule text is present in the composed system prompt for fresh generation AND re-plan, and with
generateExplanationsboth ON and OFF —replan.tscomposes the same constant, and a rule reaching only one path is half-landed. - Any frozen-contract / prompt-snapshot guard covering this constant is updated in the same PR (verify whether one exists 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, or you will conclude the constant does not exist.
Context refs
src/llm/treeGeneration.ts—SHARED_PLANNING_RULES(the constant edited),EXPLANATION_INSTRUCTION+buildGenerationSystemPrompt(the flag-gated block to NOT duplicate),buildGenerationTools.src/jobs/handlers/replan.ts— the second consumer; why the test must cover both paths.motir-meta/prompts/plan-rules.md— gate #16 + the both content axes rule; the source wording (PR #103).motir-meta/prompts/_shared.md— theplan-rules.md⟷SHARED_PLANNING_RULESpairing this card honours.