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
Back to roadmap
Implemented

The planning rule packs, re-cut on a phase → kind | type selector — and `type` becomes an output of SKELETON

Storyopened by Zhu YueMOTIR-3891

A total re-cut of the planning rule corpus and its selector. Three incremental cards (MOTIR-3853, MOTIR-3866, MOTIR-3869) improved the existing shape and, between them, established that the shape itself is wrong. This story replaces it.

The model, as decided

  1. type is an output of skeleton, not deepen. Today propose_node carries no type and deepen_node sets it, so on a fresh plan the selector reads a field the skeleton never wrote — the type axis selects nothing that a plan pass can act on.
  2. Rule packs are selected by PHASE firstskeleton or deepen.
  3. At skeleton, packs are selected by KIND. Nothing else.
  4. At deepen, packs are selected by kind OR type — never a cross-product of the two.
    • deepen epic / story / bugno type; select by KIND.
    • deepen task / subtask ⇒ the type is set; select by TYPE.

Point 4 moves bug out of the typed set for rule-selection purposes. It is in TYPED_KINDS today alongside task and subtask.

Why the current shape cannot be patched further

  • The cell space is a cross-product it should never have been. legalPlanningRuleCells() enumerates kind × type at deepen; under the model above a deepen cell is either a kind cell or a type cell, so the space is a sum, not a product.
  • A pack per type cannot express what a type needs. VERIFY_EVERY_PRECONDITION reaches every deepen cell and tells a translate card to run pg_policies, pg_roles, information_schema and row_security_active(). Subject mentions across that one constant: HTTP seam 24, design asset 23, graph 16, datastore 11, test lane 9. MOTIR-3856 tried to fix this by authoring a precondition rule per type; the PR was closed, because adding rules does not stop the wrong ones being delivered.
  • A LINE is currently a RULE, and that blocks every re-cut. tests/treeGeneration.test.ts's clauseOf states it: "clauses are one line each in the constant", and a family of guards asserts specific limbs sit adjacent to named neighbours because each reads back to the one before it. Splitting a constant changes what counts as a rule. Conservation cannot see it — it compares words and length, and a space becoming a newline changes neither.

That last point is the real blocker and it is a DECISION, not an implementation detail: it changes a recorded invariant, so it is settled on its own card before any text moves.

Acceptance criteria

  • A planning pass at skeleton receives the packs its KIND selects and no type pack at all; a pass at deepen receives the packs its kind selects (epic/story/bug) or its type selects (task/subtask), and never both.
  • type is set at skeleton and is an input to deepen, so a fresh plan's deepen pass composes the type's packs. Proven end-to-end on a generation pass, not only on the resolver.
  • No rule stops firing: for every clause that moves, the routing baseline shows the set of cells carrying it is a superset of the cells where its situation can occur.
  • The corpus a translate, copy or legal card receives contains no datastore, HTTP-seam or design-asset discharge — asserted, not reviewed by eye.
  • The worst cell and the corpus total are both measured before and after over the new cell space, at the run's own ref, and stated in the PR.
  • motir-meta's pack tree carries the same selector and the same cuts, and its MANIFEST is regenerated rather than hand-edited.

Context refs

  • motir-ai src/llm/planningRulePacks.tsresolvePlanningRulePacks, legalPlanningRuleCells, PACKS_BY_TYPE, CORPUS_ORDER.
  • motir-ai src/llm/workItemTypes.tsTYPED_KINDS (task, bug, subtask), CONTAINER_KINDS.
  • motir-ai src/llm/treeGeneration.tspropose_node / deepen_node tool schemas, deepenSelectorFor, buildGenerationSystemPrompt.
  • motir-ai tests/treeGeneration.test.tsclauseOf and the limb-adjacency guards.
  • motir-meta prompts/plan-rules/split.py + DECISION.numbers.py — the generated MANIFEST and its pre-split row model.
  • MOTIR-3853 / MOTIR-3866 / MOTIR-3869 — the three landed cards this replaces the shape of; motir-ai#325 carries them.
  • MOTIR-3856 — closed unmerged (motir-ai#332); its finding is folded in above.

Comments (0)

No comments yet — be the first to weigh in.

Sign in to comment

Reading is open to everyone; posting needs a Motir account.

Sign in