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

Delete content/legal/ and app/(public)/legal/ from motir-core — the 84-file referrer sweep, the CI content arm, and every dangling citation

Type: code · Executor: coding_agent · Repo: motir-core · ONE PR.

The documents are served from motir.co, the gate reads a manifest, the guard is re-homed and the redirect is in place. This card takes the old path out of the tree — and the abandoned path is itself the deliverable, not a side effect of emptying it.

⚠️ WHERE THIS CARD SITS — MOVED 2026-09-01

This card was MOTIR-4013, a child of MOTIR-3909. It is re-filed here, into the post-deploy half of that story, and its body is otherwise carried across unchanged.

Why: MOTIR-4013 was blocked_by MOTIR-4012, whose criteria read the DEPLOYED application that MOTIR-3909's own merge produces. A parent-run puts every child in one pull request, so that story could never open one — step 6 declines while a child is un-landed, and the merge that would unblock the confirmation also cascades done onto it. plan-rules/kind-container.md's merge-count check: two merges separated by a deploy is two containers.

What changed on this card, and nothing else did:

  • its parent, and therefore its blocked_by set — the edges to the guard card and the link-surfaces card are now CROSS-STORY and are carried by this story's own blocked_by MOTIR-3909 (plan-rules/phase-skeleton.md — never reach across a parent to sequence; readiness.blockedByAncestor holds every leaf here until that story is done);
  • the edge to the provisioning card is now an edge to the live-gate confirmation, which is the in-story sibling that observes the manifest actually holding a reader;
  • its key changed, so MOTIR-4013's relates_to edges did not travel with it and are re-wired by hand after approval.

Its two downstream gates moved with it and are this story's own children — the absence guard and the browser walk. The clauses they used to carry inside MOTIR-4014 and MOTIR-4015 were cut from those cards in the same plan, so nothing is asserted twice and nothing is dropped.

The population — MEASURE IT AGAIN, do not trust this table

git grep -l -E "content/legal|lib/legal|'/legal|\"/legal|legalDocument|LegalAcceptance|reconsent" origin/main returned 84 files at e76d1afdd (2026-08-30). Re-run it at this card's own base and give every file a disposition in the PR body — including any this table does not name. There is no third option to in scope and a named sibling.

groupfilesdisposition
content/legal/*.md7DELETE. content/ then holds nothing else (git ls-tree origin/main content/)
app/(public)/legal/{page.tsx,[slug]/page.tsx,layout.tsx}3DELETE — the abandoned route
tests/legal/legalPagesRender.test.tsx1DELETE ALREADY DONE by MOTIR-4007 (2026-09-01) — it could not survive that card: every assertion rendered doc.body, which left LegalDocument with the documents. Removed there with the reason. Do not expect to find it.
tests/legal/legalVersionGuard.test.ts1not previously listed ALSO ALREADY DONE by MOTIR-4007 — it asserted over the published document SET, which is no longer in this repository. The coverage it leaves behind is MOTIR-4133's, in motir-marketing.
messages/en.json · messages/zh.json2PARTIAL EDIT — the legal.* keys the deleted PAGES used go; the keys sign-up, the rail and the re-consent screen use STAY. Both catalogues move together
tests/seo/robots.test.ts1EDIT — its allow-list asserts /legal and /legal/privacy stay crawlable on this host, which stops being true
.github/workflows/ci.yml + tests/ci-changed-paths-gate.test.ts2⚠️ ASK THE ABSENCE QUESTION — see below
comment citations of content/legal/<doc>.md §N~12 (lib/dto/accountErasure.ts, lib/services/accountErasure{,Sweep}Service.ts, lib/jobs/definitions/accountErasureSweep.ts, lib/jobs/types.ts, lib/users/dataSubjectRequests.ts, lib/export/personalDataSections.ts, app/(authed)/settings/account/**, prisma/schema.prisma, lib/legal/*)EDIT — re-point each to the PUBLISHED document and its section, so the citation stays checkable
the re-consent machinery — lib/legal/{consent,documents,reconsentGate}.ts, lib/services/legalAcceptanceService.ts, lib/repositories/legalAcceptanceRepository.ts, app/(auth)/re-consent/**, lib/auth/index.ts, the three layouts, prisma/schema.prisma's LegalAcceptance + its migration, the six surviving tests/legal/* suites, tests/e2e/cloud-legal-reconsent.spec.tsmanyKEEP, untouched. This is the mechanism the story deliberately retains
lib/github/*, lib/test-lessons-mock.ts, lib/issues/executorDefaults.ts, components/planning/repositories/RepositorySetStep.tsx, docs/github-repo-creation-mechanics.md5+FALSE POSITIVES — they match on illegal or on legal as a work-item TYPE. Name them so the next reader does not re-check
app/(public)/explore/_components/ExploreFooter.tsx1NAMED SIBLING — its three /legal links die with the whole file under MOTIR-3951
the 301 off app.motir.co/legal/*NAMED SIBLINGMOTIR-3884, under MOTIR-3932, which this whole story is blocked_by

⚠️ The CI arm is a SUPPRESSOR, and the ordering rationale is inverted for it

.github/workflows/ci.yml carries content/*) app=true ahead of the *.md exclusion, and tests/ci-changed-paths-gate.test.ts asserts that order in three places. It exists because a legal-document-only pull request (#2427) skipped the entire Vitest lane, including the seven tests/legal/ suites written to guard exactly that file class.

Ask plan-rules/type-migration.md's question of it: if this arm were absent, what would start happening? The answer is not nothing. content/ is empty today, so removing the arm changes no current behaviour — and it silently re-arms #2427's defect for the next content/*.md anybody adds, because the *.md exclusion would then swallow it. The RECOMMENDED disposition is therefore to KEEP the arm and re-point its test's rationale, not to delete it as dead. Whichever is chosen, the PR body answers the absence question in one line, and the test's comments stop citing a directory that no longer exists.

The abandoned path, all the way down

Deleting the three route files is limb 1. Follow it inward:

  • What the route SOLELY kept alive. lib/legal/documents.ts looks like it dies with the pages and does not — it is the manifest reader the registry card rebuilt, and the re-consent gate is its surviving caller. Do not delete it. Verify by caller, not by name.
  • Their tests, which otherwise keep a deleted capability green and make the dead code look load-bearing.
  • The i18n keys, which are the quietest residue: a catalogue key nothing reads is invisible to every check.

Boundary

  • It issues no redirect and repoints no DNS.
  • It touches nothing under app/(public) except legal/MOTIR-3951 owns the other 69 files, and its own table names legal as this card's.
  • It does not touch the re-consent machinery, the LegalAcceptance table or its migration.
  • It changes no rendered surface's behaviour. Sign-up, the rail and the re-consent rows already read the manifest — the link-surfaces card did that in MOTIR-3909, which this story is blocked_by.
  • It does not edit app/sitemap.ts. That file never listed the legal documents — git grep -i legal origin/main -- app/sitemap.ts returns nothing, and MOTIR-3881 settled its contents.

⚠️ Ordering — TWO story edges and ONE leaf edge

Delete before the redirect and /legal 404s for everyone holding a link; redirect first and the pages are quietly unreachable before they are removed. So this card must run after MOTIR-3884 — which it does: that card is under MOTIR-3932, which is done, and MOTIR-3909 is blocked_by it.

Delete before the hosted gate has been SEEN working over the manifest, and the fallback is gone while nothing is known to have replaced it. That is the leaf edge this card carries: blocked_by the live-gate confirmation, an in-story sibling. It replaces the old edge to MOTIR-4012, which set the value but could not observe it being read.

Everything else this card used to be ordered against is carried by this story's own blocked_by MOTIR-3909 — the manifest reader, the three link surfaces, the subprocessor split and the provisioning. The readiness cascade holds every leaf here until that whole story is done, so no cross-parent leaf edge is owed and none is wired.

Acceptance criteria

  • Every file the re-run grep returns has a disposition in the PR body — deleted, edited, kept with a reason, or named as another card's — with the re-run population quoted rather than this card's table. No file is left unaccounted for.
  • content/legal/ and app/(public)/legal/ are gone; git grep -n "content/legal" -- ':!docs/decisions' returns nothing but re-pointed citations.
  • git grep -rn "moooon" -- ':!docs' ':!CLA.md' ':!README.md' ':!.github' ':!design' returns only the configuration seam and its tests — the story's own verification step, run and quoted.
  • The legal.* catalogue keys are split correctly: en and zh stay in parity, no key that a surviving surface reads is removed, and no orphan key survives.
  • tests/seo/robots.test.ts no longer asserts /legal is crawlable on this host, and its comment says why.
  • The CI arm's absence question is answered in one line in the PR body, and tests/ci-changed-paths-gate.test.ts is consistent with whatever was chosen — no assertion cites a path that no longer exists.
  • Every re-pointed comment citation names the document as served on the brand host, and its section, so the reference is still checkable by a reader.
  • lib/legal/documents.ts and the whole re-consent path are untouched, and the six surviving tests/legal/ suites plus tests/e2e/cloud-legal-reconsent.spec.ts are green.
  • next build produces no route under app/(public)/legal, and the route manifest is in the PR body.
  • No test is deleted merely because its subject moved: one covering behaviour that still exists is re-pointed; one covering a deleted page is removed with its reason stated.
  • ≥90% coverage on any file this PR modifies rather than deletes; the five files vitest.config.ts pins stay at their thresholds.

Context refs

  • motir-core/content/legal/ · app/(public)/legal/ — the population being removed
  • motir-core/.github/workflows/ci.yml — the content/* arm, and the comment recording PR #2427
  • motir-core/tests/ci-changed-paths-gate.test.ts — the three assertions about it
  • motir-core/tests/seo/robots.test.ts — the crawlable-allow list
  • motir-core/messages/en.json · messages/zh.json — the legal.* namespace to split
  • motir-core/lib/legal/documents.ts — looks abandoned, is not; verify by caller
  • motir-core/app/sitemap.ts — verified NOT a legal reader
  • MOTIR-3951 — the rest of app/(public); its table names legal as this card's
  • MOTIR-3884 — the redirect, in MOTIR-3932; ordered against by the story edge, not a leaf edge
  • the live-gate confirmationblocked_by, so the hosted gate is SEEN holding a reader over the manifest before the fallback goes
  • MOTIR-4012 — set the hosted manifest inside MOTIR-3909; ordered against by the story edge, not a leaf edge

Advisory dispositions

  • shape / likely-ordering-violation (criterion 7, phrase the published): ACTED ON — the phrase was a false trigger and is gone. The criterion was never about state after this card's own pull request merges: published named the document as served on the brand host by the render card, which is in MOTIR-3932 and therefore done before this card starts. The wording now says that directly rather than leaving a lexical gate to argue with. Every criterion on this card is satisfiable at PR opened.
  • Every reference advisory naming a card under MOTIR-3909 — the registry, guard, link-surfaces and provisioning cards: NOT an owed leaf edge. They sit in another container, and this story is blocked_by that container; the edge belongs BETWEEN the stories and already exists, so nothing is owed (core.md gate 4's cross-parent limb; gate 7).
  • 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.