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-4014Done

Vitest gate (motir-core) — the CONFIGURED manifest seam end to end, and both arms of the unconfigured case

Type: test · Executor: coding_agent · Repo: motir-core · ONE PR. The story's per-repo coverage + integration gate for the application host. The motir-marketing gate is the other one — one repo, one suite, one PR.

It runs LAST in this repository, after every motir-core code card has merged, because it measures their real, merged coverage and drives their real seams. Real Postgres, not mocks.

⚠️ RE-SCOPED 2026-09-01 — the ABSENCE clauses left with the deletion

The deletion moved out of this story (plan-rules/kind-container.md's merge-count check — see MOTIR-3909's own amendment), so the clauses that could only be asserted AFTER it are now the post-deletion vitest gate's, in the deletion story:

  • the no-content/legal-reader guard and its red run,
  • catalogue parity after the legal.* namespace was split.

Both were CUT from this card rather than duplicated, so nothing is asserted twice and nothing was dropped. This card's blocked_by edge to the deletion is gone with them; what remains is the CONFIGURED manifest seam, which is fully assertable with content/legal/ still in the tree because nothing surviving reads it.

⚠️ Do not re-add an absence assertion here on the grounds that it would be cheap. Asserted in this story it passes for a reason that has nothing to do with the guard: the files are still present and simply unread, so the guard is measuring the wrong state and would go green whether or not the reader was really gone.

Its three jobs at run time — not a plan-time case list

  1. Coverage floor. Run coverage over this story's changed surface in this repository and write whatever is missing to reach the project's per-file gate (≥90% branch/fn/line, motir-core/CLAUDE.md), plus the five files vitest.config.ts already pins at their own thresholds — lib/legal/{consent,documents,reconsentGate}.ts, lib/repositories/legalAcceptanceRepository.ts, lib/services/legalAcceptanceService.ts. Do not pre-subtract what the feature cards' own units cover; that they cover it is the expected normal, and this gate tops up the seams BETWEEN them.
  2. The integration seam, which for this story is one wire: the manifest value → documents.tsconsent.tslegalAcceptanceService → the LegalAcceptance rows → resolveOutstanding → the rendered row's href. Drive one card's real output back through the next card's real consumer. The units on either side mock the middle, and this is the only place the whole wire is exercised.
  3. The contract guards coverage cannot see — below.

The guards

  • ⚠️ NOTHING IN THIS REPOSITORY READS content/legal/ ANY MORE. MOVED to the post-deletion vitest gate (2026-09-01) — the files are still in this repository when this story merges, so the guard would pass here for the wrong reason. Its own sentence is why: a manifest that works proves the new path, never that the old one is gone, and neither does a guard run before anything left.
  • The materiality rule survives the source swap. Over a manifest: a MINOR or MAJOR bump on one of the three re-consent slugs HOLDS the user; a PATCH bump does not, because content/legal/terms.md §14 promises a clarification takes effect when published. This is consent.ts's rule, asserted through the seam rather than in isolation.
  • The unconfigured arm, on BOTH sides. With no manifest: recordAcceptance writes zero rows and does not throw; resolveOutstanding answers []; a signed-in request is not held; sign-up renders its unconfigured form and the rail has no Legal row. Assert each of those, not "nothing errored" — every one of them is a deliberate empty-set arm, and the whole failure mode this story guards against is exactly that arrangement being silently correct.
  • A malformed manifest cannot hold the product. An entry whose version does not parse must not reach listLegalDocuments(), because isMaterialChange treats an unparseable version as material and would hold every signed-in reader at /re-consent.
  • Tenancy isolation on the acceptance table. legalAcceptanceRepository writes under withUserContext; one user's acceptance rows must not be visible to another. A fixture in which the actor's view and the true population DIFFER — a test whose actor happens to see everything cannot tell a scoped read from an unscoped one.
  • Catalogue parity after the legal.* namespace was split. MOVED to the post-deletion vitest gate (2026-09-01) — nothing splits that namespace in this story.

⚠️ Read the lane's own configuration before writing a line in it

The manifest is a server-side, process-wide value, so a spec that needs it CONFIGURED has no per-test override and no client seam a request stub can reach. Name the exact mechanism this suite uses to set it, and confirm the runner reaches it, before writing the assertions — a guard in a lane that cannot reach the asserted state passes on unfixed code and stays green for ever. Where the configured arm cannot be reached from this suite at all, that arm belongs in the lane that sets it (see the E2E card) and this card says so rather than asserting the harness.

⚠️ What this card may NOT assert

  • Nothing about motir-marketing. The seven rendered documents, the reachability glob and the page-side subprocessor check are the other gate's, and a copy of them here would test a copied file.
  • Nothing about the redirect. MOTIR-3884's.
  • Nothing about the deployed manifest. The provisioning card reads that back from the platform; a repository suite cannot.

Acceptance criteria

  • Coverage over this story's changed surface in motir-core meets the per-file gate, and the five pinned files stay at their configured thresholds; the PR body shows the run.
  • The full manifest seam is driven end to end against real Postgres, from a configured manifest to a rendered href, in one test — not a chain of unit tests each mocking its neighbour.
  • The no-content/legal-reader guard exists, and the PR shows it going RED… MOVED to the post-deletion vitest gate (2026-09-01).
  • The materiality guard asserts both directions — a MINOR bump holds, a PATCH bump does not — through the seam.
  • All four unconfigured assertions are present and each is an assertion about a specific behaviour, not about the absence of an exception.
  • The malformed-manifest guard exists and is shown red against a valid-looking entry with an unparseable version.
  • The tenancy fixture has the actor's view and the true population DIFFER, and the PR body says so explicitly.
  • Catalogue parity passes. MOVED to the post-deletion vitest gate (2026-09-01).
  • The mechanism this suite uses to configure the manifest is named in the spec's own comment, and the PR body confirms the runner reaches it — or names which arm was moved to the E2E lane and why.
  • No test is deleted because its subject moved; anything re-pointed is re-pointed to a shipped symbol, and the PR body maps every assertion to one.

Context refs

  • motir-core/vitest.config.ts — the per-file thresholds on the five legal files
  • motir-core/lib/legal/documents.ts · consent.ts · reconsentGate.ts — the seam's upper half
  • motir-core/lib/services/legalAcceptanceService.ts · lib/repositories/legalAcceptanceRepository.ts — its lower half, and withUserContext
  • motir-core/tests/legal/ — the six surviving suites this composes with
  • motir-core/CLAUDE.md — the coverage gate and the real-Postgres discipline
  • motir-core/messages/en.json · messages/zh.json — the parity subject
  • the registry card · the link-surfaces card · the guard card — every motir-core code card this measures; all three blocked_by
  • the post-deletion vitest gate — took this card's absence clauses on 2026-09-01, in the deletion story; the deletion blocked_by edge went with them

Advisory dispositions

  • The remaining reference advisories name cards this one's Boundary excludes. A boundary exists to say a deliverable is somebody else's, and naming the owner is what makes the exclusion checkable — so the reference is deliberate and no edge is owed.