name: fm-verify
description: "Use after fm-gen to run the technical gate on a migrated page — build, TypeScript (composite-aware), Vitest, and ESLint (hard); Prettier --check is advisory — from the app's appDir, and advance the page to verified."
argument-hint: " [--app pc|mobile|hana]"
user-invocable: true
allowed-tools: Read, Write, Glob, Grep, Bash, Agent
Verify a Migrated Page (Technical Gate)
The first hard gate after generation: build + types + unit/component tests. (E2E is fm-e2e,
legacy parity is fm-parity.) All user-facing output in workingLanguage.
Instructions
Step 0: Config
Read config (absent → run fm-init; stop). Resolve app, its appDir, workingLanguage.
Confirm the page is at least generated in tracker.json.
Step 1: Lock
This skill mutates tracker.json, so acquire docs/migration/{app}/{page}/.lock (stale after
30 min) before running the gate. If held and fresh, report who holds it and stop.
Step 2: Resolve the run directory
All commands run from {monorepoRoot}/{appDir}. If appDir is ".", run from root.
Step 3: TypeScript (composite-aware)
Read tsconfig.json in {appDir}:
- has a
referencesarray →npx tsc -b 2>&1 - otherwise →
npx tsc --noEmit 2>&1
Step 4: Build & tests
npx vite build 2>&1(or the app's build script).npx vitest run 2>&1.
Step 4b: Lint (hard) & format (advisory)
Follow CLAUDE.md → "Lint & Format Gate" (detection / scaffold-if-flag-on / skip-if-deps-missing).
- ESLint — hard.
npx eslint . 2>&1. Exit ≠ 0 is a gate failure.skipped(config absent &eslintTemplate: false, or deps missing) does not fail the gate. - Prettier — advisory.
npx prettier --check . 2>&1. Exit ≠ 0 is recorded as a warning only; it never blocksverified. Surface the unformatted file list and suggestnpx prettier --write ..
Step 5: Read and judge (evidence before claims)
Apply the 5-step gate: RUN → READ the full output (exit codes, error/test counts) → VERIFY → CLAIM. Do not report a pass you did not observe. Capture the failing output verbatim if any step fails.
Step 6: Record
Update tracker.json (Read-Modify-Write):
- tsc + build + vitest + eslint all pass (or eslint
skipped) →apps[app].pages[page].status = "verified", withverifiedAt, the tool summary, and any Prettier advisory underformatWarnings. - any hard tool fails (tsc / build / vitest / eslint) →
verify-failed, with the failing summary. A Prettier advisory alone never setsverify-failed.
Release the lock.
Step 6b: Codex audit (advisory) — see CLAUDE.md → "Codex Independent Audit"
If codexAudit is enabled and Codex is available, after the lock is released spawn codex-auditor
(Agent) for the verify stage (params: app, page, stage="verify", appDir, legacyDir,
generated code + test paths + the verify summary, outPath = docs/migration/{app}/{page}/codex-audit.json,
workingLanguage) — an independent second opinion to Claude's own reviewers. Advisory — never
changes the page status. Surface its verdict below.
Step 7: Report
In workingLanguage: per-tool result (tsc / build / vitest / eslint) with the evidence (exit code,
counts), the Prettier advisory if any, and the Codex audit verdict (advisory). Next step: on pass →
/frontend-migration-plugin:fm-e2e {page}; on fail → /frontend-migration-plugin:fm-fix {page}.