[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6RW2GC842HR3KNW2TJ5A7P2":3,"skill-same:01M6RW2GC842HR3KNW2TJ5A7P2":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":13,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":58,"install":59,"resources":71},"01M6RW2GC842HR3KNW2TJ5A7P2","quarkus-tdd",null,"Test-driven development for Quarkus 3.x LTS using JUnit 5, Mockito, REST Assured, Camel testing, and JaCoCo. Use when adding features, fixing bugs, or refactoring event-driven services.","sakamoto-family-smile\u002Fagent_monorepo","sakamoto-family-smile","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F132812403?v=4","01M6RTAT3H8PMWX5SJ65KP3VYF","01M6RTAV321WB5RAHCWTZMX5CV",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fecc\u002Fquarkus-tdd\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"tdd","quarkus tdd","quarkus","when","testing","test-driven","mockito","features","bugs","for","event","event-driven","driven","use","refactoring","REST","services","camel","development","test","2026-11-10 10:12:30",false,"---\nname: fm-verify\ndescription: \"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.\"\nargument-hint: \"\u003Cpage> [--regate] [--app pc|mobile|hana]\"\nuser-invocable: true\nallowed-tools: Read, Write, Glob, Grep, Bash, Agent\n---\n\n# Verify a Migrated Page (Technical Gate)\n\nThe first hard gate after generation: build + types + unit\u002Fcomponent tests. (E2E is `fm-e2e`,\nlegacy parity is `fm-parity`.) All user-facing output in `workingLanguage`.\n\n## Instructions\n\n### Step 0: Config\nRead config (absent → run `fm-init`; stop). Resolve `app`, its `appDir`, `monorepoRoot`,\n`packagesDir` (Step 6 maps the plan's `sharedDeps[]` through it for the gate-evidence hash), **`pluginRoot`** (absolute, per-machine — read from `.claude\u002Ffrontend-migration-plugin.local.json`, never the shared config; where `scripts\u002Fgate-tree-hash.sh` lives — absent → record no `tree` and report the freshness axis `unverifiable`, never an inline pipeline).\n`legacyDir` (Step 6b hands it to the Codex auditor), `workingLanguage`. Confirm the page is at least `generated` in `tracker.json` — **but refuse a page\nat `flipped` or `done`, and refuse while `flipPrOpenedAt` is present** (unless `--regate`, Step 0a, admits it): \"at least `generated`\" is a\nmonotonic comparison and `flipped`\u002F`done` both satisfy it, so\nwithout this guard a re-verify would write `verified` over a live page and desync the tracker from\nthe edge flag (CLAUDE.md → Per-page State Machine). For `flipped` or a present `flipPrOpenedAt`,\npoint the user at `\u002Ffrontend-migration-plugin:fm-verify {page} --regate` (Step 0a — re-gate without\na status change), or at `\u002Ffrontend-migration-plugin:fm-route {page} --revert` to abandon the flip.\nFor **`done`, do not** — `--revert` refuses a `done` page (the legacy page is deleted, so there is no\nrollback target); reopening it is a manual decision.\n\n**Warn before demoting, and clear the route fields.** If the page is already at `verified`,\n`e2e-passed` or `parity-passed`, this skill's Record step moves it backwards and discards that gate\nprogress — **so clear `routePrepared` and `flagKey` on that write**, the same set `fm-gen`,\n`fm-fix`, `fm-delta` and `fm-extract` clear for the same reason. Left standing, the page re-passes\nthe chain and reaches `--flag-on` with a `routePrepared` from before the change, so Step 1-pre is\nsatisfied by the stale `--flag-off` and the route-stage Codex audit that step exists to force never\nre-runs. This is the recovery `fm-route` Step 1a now names, so it is the path that reaches it. Say so and get confirmation first — the same courtesy `fm-gen` Step 2 extends. Without it, the documented recovery from a stale-evidence block (re-run the gates) silently destroys `parity-passed` on the way through.\n\n**Confirm `apps[app]` before using it** (CLAUDE.md → Configuration): the app entry must exist and carry the keys this stage reads. Config-file presence is not app presence — `mobile`\u002F`hana` are scaffolded, and a `--app` naming an unconfigured one must stop here with a clear message rather than fail deep inside an agent on an unresolved path.\n\n### Step 0a: `--regate` (in-flight or flipped page) — CLAUDE.md → Per-page State Machine → In-flight window\nWith `--regate`, require `flipPrOpenedAt` present (status `parity-passed`) or status `flipped`;\nrefuse anything else and name the plain `fm-verify {page}` run, which is what advances a status.\nRun Steps 1–5 unchanged. Step 6 then records **evidence only**: it never writes `status`,\n`routePrepared`, `flagKey`, `flipPrOpenedAt` or `flippedAt`, and skips the demotion warning above.\nOn a pass it writes `verifiedAt`, `gateEvidence.verify` and the manifest exactly as the pass branch\ndoes, and deletes `regateFailed.verify`. On a failure it writes\n`regateFailed.verify = { \"at\", \"commit\", \"summary\" }` (the failing summary) instead of\n`verify-failed`. `fm-route --confirm-live` blocks while verify's evidence is stale or `regateFailed.verify` is present.\n\n### Step 1: Lock\nThis skill mutates `tracker.json`, so acquire `docs\u002Fmigration\u002F{app}\u002F{page}\u002F.lock` (stale only when\nits holder is gone — CLAUDE.md → Lock file) before running the gate. If held and fresh, report who holds it and stop.\n\n### Step 2: Resolve the run directory\nAll commands run from `{monorepoRoot}\u002F{appDir}`. If `appDir` is `\".\"`, run from root.\n\nBefore the first tool runs, compute the **pre-run** `tree` hash — same script, same watch-path\nunion as Step 6. Step 6 compares its record-time hash against this one: a gate may record a pass\nonly if its watch paths did not move while it ran (CLAUDE.md → Gate Result Accounting E).\n\n### Step 3: TypeScript (composite-aware)\nRead `tsconfig.json` in `{appDir}`:\n- has a `references` array → `npx tsc -b 2>&1`\n- otherwise → `npx tsc --noEmit 2>&1`\n\n### Step 4: Build & tests\n- `npx vite build 2>&1` (or the app's build script).\n- `npx vitest run 2>&1`.\n\n### Step 4a: i18n key coverage (observed-in-the-run check — the run itself is Step 4)\nThe key-coverage spec `foundation-generator` scaffolds (`templates\u002Fi18n-copy-parity.md`) runs inside\nStep 4's `npx vitest run`, so a missing\u002Flocale-gapped key — or a markup\u002Fentity value rendered as\nplain text (K3) — already **fails the gate** there; there is no separate command here. What this\nstep adds is that the spec **ran**, so the check cannot be silently removed — by deletion or by\nfalling out of the harness's collection:\n- Config has an `i18n` block, the app has the spec, **and the spec's results appear in Step 4's\n  vitest output** → note it as `present` and surface its `uncheckable` (dynamic-key) count from\n  that output. A rising count is a signal, not a pass. **File existence is not the test** — a spec\n  vitest never collected produces no output to read, and recording `present` from the file alone is\n  the pass-you-did-not-observe Step 5 forbids.\n- Config has an `i18n` block but the spec is **absent** → **gate failure**; point at\n  `fm-gen {page} --force` (there is no per-phase entry point; `--force` re-runs every phase, and\n  `foundation-generator` regenerates the spec when the app has none).\n- Config has an `i18n` block, the spec exists, but **its results are not in the output** → **gate\n  failure**, and **do not** record `regenRequiredAt`: the spec is already there, so a full\n  regeneration would not change whether vitest collects it. Two cases, told apart by Step 4's exit\n  code because their remedies differ:\n  - **vitest exited 0** → the spec was genuinely not collected. Record the failing summary as\n    `i18n key-coverage spec not collected: \u003Cpath>` — `migration-fixer`'s `verify-fix` mode owns the\n    harness and repairs the include pattern. It still re-runs all four tools, but the repair is what\n    makes the next `fm-verify` observe the spec — without it `fm-fix` would report a pass and land\n    the page back on this same failure.\n  - **vitest exited non-zero** → the run died before per-file reporting, so \"not collected\" cannot\n    be told from \"never reached\". Record the coverage axis as `not-observed` and let the hard-tool\n    failure carry the gate; its remedy is the one that applies.\n- No `i18n` block in config → record `skipped` (never a silent pass); note that `fm-init` can add it.\n\n**Route-target spec** (`foundation-generator` 3c) — the same observed-in-the-run reading, lighter\nconsequences. Its failures already fail Step 4's vitest run. Find it by name, `route-targets.test.ts`\nunder `{appDir}`, and record `routeTargets` as one of:\n- `present` — its results appear in the output. Surface its `uncheckable` count.\n- `absent` — no such file.\n- `not-observed` — the file exists but vitest exited non-zero before per-file reporting. The\n  hard-tool failure carries the gate, as in the i18n branch.\n- **not collected** — the file exists but its results are not in the output while vitest exited 0.\n  This is a **gate failure**, exactly like the i18n branch above: summary\n  `route-target spec not collected: \u003Cpath>`, no `regenRequiredAt`, repaired by `verify-fix`. File\n  existence is not the test.\n\n**Only `absent` is reported rather than failed**, because the spec postdates many already-generated\napps. The next page this app generates scaffolds it (`foundation-generator`\nchecks per app, not per page); `fm-gen {page} --force` does it now. Say so in the report and name\nthe command.\n\n### Step 4b: Lint (hard) & format (advisory)\nFollow CLAUDE.md → \"Lint & Format Gate\" (detection \u002F scaffold-if-flag-on \u002F skip-if-deps-missing).\n- **ESLint — hard.** `npx eslint . 2>&1`. Exit ≠ 0 is a gate failure. `skipped` (config absent &\n  `eslintTemplate: false`, or deps missing) does not fail the gate.\n- **Prettier — advisory.** `npx prettier --check . 2>&1`. Exit ≠ 0 is recorded as a warning only;\n  it never blocks `verified`. Surface the unformatted file list and suggest `npx prettier --write .`.\n\n### Step 4c: Design-token traps (advisory — `templates\u002Fvisual-parity-checklist.md`)\nThe computed-value parity probe catches a mis-resolved Tailwind token, but it runs later and is\nskipped\u002Fblocked exactly where clusters and blocked pages ship — so surface the **known** traps here,\nat the first gate, where they are cheap to fix. Grep this page's generated files (`tracker.json`\n`sourcePaths[]` — never the legacy tree) for the enumerated trap literals:\n\n```sh\ngrep -nE '\\brounded-lg\\b|\\bfont-inherit\\b|\\bborder-[trbl]-solid\\b' -- \u003CsourcePaths...> 2>\u002Fdev\u002Fnull || true\n```\n\nReport each hit `file:line · \u003Cliteral>` as an **advisory warning** (like Prettier — it never sets\n`verify-failed` or blocks): `rounded-lg` computes 16px in this repo (use `rounded-[8px]` for a bespoke\nlegacy radius), and `font-inherit` \u002F per-side border-style emit no CSS in Tailwind v4. Point at the\nchecklist's \"Design-token traps\" section and the page's `style-spec.json` computed value. A project's\nown `docs\u002Fmigration\u002F**\u002Fcss-parity-checklist.md`, if present, may list more literals to grep. This is a\nreminder to check the computed value against the spec, not a verdict.\n\n### Step 5: Read and judge (evidence before claims)\nApply the 5-step gate: RUN → READ the full output (exit codes, error\u002Ftest counts) → VERIFY →\nCLAIM. Do not report a pass you did not observe. Capture the failing output verbatim if any step\nfails.\n\n### Step 6: Record\n\n**Tracker lock.** Take `docs\u002Fmigration\u002F.tracker.lock` around every `tracker.json` write below —\nafter the lock this step already holds, released right after the write (CLAUDE.md → Lock file). Write it per CLAUDE.md → Serialization.\n\nUpdate `tracker.json` (Read-Modify-Write). **Under `--regate`, apply Step 0a instead of every status\nwrite below** — the evidence writes are the same:\n- tsc + build + vitest + eslint all pass (or eslint `skipped`) **and** the i18n key-coverage spec is\n  `present` or `skipped` **and** the route-target spec is `present` or `absent` → `apps[app].pages[page].status = \"verified\"`, with `verifiedAt`, the tool\n  summary, the spec's `uncheckable` count under `i18nCoverage`, the route-target spec's state under\n  `routeTargets` (`{ \"state\": \"present\", \"uncheckable\": N }` or `{ \"state\": \"absent\" }`), and any\n  Prettier advisory under `formatWarnings` (all three are reporting surfaces for `fm-progress` and a\n  human reading the tracker — no gate branches on any of them; a Prettier advisory never fails\n  anything). **Clear `regenRequiredAt`**\n  — a passing gate means the full regeneration it records as owed is discharged, however it was\n  met. Also record\n  `apps[app].pages[page].gateEvidence.verify = { \"at\": \u003CISO-8601>, \"commit\": \u003Csha>, \"tree\": \u003Chash> }`\n  exactly as CLAUDE.md → \"Gate Result Accounting\" E prescribes — `commit` from\n  `git rev-parse --short HEAD` (`\u003Csha>+dirty` when `git status --porcelain` is non-empty), `tree` by\n  **running the script** once with `--manifest` and hashing its output — never by re-implementing\n  its records with an inline pipeline:\n\n  ```sh\n  REPO=$(git rev-parse --show-toplevel)\n  MAN=\"$REPO\u002Fdocs\u002Fmigration\u002F{app}\u002F{page}\u002Fgate-tree\u002Fverify.tsv\"\n  mkdir -p \"$(dirname \"$MAN\")\"\n  {pluginRoot}\u002Fscripts\u002Fgate-tree-hash.sh --manifest \\\n      --exclude docs\u002Fmigration\u002F{app}\u002F{page}\u002Fgate-tree\u002Fverify.tsv -- \u003Cwatch path>... > \"$MAN.tmp\"\n  TREE=$(git hash-object --no-filters -- \"$MAN.tmp\")\n  ```\n\n  **One execution produces both.** The script's aggregate is `git hash-object` of exactly these\n  records (its own construction), so hashing the manifest file yields the same `tree` — atomically.\n  Two separate executions could straddle a change and record a hash the manifest does not describe.\n  On a non-zero script exit, do not hash: exit 2 put `unverifiable` in the redirect (freshness axis\n  `unverifiable`), exit 1 is an error.\n\n  Watch paths are the union of the three axes CLAUDE.md → \"Gate Result Accounting\" F defines,\n  **minus every axis-1 entry under `{appDir}\u002Fe2e\u002F`**, and minus any untracked axis-1 entry\n  `git check-ignore -q` accepts (F) (the e2e carve-out: `fm-e2e` has not realized\n  them yet, and a re-run rewrites them);\n  resolve `packagesDir` and `monorepoRoot` in Step 0 and read the plan's `sharedDeps[]` here.\n  The redirect target must be the real repo root, not `{monorepoRoot}` — this skill runs from\n  `{appDir}`. Compare this hash with the pre-run hash from Step 2: if they differ, the watch paths\n  moved while the gate ran — record **no pass**, leave the status unchanged, discard `\"$MAN.tmp\"`,\n  and say to re-run. Only when the pass is recorded, promote the manifest — an overwritten\n  manifest beside a refused pass would pair the old recorded `tree` with a file list from a\n  different tree — and stage it with the tracker: the two are one piece of evidence, and\n  `fm-route` Step 1a blocks while either is uncommitted:\n\n  ```sh\n  REPO=$(git rev-parse --show-toplevel); MAN=\"$REPO\u002Fdocs\u002Fmigration\u002F{app}\u002F{page}\u002Fgate-tree\u002Fverify.tsv\"\n  mv \"$MAN.tmp\" \"$MAN\" && git add -- \"$MAN\" \"$REPO\u002Fdocs\u002Fmigration\u002Ftracker.json\"\n  ```\n\n  If `git add` fails (the index lock held by a concurrent page, an ignored path), say so: the pass\n  stands, the pair is unstaged, and `fm-route` Step 1a blocks until it is committed.\n\n  If it prints `unverifiable` (exit 2 — no watch paths resolved), record **no `tree`** and say so:\n  the page is unverifiable on this axis, which `fm-route` acknowledges rather than blocks. Never\n  store the word `unverifiable`, and never store a hash the script did not print. Keep `verifiedAt` for\n  backward compatibility.\n- any hard tool fails (tsc \u002F build \u002F vitest \u002F eslint) → `verify-failed`, with the failing summary.\n  A Prettier advisory alone never sets `verify-failed`.\n- **while `i18n` is configured**, the spec **exists but its results are not in the output, and no\n  hard tool failed** (eslint\n  `skipped` counts here exactly as it does in the pass branch above — it is neither a pass nor a\n  failure, and an app that has not installed the lint deps yet is the ordinary early state) →\n  `verify-failed`, with the failing summary `i18n key-coverage spec not collected: \u003Cpath>` and\n  **no `regenRequiredAt`** (Step 4a). Both halves are load-bearing: without the status the page\n  keeps its entry status and `fm-fix` — the remedy Step 7 names — refuses it; without the summary\n  in `tracker.json` the harness repair in `migration-fixer`'s `verify-fix` mode has nothing to key\n  on, since verify writes no report file.\n- the route-target spec **exists but its results are not in the output, and no hard tool failed**\n  → `verify-failed`, summary `route-target spec not collected: \u003Cpath>`, no `regenRequiredAt` — the\n  same handling and the same reasons as the i18n not-collected branch above.\n- the spec is **absent while `i18n` is configured** → `verify-failed` **and record\n  `regenRequiredAt`**. `fm-fix` cannot produce the spec (Step 7), and the next-step advisors\n  already override the `*-failed` wildcard to `fm-gen --force` when that field is set — this is\n  what puts them on the remedy this skill's own report names. `fm-gen` Step 5.3 clears it once a\n  full regeneration succeeds, and this skill's own PASS branch clears it too.\n\nRelease the lock.\n\n### Step 6b: Codex audit (advisory) — see CLAUDE.md → \"Codex Independent Audit\"\nIf `codexAudit` is enabled and this stage is in `codexAuditStages` (**absent → all seven**; the\nkey narrows coverage, it never means \"none\"), after the lock is released spawn\n`codex-auditor`\n(Agent) for the `verify` stage (params: `app`, `page`, `stage=\"verify\"`, `appDir`, `legacyDir`,\ngenerated code + test paths + the verify summary, `outPath = docs\u002Fmigration\u002F{app}\u002F{page}\u002Fcodex-audit.json`,\n`workingLanguage`) — an independent second opinion to Claude's own reviewers. Advisory — never\nchanges the page status. Surface its verdict below.\n\n### Step 7: Report\nIn `workingLanguage`: per-tool result (tsc \u002F build \u002F vitest \u002F eslint) with the evidence (exit code,\ncounts), the i18n key-coverage result (`present` + `uncheckable` count \u002F `absent` \u002F `not collected` \u002F\n`not-observed` \u002F `skipped`), the route-target spec result (`present` + `uncheckable` count \u002F\n`absent` with its remedy \u002F `not collected` \u002F `not-observed`), the\nPrettier advisory if any, and the Codex audit verdict (advisory). Next step: on pass →\n`\u002Ffrontend-migration-plugin:fm-cascade {page}` when the page injects markup it does not author (CMS\nrich text, i18n values containing HTML, editor output — the case no element-indexed style spec and no\njsdom test can cover), otherwise `\u002Ffrontend-migration-plugin:fm-e2e {page}`; on fail →\n`\u002Ffrontend-migration-plugin:fm-fix {page}`\n— **except the absent i18n key-coverage spec** (Step 4a), whose remedy is\n`\u002Ffrontend-migration-plugin:fm-gen {page} --force`. `fm-fix` cannot produce that spec: its\n`verify-fix` mode re-runs tsc\u002Fbuild\u002Fvitest\u002Feslint, all of which pass, so it would report a\nsuccessful fix, set the page back to `generated`, and land on this same failure again.\n\n**Under `--regate`** the next step follows the evidence, not a status: on a pass,\n`\u002Ffrontend-migration-plugin:fm-e2e {page} --regate`; on a failure,\n`\u002Ffrontend-migration-plugin:fm-fix {page} --mode review --findings \u003Cfile>` with the failure as the\nfinding (then re-gate), or `fm-route {page} --revert` to take the page back to legacy.\n","# Verify a Migrated Page (Technical Gate)\n\nThe first hard gate after generation: build + types + unit\u002Fcomponent tests. (E2E is `fm-e2e`,\nlegacy parity is `fm-parity`.) All user-facing output in `workingLanguage`.\n\n## Instructions\n\n### Step 0: Config\nRead config (absent → run `fm-init`; stop). Resolve `app`, its `appDir`, `monorepoRoot`,\n`packagesDir` (Step 6 maps the plan's `sharedDeps[]` through it for the gate-evidence hash), **`pluginRoot`** (absolute, per-machine — read from `.claude\u002Ffrontend-migration-plugin.local.json`, never the shared config; where `scripts\u002Fgate-tree-hash.sh` lives — absent → record no `tree` and report the freshness axis `unverifiable`, never an inline pipeline).\n`legacyDir` (Step 6b hands it to the Codex auditor), `workingLanguage`. Confirm the page is at least `generated` in `tracker.json` — **but refuse a page\nat `flipped` or `done`, and refuse while `flipPrOpenedAt` is present** (unless `--regate`, Step 0a, admits it): \"at least `generated`\" is a\nmonotonic comparison and `flipped`\u002F`done` both satisfy it, so\nwithout this guard a re-verify would write `verified` over a live page and desync the tracker from\nthe edge flag (CLAUDE.md → Per-page State Machine). For `flipped` or a present `flipPrOpenedAt`,\npoint the user at `\u002Ffrontend-migration-plugin:fm-verify {page} --regate` (Step 0a — re-gate without\na status change), or at `\u002Ffrontend-migration-plugin:fm-route {page} --revert` to abandon the flip.\nFor **`done`, do not** — `--revert` refuses a `done` page (the legacy page is deleted, so there is no\nrollback target); reopening it is a manual decision.\n\n**Warn before demoting, and clear the route fields.** If the page is already at `verified`,\n`e2e-passed` or `parity-passed`, this skill's Record step moves it backwards and discards that gate\nprogress — **so clear `routePrepared` and `flagKey` on that write**, the same set `fm-gen`,\n`fm-fix`, `fm-delta` and `fm-extract` clear for the same reason. Left standing, the page re-passes\nthe chain and reaches `--flag-on` with a `routePrepared` from before the change, so Step 1-pre is\nsatisfied by the stale `--flag-off` and the route-stage Codex audit that step exists to force never\nre-runs. This is the recovery `fm-route` Step 1a now names, so it is the path that reaches it. Say so and get confirmation first — the same courtesy `fm-gen` Step 2 extends. Without it, the documented recovery from a stale-evidence block (re-run the gates) silently destroys `parity-passed` on the way through.\n\n**Confirm `apps[app]` before using it** (CLAUDE.md → Configuration): the app entry must exist and carry the keys this stage reads. Config-file presence is not app presence — `mobile`\u002F`hana` are scaffolded, and a `--app` naming an unconfigured one must stop here with a clear message rather than fail deep inside an agent on an unresolved path.\n\n### Step 0a: `--regate` (in-flight or flipped page) — CLAUDE.md → Per-page State Machine → In-flight window\nWith `--regate`, require `flipPrOpenedAt` present (status `parity-passed`) or status `flipped`;\nrefuse anything else and name the plain `fm-verify {page}` run, which is what advances a status.\nRun Steps 1–5 unchanged. Step 6 then records **evidence only**: it never writes `status`,\n`routePrepared`, `flagKey`, `flipPrOpenedAt` or `flippedAt`, and skips the demotion warning above.\nOn a pass it writes `verifiedAt`, `gateEvidence.verify` and the manifest exactly as the pass branch\ndoes, and deletes `regateFailed.verify`. On a failure it writes\n`regateFailed.verify = { \"at\", \"commit\", \"summary\" }` (the failing summary) instead of\n`verify-failed`. `fm-route --confirm-live` blocks while verify's evidence is stale or `regateFailed.verify` is present.\n\n### Step 1: Lock\nThis skill mutates `tracker.json`, so acquire `docs\u002Fmigration\u002F{app}\u002F{page}\u002F.lock` (stale only when\nits holder is gone — CLAUDE.md → Lock file) before running the gate. If held and fresh, report who holds it and stop.\n\n### Step 2: Resolve the run directory\nAll commands run from `{monorepoRoot}\u002F{appDir}`. If `appDir` is `\".\"`, run from root.\n\nBefore the first tool runs, compute the **pre-run** `tree` hash — same script, same watch-path\nunion as Step 6. Step 6 compares its record-time hash against this one: a gate may record a pass\nonly if its watch paths did not move while it ran (CLAUDE.md → Gate Result Accounting E).\n\n### Step 3: TypeScript (composite-aware)\nRead `tsconfig.json` in `{appDir}`:\n- has a `references` array → `npx tsc -b 2>&1`\n- otherwise → `npx tsc --noEmit 2>&1`\n\n### Step 4: Build & tests\n- `npx vite build 2>&1` (or the app's build script).\n- `npx vitest run 2>&1`.\n\n### Step 4a: i18n key coverage (observed-in-the-run check — the run itself is Step 4)\nThe key-coverage spec `foundation-generator` scaffolds (`templates\u002Fi18n-copy-parity.md`) runs inside\nStep 4's `npx vitest run`, so a missing\u002Flocale-gapped key — or a markup\u002Fentity value rendered as\nplain text (K3) — already **fails the gate** there; there is no separate command here. What this\nstep adds is that the spec **ran**, so the check cannot be silently removed — by deletion or by\nfalling out of the harness's collection:\n- Config has an `i18n` block, the app has the spec, **and the spec's results appear in Step 4's\n  vitest output** → note it as `present` and surface its `uncheckable` (dynamic-key) count from\n  that output. A rising count is a signal, not a pass. **File existence is not the test** — a spec\n  vitest never collected produces no output to read, and recording `present` from the file alone is\n  the pass-you-did-not-observe Step 5 forbids.\n- Config has an `i18n` block but the spec is **absent** → **gate failure**; point at\n  `fm-gen {page} --force` (there is no per-phase entry point; `--force` re-runs every phase, and\n  `foundation-generator` regenerates the spec when the app has none).\n- Config has an `i18n` block, the spec exists, but **its results are not in the output** → **gate\n  failure**, and **do not** record `regenRequiredAt`: the spec is already there, so a full\n  regeneration would not change whether vitest collects it. Two cases, told apart by Step 4's exit\n  code because their remedies differ:\n  - **vitest exited 0** → the spec was genuinely not collected. Record the failing summary as\n    `i18n key-coverage spec not collected: \u003Cpath>` — `migration-fixer`'s `verify-fix` mode owns the\n    harness and repairs the include pattern. It still re-runs all four tools, but the repair is what\n    makes the next `fm-verify` observe the spec — without it `fm-fix` would report a pass and land\n    the page back on this same failure.\n  - **vitest exited non-zero** → the run died before per-file reporting, so \"not collected\" cannot\n    be told from \"never reached\". Record the coverage axis as `not-observed` and let the hard-tool\n    failure carry the gate; its remedy is the one that applies.\n- No `i18n` block in config → record `skipped` (never a silent pass); note that `fm-init` can add it.\n\n**Route-target spec** (`foundation-generator` 3c) — the same observed-in-the-run reading, lighter\nconsequences. Its failures already fail Step 4's vitest run. Find it by name, `route-targets.test.ts`\nunder `{appDir}`, and record `routeTargets` as one of:\n- `present` — its results appear in the output. Surface its `uncheckable` count.\n- `absent` — no such file.\n- `not-observed` — the file exists but vitest exited non-zero before per-file reporting. The\n  hard-tool failure carries the gate, as in the i18n branch.\n- **not collected** — the file exists but its results are not in the output while vitest exited 0.\n  This is a **gate failure**, exactly like the i18n branch above: summary\n  `route-target spec not collected: \u003Cpath>`, no `regenRequiredAt`, repaired by `verify-fix`. File\n  existence is not the test.\n\n**Only `absent` is reported rather than failed**, because the spec postdates many already-generated\napps. The next page this app generates scaffolds it (`foundation-generator`\nchecks per app, not per page); `fm-gen {page} --force` does it now. Say so in the report and name\nthe command.\n\n### Step 4b: Lint (hard) & format (advisory)\nFollow CLAUDE.md → \"Lint & Format Gate\" (detection \u002F scaffold-if-flag-on \u002F skip-if-deps-missing).\n- **ESLint — hard.** `npx eslint . 2>&1`. Exit ≠ 0 is a gate failure. `skipped` (config absent &\n  `eslintTemplate: false`, or deps missing) does not fail the gate.\n- **Prettier — advisory.** `npx prettier --check . 2>&1`. Exit ≠ 0 is recorded as a warning only;\n  it never blocks `verified`. Surface the unformatted file list and suggest `npx prettier --write .`.\n\n### Step 4c: Design-token traps (advisory — `templates\u002Fvisual-parity-checklist.md`)\nThe computed-value parity probe catches a mis-resolved Tailwind token, but it runs later and is\nskipped\u002Fblocked exactly where clusters and blocked pages ship — so surface the **known** traps here,\nat the first gate, where they are cheap to fix. Grep this page's generated files (`tracker.json`\n`sourcePaths[]` — never the legacy tree) for the enumerated trap literals:\n\n```sh\ngrep -nE '\\brounded-lg\\b|\\bfont-inherit\\b|\\bborder-[trbl]-solid\\b' -- \u003CsourcePaths...> 2>\u002Fdev\u002Fnull || true\n```\n\nReport each hit `file:line · \u003Cliteral>` as an **advisory warning** (like Prettier — it never sets\n`verify-failed` or blocks): `rounded-lg` computes 16px in this repo (use `rounded-[8px]` for a bespoke\nlegacy radius), and `font-inherit` \u002F per-side border-style emit no CSS in Tailwind v4. Point at the\nchecklist's \"Design-token traps\" section and the page's `style-spec.json` computed value. A project's\nown `docs\u002Fmigration\u002F**\u002Fcss-parity-checklist.md`, if present, may list more literals to grep. This is a\nreminder to check the computed value against the spec, not a verdict.\n\n### Step 5: Read and judge (evidence before claims)\nApply the 5-step gate: RUN → READ the full output (exit codes, error\u002Ftest counts) → VERIFY →\nCLAIM. Do not report a pass you did not observe. Capture the failing output verbatim if any step\nfails.\n\n### Step 6: Record\n\n**Tracker lock.** Take `docs\u002Fmigration\u002F.tracker.lock` around every `tracker.json` write below —\nafter the lock this step already holds, released right after the write (CLAUDE.md → Lock file). Write it per CLAUDE.md → Serialization.\n\nUpdate `tracker.json` (Read-Modify-Write). **Under `--regate`, apply Step 0a instead of every status\nwrite below** — the evidence writes are the same:\n- tsc + build + vitest + eslint all pass (or eslint `skipped`) **and** the i18n key-coverage spec is\n  `present` or `skipped` **and** the route-target spec is `present` or `absent` → `apps[app].pages[page].status = \"verified\"`, with `verifiedAt`, the tool\n  summary, the spec's `uncheckable` count under `i18nCoverage`, the route-target spec's state under\n  `routeTargets` (`{ \"state\": \"present\", \"uncheckable\": N }` or `{ \"state\": \"absent\" }`), and any\n  Prettier advisory under `formatWarnings` (all three are reporting surfaces for `fm-progress` and a\n  human reading the tracker — no gate branches on any of them; a Prettier advisory never fails\n  anything). **Clear `regenRequiredAt`**\n  — a passing gate means the full regeneration it records as owed is discharged, however it was\n  met. Also record\n  `apps[app].pages[page].gateEvidence.verify = { \"at\": \u003CISO-8601>, \"commit\": \u003Csha>, \"tree\": \u003Chash> }`\n  exactly as CLAUDE.md → \"Gate Result Accounting\" E prescribes — `commit` from\n  `git rev-parse --short HEAD` (`\u003Csha>+dirty` when `git status --porcelain` is non-empty), `tree` by\n  **running the script** once with `--manifest` and hashing its output — never by re-implementing\n  its records with an inline pipeline:\n\n  ```sh\n  REPO=$(git rev-parse --show-toplevel)\n  MAN=\"$REPO\u002Fdocs\u002Fmigration\u002F{app}\u002F{page}\u002Fgate-tree\u002Fverify.tsv\"\n  mkdir -p \"$(dirname \"$MAN\")\"\n  {pluginRoot}\u002Fscripts\u002Fgate-tree-hash.sh --manifest \\\n      --exclude docs\u002Fmigration\u002F{app}\u002F{page}\u002Fgate-tree\u002Fverify.tsv -- \u003Cwatch path>... > \"$MAN.tmp\"\n  TREE=$(git hash-object --no-filters -- \"$MAN.tmp\")\n  ```\n\n  **One execution produces both.** The script's aggregate is `git hash-object` of exactly these\n  records (its own construction), so hashing the manifest file yields the same `tree` — atomically.\n  Two separate executions could straddle a change and record a hash the manifest does not describe.\n  On a non-zero script exit, do not hash: exit 2 put `unverifiable` in the redirect (freshness axis\n  `unverifiable`), exit 1 is an error.\n\n  Watch paths are the union of the three axes CLAUDE.md → \"Gate Result Accounting\" F defines,\n  **minus every axis-1 entry under `{appDir}\u002Fe2e\u002F`**, and minus any untracked axis-1 entry\n  `git check-ignore -q` accepts (F) (the e2e carve-out: `fm-e2e` has not realized\n  them yet, and a re-run rewrites them);\n  resolve `packagesDir` and `monorepoRoot` in Step 0 and read the plan's `sharedDeps[]` here.\n  The redirect target must be the real repo root, not `{monorepoRoot}` — this skill runs from\n  `{appDir}`. Compare this hash with the pre-run hash from Step 2: if they differ, the watch paths\n  moved while the gate ran — record **no pass**, leave the status unchanged, discard `\"$MAN.tmp\"`,\n  and say to re-run. Only when the pass is recorded, promote the manifest — an overwritten\n  manifest beside a refused pass would pair the old recorded `tree` with a file list from a\n  different tree — and stage it with the tracker: the two are one piece of evidence, and\n  `fm-route` Step 1a blocks while either is uncommitted:\n\n  ```sh\n  REPO=$(git rev-parse --show-toplevel); MAN=\"$REPO\u002Fdocs\u002Fmigration\u002F{app}\u002F{page}\u002Fgate-tree\u002Fverify.tsv\"\n  mv \"$MAN.tmp\" \"$MAN\" && git add -- \"$MAN\" \"$REPO\u002Fdocs\u002Fmigration\u002Ftracker.json\"\n  ```\n\n  If `git add` fails (the index lock held by a concurrent page, an ignored path), say so: the pass\n  stands, the pair is unstaged, and `fm-route` Step 1a blocks until it is committed.\n\n  If it prints `unverifiable` (exit 2 — no watch paths resolved), record **no `tree`** and say so:\n  the page is unverifiable on this axis, which `fm-route` acknowledges rather than blocks. Never\n  store the word `unverifiable`, and never store a hash the script did not print. Keep `verifiedAt` for\n  backward compatibility.\n- any hard tool fails (tsc \u002F build \u002F vitest \u002F eslint) → `verify-failed`, with the failing summary.\n  A Prettier advisory alone never sets `verify-failed`.\n- **while `i18n` is configured**, the spec **exists but its results are not in the output, and no\n  hard tool failed** (eslint\n  `skipped` counts here exactly as it does in the pass branch above — it is neither a pass nor a\n  failure, and an app that has not installed the lint deps yet is the ordinary early state) →\n  `verify-failed`, with the failing summary `i18n key-coverage spec not collected: \u003Cpath>` and\n  **no `regenRequiredAt`** (Step 4a). Both halves are load-bearing: without the status the page\n  keeps its entry status and `fm-fix` — the remedy Step 7 names — refuses it; without the summary\n  in `tracker.json` the harness repair in `migration-fixer`'s `verify-fix` mode has nothing to key\n  on, since verify writes no report file.\n- the route-target spec **exists but its results are not in the output, and no hard tool failed**\n  → `verify-failed`, summary `route-target spec not collected: \u003Cpath>`, no `regenRequiredAt` — the\n  same handling and the same reasons as the i18n not-collected branch above.\n- the spec is **absent while `i18n` is configured** → `verify-failed` **and record\n  `regenRequiredAt`**. `fm-fix` cannot produce the spec (Step 7), and the next-step advisors\n  already override the `*-failed` wildcard to `fm-gen --force` when that field is set — this is\n  what puts them on the remedy this skill's own report names. `fm-gen` Step 5.3 clears it once a\n  full regeneration succeeds, and this skill's own PASS branch clears it too.\n\nRelease the lock.\n\n### Step 6b: Codex audit (advisory) — see CLAUDE.md → \"Codex Independent Audit\"\nIf `codexAudit` is enabled and this stage is in `codexAuditStages` (**absent → all seven**; the\nkey narrows coverage, it never means \"none\"), after the lock is released spawn\n`codex-auditor`\n(Agent) for the `verify` stage (params: `app`, `page`, `stage=\"verify\"`, `appDir`, `legacyDir`,\ngenerated code + test paths + the verify summary, `outPath = docs\u002Fmigration\u002F{app}\u002F{page}\u002Fcodex-audit.json`,\n`workingLanguage`) — an independent second opinion to Claude's own reviewers. Advisory — never\nchanges the page status. Surface its verdict below.\n\n### Step 7: Report\nIn `workingLanguage`: per-tool result (tsc \u002F build \u002F vitest \u002F eslint) with the evidence (exit code,\ncounts), the i18n key-coverage result (`present` + `uncheckable` count \u002F `absent` \u002F `not collected` \u002F\n`not-observed` \u002F `skipped`), the route-target spec result (`present` + `uncheckable` count \u002F\n`absent` with its remedy \u002F `not collected` \u002F `not-observed`), the\nPrettier advisory if any, and the Codex audit verdict (advisory). Next step: on pass →\n`\u002Ffrontend-migration-plugin:fm-cascade {page}` when the page injects markup it does not author (CMS\nrich text, i18n values containing HTML, editor output — the case no element-indexed style spec and no\njsdom test can cover), otherwise `\u002Ffrontend-migration-plugin:fm-e2e {page}`; on fail →\n`\u002Ffrontend-migration-plugin:fm-fix {page}`\n— **except the absent i18n key-coverage spec** (Step 4a), whose remedy is\n`\u002Ffrontend-migration-plugin:fm-gen {page} --force`. `fm-fix` cannot produce that spec: its\n`verify-fix` mode re-runs tsc\u002Fbuild\u002Fvitest\u002Feslint, all of which pass, so it would report a\nsuccessful fix, set the page back to `generated`, and land on this same failure again.\n\n**Under `--regate`** the next step follows the evidence, not a status: on a pass,\n`\u002Ffrontend-migration-plugin:fm-e2e {page} --regate`; on a failure,\n`\u002Ffrontend-migration-plugin:fm-fix {page} --mode review --findings \u003Cfile>` with the failure as the\nfinding (then re-gate), or `fm-route {page} --revert` to take the page back to legacy.\n",{"name":48,"description":49,"allowed-tools":50,"argument-hint":51,"user-invocable":52},"fm-verify","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.","Read, Write, Glob, Grep, Bash, Agent","\u003Cpage> [--regate] [--app pc|mobile|hana]",true,"main","99f07e592261c66756a2927d0440fc5fef950507",".claude\u002Fskills\u002Fecc\u002Fquarkus-tdd","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile","2026-11-08 20:29:14",{"source":8,"skillName":48,"commands":60,"prompt":70,"zipAvailable":52},[61,64,67],{"tool":62,"command":63},"npx","npx skills add sakamoto-family-smile\u002Fagent_monorepo --skill fm-verify",{"tool":65,"command":66},"bunx","bunx skills add sakamoto-family-smile\u002Fagent_monorepo --skill fm-verify",{"tool":68,"command":69},"pnpm","pnpm dlx skills add sakamoto-family-smile\u002Fagent_monorepo --skill fm-verify","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fecc\u002Fquarkus-tdd\u002FSKILL.md",[],[73,105,113,133,156,183],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":85,"publishedAt":43},"01M6RW50THEFSKK42YNR8XFZA1","remotion-video-creation","Best practices for Remotion - Video creation in React. 29 domain-specific rules covering 3D, animations, audio, captions, charts, transitions, and more.","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fecc\u002Fremotion-video-creation\u002FSKILL.md",[79,82],{"categoryNo":80,"categoryName":81,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":83,"categoryName":84,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体",[86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,32],"Video","remotion video","remotion video creation","creation","Remotion","Charts","Captions","Audio","3D","Composition","Animation","best practices","more","animations","domain-specific","domain","three","Rules","Lottie",{"skillNo":106,"name":107,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":110,"publishedAt":43},"01M6VCJ23NPECPSZJKGY691F75","hotcook-recipes","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002Fhotcook-agent\u002Fdata\u002Fskills\u002Fhotcook-recipes\u002FSKILL.md",[],[111,112],"hotcook recipes","recipes",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":127,"publishedAt":43},"01M6VCHHE00X5XHSDRD1KH1BW2","code-helper","Code review and assistance skill","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002Fagent-system-2\u002Fskills\u002Fcode-helper\u002Fskill.md",[119,122],{"categoryNo":120,"categoryName":121,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":123,"categoryName":124,"taxonomyType":125,"taxonomyTypeDesc":126},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[128,129,130,131,132],"code helper","helper","code","code review","review",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":137,"categories":138,"keywords":145,"publishedAt":43},"01M6VCH3Q31A20H6SQ1H0J7JB2","research-assistant","Web research assistant skill using Brave Search MCP","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002Fagent-system-1\u002Fskills\u002Fresearch-assistant\u002Fskill.md",[139,142],{"categoryNo":140,"categoryName":141,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000021","资料检索与研究",{"categoryNo":143,"categoryName":144,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[146,147,148,149,150,151,152,153,154,155],"research assistant","research","assistant","MCP","web","search","brave search","web research","brave","web research assistant",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":166,"publishedAt":43},"01M6VCGZZGPNVJSCZ1JTMNZAHY","x-api","X\u002FTwitter API integration for posting tweets, threads, reading timelines, search, and analytics. Covers OAuth auth patterns, rate limits, and platform-native content posting. Use when the user wants to interact with X programmatically.","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fecc\u002Fx-api\u002FSKILL.md",[162,165],{"categoryNo":163,"categoryName":164,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":123,"categoryName":124,"taxonomyType":125,"taxonomyTypeDesc":126},[167,168,169,26,170,171,32,172,173,174,175,176,177,178,179,36,180,181,151,182],"x api","api","with","limits","rate","threads","reading","native","posting","platform","patterns","api integration","twitter","auth","analytics","OAuth",{"skillNo":184,"name":185,"nameZh":6,"description":186,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":187,"categories":188,"keywords":190,"publishedAt":43},"01M6VCGVX6DGB1FKTA53QBBCQB","workspace-surface-audit","Audit the active repo, MCP servers, plugins, connectors, env surfaces, and harness setup, then recommend the highest-value ECC-native skills, hooks, agents, and operator workflows. Use when the user wants help setting up Claude Code or understanding what capabilities are actually available in their environment.","https:\u002F\u002Fgithub.com\u002Fsakamoto-family-smile\u002Fagent_monorepo\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fecc\u002Fworkspace-surface-audit\u002FSKILL.md",[189],{"categoryNo":143,"categoryName":144,"taxonomyType":20,"taxonomyTypeDesc":21},[191,192,193,194,149,195,196,130,197,198,199,200,36,201,202,203,204,174,205,26],"workspace surface audit","workspace","audit","hooks","workflows","connectors","capabilities","harness","repo","environment","up","harness setup","active","env","value"]