motir-marketing grows a Playwright lane — the harness, the CI job and the acceptance-video upload this story's E2E needs
Opened by Zhu Yue ·
motir-marketing has no browser test lane, and this story owes an E2E and an acceptance video. That is a prerequisite with no owner, so it is a card.
Measured on origin/main (79296a6): .github/workflows/ci.yml declares lint, typecheck, build, test, design-guards and deploy, and its own header says "There is still no coverage, e2e or e2e-at-scale job here and needs still names none." playwright is a devDependency, used by scripts/design/render-design-mock.ts and the test:design config — a headless chromium for measuring .mock.html files, not a test harness. There is no playwright.config, no e2e/ directory, and no acceptance-video workflow.
Build the lane, and nothing else:
- a Playwright config for this repository — a
webServerthat runs the built app, one project, the artefacts (trace, video) the acceptance receipt needs; - the public API stubbed at the network boundary, because the pages under test fetch
app.motir.coand CI has nomotir-core. Route-level fulfilment with fixtures shaped frommotir-core's published public contract, and a note saying that the CONTRACT itself is guarded in the producing repository (docs/decisions/public-surface-hosts.md§3) so this stub is a fixture, never a second source of truth; - an
e2ejob inci.yml, added todeploy'sneedsin the same change — the rule this file states about itself: "Add a gate toneedsbelow as this repository grows one — do not declare a gate before its job exists"; an acceptance-video workflow mirroring⚠️ FALSIFIED 2026-09-02 — both artefacts were DELETED frommotir-core's.github/workflows/acceptance-video.ymland its.github/actions/upload-acceptance-videocomposite, publishing throughPOST /api/work-items/{id}/acceptance-evidencewith an upload token.motir-coreNINETEEN HOURS AFTER this card was authored, by MOTIR-4096 (bb56e595a, merged2026-09-02T14:20:55Z; this card was authored2026-09-01T19:40:19Z).docs/decisions/acceptance-video.md's amendment of that date decides: "CI NO LONGER UPLOADS THE RECORDING. THE AGENT PUBLISHES IT, over the Motir MCP surface", retiring the uploader script, the composite action, theid-token: writegrant and theMOTIR_UPLOAD_TOKENsecret because "a credential with no consumer is one nobody thinks about when deciding whether to rotate it". Mirroring it would re-introduce that credential in a second repository the day after it left the first, and the same amendment recordsnextjs-prisma-vercel-starter's copy being retired under MOTIR-4097 — the precedent for a repository that would carry one. What ships instead is the half the decision KEPT: the lane RECORDS (video: 'on', report + clips uploaded as an ordinary run artifact) and the agent publishes the clip onto the card viaattach_file. Filed as MOTIR-4170 (the planning bug) — and, separately, the accessibility defect this card's own smoke spec surfaced, MOTIR-4169.
One smoke spec ships with the lane so the job has a subject and cannot be green-because-empty: load / and assert one landmark. The /p/* walk is the E2E card's.
The secret and the token are a provisioning question. If the acceptance-video upload needs a credential this repository does not have, that is not something to invent in a workflow file: file the manual/human provisioning card for it and wire this card blocked_by it, per the plan-ALL-types rule. Diff this card's own PR for new process.env reads before closing it.
Acceptance criteria
pnpm exec playwright testruns a real chromium against the built app locally, from a config committed in this repository.- A stub layer serves the
/api/public/*responses the pages read, from fixtures, with a comment naming the producing repository as the contract's owner. ci.ymlhas ane2ejob anddeploy'sneedsnames it; the header's running commentary is updated in the same change rather than left describing a repository that no longer exists.An acceptance-video workflow exists and, on its documented trigger, uploads a recorded run to a work item through the acceptance-evidence API — demonstrated once against a real work item, not asserted from the file.⚠️ WITHDRAWN — see the banner above. Replaced by: the lane RECORDS withvideo: 'on'and uploads the report and clips as a CI artifact, which is what the agent publishing the receipt reads from. Demonstrated locally: three specs green,video.webmand a failure screenshot written undertest-results/.- One smoke spec is in the lane and passes; the job fails if the spec is removed (no empty-suite pass).
- Every new environment variable or secret this lane requires is named on the card and has a provisioning work item, with this card
blocked_byit. — DISCHARGED BY THERE BEING NONE, not deferred. With the CI publisher out of scope there is no upload token, no OIDC grant and no secret. The PR was diffed for newprocess.envreads:MOTIR_PUBLIC_API_STUB_PORTandPORT, both set byplaywright.config.tsitself with defaults, neither a secret. No provisioning card is owed and noblocked_byedge is wired. - No file outside
motir-marketingis touched. (motir-core's workflow and composite action are read as the model; they are EVIDENCE here, not deliverables.)
Context refs
motir-marketing/.github/workflows/ci.yml— the jobs today, and the header's own rule about adding onemotir-marketing/package.json—playwrightas a devDependency;test:designmotir-marketing/vitest.design.config.mts·scripts/design/render-design-mock.ts— how chromium is already driven heremotir-core/.github/workflows/acceptance-video.yml·.github/actions/upload-acceptance-video/action.yml— the model to mirror (evidence, not deliverables)motir-core/app/api/work-items/[id]/acceptance-evidence/route.ts·upload-token/route.ts— the publish APImotir-core/docs/decisions/acceptance-video.md·docs/e2e/acceptance-video-byok.mdmotir-core/docs/decisions/public-surface-hosts.md§3 — the guard lives in the producing repository
Discussion
No comments yet.
Adding to this discussion signs you in on app.motir.co and brings you back to this request.