AGENT SKILL

cl_async-task-ux

Use when adding a long-running background task to Canary Lab (anything that shouldn't block a REST request or the UI) — coverage generation, port-ification, spec/eval generation.

适用职业设计师
使用场景测试与质量
License 许可
MIT
最近更新
2026-11-05
Stars
★ 4
Forks
0

01 前言 Front Matter

name
cl_async-task-ux
description
Use when adding a long-running background task to Canary Lab (anything that shouldn't block a REST request or the UI) — coverage generation, port-ification, spec/eval generation.

03 SKILL.md 正文

Canary Lab Async-Task UX

Long-running work (agent runs, multi-second generation, double-boot verification) must NOT block a REST handler or freeze the UI. Canary models it as a background job: start returns immediately, the job persists to disk, the UI/MCP poll it, and a server restart recovers it. Get this contract right by copying an existing impl — don't invent a new lifecycle.

Reference implementations

Subsystem Store Runner / lifecycle
Verified Coverage jobs apps/web-server/src/features/coverage/logic/coverage/jobs/store.ts …/jobs/runner.ts (startCoverageJob)
Port-ification apps/web-server/src/features/portify/logic/runtime/store.ts …/portify/* + src/features/portify/routes/portify.ts

Coverage jobs are the smallest complete example — read those two files first.

The five-part contract

  1. Non-blocking. The start endpoint validates input, creates a running manifest, kicks off the work detached (no await on the driver), and returns promptly with the manifest. Coverage returns 202; Portify currently returns 200. The driver streams progress into the manifest and flips it to done / failed when it settles.
  2. Persistent. State lives in a file-backed store (<logs>/<kind>/<id>/…json
    • an index.json), never only in memory. The coverage store uses the shared FileBackedTaskStore; its save() writes atomically (tmp + rename) then emits a changed event (the WS/poll push point). Reads come straight off disk so a fresh process sees history.
  3. Recoverable. On server boot, call store.reconcileInterrupted(now) to flip any job left running by the dead process to aborted — otherwise it shows as live forever AND wedges the single-flight lock. Wire this next to the other store reconciles in server.ts.
  4. Re-openable. Status is a pure read of the manifest by id plus a list endpoint (GET /api/coverage/jobs/:jobId and GET /api/features/:name/coverage/jobs for coverage; GET /api/portify/:workflowId and GET /api/portify for Portify). The dialog/pill re-attaches to a running job by polling that id — closing the UI never kills the work.
  5. Server-side single-flight. The guard is on the START path, keyed on the real identity (e.g. feature + kind): store.activeFor(...) → throw a typed conflict (409). UI disabling is cosmetic, never the guard — two tabs, an agent, and the UI all hit the same on-disk index, so the server must be the lock.

Dual-surface parity

Every async capability ships on BOTH the UI (REST) and MCP, against the same store (see cl_add-mcp-tool). Start + poll + list at minimum; accept/reject-style follow-ups if the job parks for human input. MCP tools may construct a fresh store over the same logsDir — the lock is the on-disk index, not the instance.

Common mistakes

Mistake Consequence
await-ing the driver in the start handler Request blocks — the whole point is lost
Single-flight enforced only by disabling the button A second tab / an agent / a restart races a duplicate job
Skipping reconcileInterrupted on boot Crashed jobs show as live forever and hold the lock
In-memory-only state A restart loses history and re-openability
Non-atomic manifest writes A crash mid-write corrupts the job; readers throw

04 同仓库更多 Skills

ferterahadi
ferterahadi/canary-lab

off-by-one

暂无简介

测试与质量Skill与智能体开发
★ 4
ferterahadi
ferterahadi/canary-lab

multi-failure-cascade

暂无简介

测试与质量Skill与智能体开发
★ 4
ferterahadi
ferterahadi/canary-lab

broken-delete-contract

暂无简介

律师与法务测试与质量Skill与智能体开发
★ 4
ferterahadi
ferterahadi/canary-lab

canary-lab

Use when the user wants Canary Lab to take a product repo end to end — "test this app", "onboard this repo", "run a flight", "evaluate what I just built" — through the flight pipeline (start_flight / get_flight / respond_flight_checkpoint over MCP). One conducted pipeline continues a configured suite or takes bare repo(s) to a green, covered, healed run and publishes a downloadable Report; Parallel setup continues as Canary-owned background work. Use a focused skill only when the user asks for that single capability without asking for a Flight or /canary-lab.

测试与质量Skill与智能体开发
★ 4
ferterahadi
ferterahadi/canary-lab

canary-lab-verify

Use when verifying a Canary Lab feature against a RUNNING target — a deployed environment ("verify checkout on staging", "run the saved verify config", "check the deployed app") or a locally booted app ("verify a running app") — through the verify MCP tools (list/get/create/update_verification_config, boot_services, execute_verification, get_verification_result). No heal loop. For run + heal use canary-lab-run; for end-to-end onboarding use canary-lab (flight).

测试与质量Skill与智能体开发
★ 4
ferterahadi
ferterahadi/canary-lab

canary-lab-run

Use when running or healing an EXISTING Canary Lab feature locally — "run <feature>", "fix the failing run", "rerun 7cvh", "drive the heal loop" — through the repair MCP tools (start_run, wait_for_heal_task, signal_run, get_heal_context, pause_run, cancel_heal, abort_run). Fix failing runs by editing app/service code, not tests. For end-to-end onboarding of a new repo use canary-lab (flight); for deployed-environment checks use canary-lab-verify.

开发工程师测试与质量Skill与智能体开发
★ 4