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

`replan` is `plan` — retire the operation axis from rule selection, because a fresh plan already carries the reconcile TOOLS without the reconcile RULES

Done
Description

Third in the sequence after MOTIR-3853 and MOTIR-3866. The operation axis (plan | replan) is not a rules axis — it is a CONTEXT axis, and it is already carried as context.

The finding

resolvePlanningRulePacks adds the op-replan pack (15,383 chars — RECONCILE_EXISTING_NOT_DONE_WORK) only when operation === 'replan'. But reconciliation is not replan-only:

  • treeGeneration.ts:2151const reconcileAllowed = input.reconcileAllowed !== false; The reconcile tools (modify_node, remove_node) are ON BY DEFAULT and are withheld only by augment, whose prompt forbids reconciling outright.
  • So a fresh plan pass holds the reconcile tools and does not hold the rules that govern them. A rule that stops firing where its situation occurs is the one failure the pack invariants exist to prevent, and here it is inverted: the capability ships without its discipline.

Meanwhile the thing that genuinely distinguishes a re-plan is already carried elsewhere and NOT as rules: replan.ts:319 and revisePlan.ts:243 both pass situationPrompt: REPLAN_SITUATION_PROMPT / REVISE_SITUATION_PROMPT. The re-plan REASON is context, exactly where it belongs.

The axis also doubles the cell space for nothing: legalPlanningRuleCells() returns 104 cells, of which half differ from their twin only by this overlay.

Acceptance criteria

  • The operation axis is removed from rule selection: PlanningRuleSelector no longer carries it, resolvePlanningRulePacks no longer branches on it, and legalPlanningRuleCells() returns the halved, de-duplicated cell space.
  • RECONCILE_EXISTING_NOT_DONE_WORK moves to a pack every cell loads, so the reconcile rules reach every pass that holds the reconcile tools. The op-replan pack is retired rather than left declared and unreachable.
  • composeSkeletonRules, deepenSelectorFor and the rulePackOperation generation input drop the parameter; no caller passes a now-ignored argument.
  • A guard asserts a plan cell and its former replan twin compose IDENTICALLY — the claim this card makes, stated as a test rather than as a comment.
  • A guard asserts the reconcile rules are present in every cell that can receive the reconcile tools.
  • Routing, conservation and register baselines refreshed in the same commit, each diff reviewed; the cautionary count does not rise.

Context refs

  • motir-ai src/llm/planningRulePacks.tsPlanningRuleOperation, resolvePlanningRulePacks, legalPlanningRuleCells, composeSkeletonRules.
  • motir-ai src/llm/treeGeneration.ts:2151reconcileAllowed defaulting true; :2132 rulePackOperation; :2080 deepenSelectorFor.
  • motir-ai src/jobs/handlers/replan.ts:319, src/jobs/handlers/revisePlan.ts:243 — the situation prompts that already carry the re-plan reason.
  • MOTIR-3866 / motir-ai#329 — the pack structure this simplifies.

⚠️ This RAISES the floor for cells that never reconcile. Every cell gains ~15 KB. That is the cost of the rules matching the tools, and it is the correct direction: the alternative is a pass that can modify existing work with no rule telling it how. If a narrower gate is wanted later it keys on reconcileAllowed, which is a runtime flag the selector does not currently see — never on operation.