Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-2357Done

`ai:plan` (2/4) — the plan-editing jobs: augment, expand, replan, the explanation drafter and the per-item planner

The second ai:plan card: the jobs that CHANGE an existing plan. Five submission routes across three services.

OperationService methodToday
POST /api/ai/augmentaiPlanEditsService.submitAugmentreaches a gate indirectly
POST /api/ai/expandaiPlanEditsService.submitExpandreaches a gate indirectly
POST /api/ai/replanaiPlanEditsService.submitReplanreaches a gate indirectly
POST /api/ai/explanationaiExplanationService.submitExplanationDraftnothing
POST /api/work-items/[id]/ai/planthe per-item plannerreaches a gate indirectly

aiPlanEditsService and aiExplanationService contain no assertion of their own on origin/main — the guard reads four of these as governed only because of something else the route calls, which is exactly the indirection the story exists to replace with a named key.

The [id]-scoped route resolves its project from the WORK ITEM, not from the active-project context. Resolve it explicitly and assert against that project id: a gate that asserts on the actor's active project while acting on an item in another one is not a gate at all.

Acceptance criteria

  • Each of the five service methods asserts projectAccessService.assertPermission(projectId, ctx, 'ai:plan') before submitting anything to motir-ai — before the job is created, so a refusal costs no credits.
  • The per-item planner resolves its project from the work item it acts on, and a test proves an item in a project the actor cannot plan in is refused.
  • A unit test proves a project viewer is refused all five, and an admin and member pass.
  • ai:plan does NOT flip to enforcement: 'enforced' here — the close-out card owns the flip once every ai:plan card has landed, so tests/permissions/catalog.test.ts is untouched by this PR.
  • The inventory rows for these five record the gate that landed.
  • The guard's pinned counts are re-derived by running it on this branch.
  • pnpm test tests/permissions/ tests/services/ is green.

Context refs

  • lib/services/aiPlanEditsService.ts, lib/services/aiExplanationService.ts — neither holds an assertion today.
  • app/api/work-items/[id]/ai/plan/route.ts — the route whose project comes from the item.
  • lib/services/projectAccessService.tsassertPermission.
  • docs/decisions/member-facing-permissions.md — the role assignment for ai:plan.
  • The role-set seam — the prerequisite.
  • ai:plan (1/4) — the sibling card; read its PR for the gate shape before repeating it.