canary-lab-author
Use when creating or extending a Canary Lab feature by hand — "create a feature for X", "add test cases to <feature>", "capture the env files", "switch the feature's branch" — through the author MCP tools (create_feature, capture_feature_env_files, write_envset, start/update/apply_external_draft, get_feature_repo_status, checkout_feature_repo_branch). For docs/PRD/coverage use canary-lab-coverage; for full onboarding of a bare repo use canary-lab (flight).
- License 许可
- MIT
- 最近更新
- 2026-11-05
- Stars
- ★ 4
- Forks
- 0
01 前言 Front Matter
- name
- canary-lab-author
- type
- skill
- description
- Use when creating or extending a Canary Lab feature by hand — "create a feature for X", "add test cases to <feature>", "capture the env files", "switch the feature's branch" — through the author MCP tools (create_feature, capture_feature_env_files, write_envset, start/update/apply_external_draft, get_feature_repo_status, checkout_feature_repo_branch). For docs/PRD/coverage use canary-lab-coverage; for full onboarding of a bare repo use canary-lab (flight).
02 资源文件 1
- 参考文档agents/openai.yaml205 B
03 SKILL.md 正文
Canary Lab — Feature Authoring
MCP Invocation
Setup and the plugin expose one public Canary Lab MCP tool: exec (usually
rendered as mcp__Canary_Lab__exec). Every
Canary Lab tool name below is the exact command value, not a separate public
tool. For a feature-scoped command, replace both placeholders in this shape:
{"command":"<exact_tool_name>","arguments":{"feature":"<feature_name>"}}
This is the envelope shape, not every command's complete schema. Add the
fields that command declares inside arguments; call describe_tool when a
field is uncertain.
Never invent a wrapper verb such as learn or call, embed JSON in a command
string, or turn arguments into flags. Keep fields such as confirm: true inside
arguments. Use list_tools, search_tools, or describe_tool as the
command when discovery is needed. A deliberately selected focused or full
profile still exposes atomic tools for debugging; the setup-installed path is
compact + exec.
This client writes the specs; Canary Lab is the control plane and artifact
store. These tools arrive via the Canary Lab MCP server. If this client is
already connected (the plugin connects with compact), skip this step. To
configure the same connection manually: npx canary-lab mcp --profile compact.
Arguments
An invocation argument (/canary-lab-author <suite> — the Getting Started
guide's "Author Tests" card emits exactly this shape) is the name of an
EXISTING suite (feature) in the connected workspace. Follow the
extend-an-existing-feature path below — never create_feature for it,
and never rename it to dodge a collision.
Workspace Bootstrap
- Find the LIVE server first: read
~/.canary-lab/active-servers.json, which recordsprojectRoot,portandpidfor every UI that registered. A stopped server's entry LINGERS — the file is only rewritten when the next server registers — so an entry is a candidate, not proof: the health check below is what confirms it. One entry → that is your server and itsport. Several → take the one whoseprojectRootis the workspace the user means. None → fall back to~/.canary-lab/workspaces.json(Windows:%USERPROFILE%\.canary-lab\workspaces.json): one workspace → use it, several → ask which, none → ask the user to runnpx canary-lab setup. Do NOT start from a guessed port. - Then CONFIRM it is the right server:
curl -s http://127.0.0.1:<port>/mcp/healthand check thatprojectRootis the workspace you intended. A healthy response does not settle the question on its own — a stale UI left behind by a demo or a tarball smoke test answers a port just as convincingly as the right one, and that is how a flight ends up running in someone's throwaway workspace.projectRootmatches what you intended → continue and tell the user which workspace. It names a DIFFERENT workspace → this is the wrong server; go back to step 1 rather than adopting it. It is under a temp directory (/tmp,/private/var/folders,%TEMP%) → never auto-select it; those are throwaway demo workspaces, so use one only when the user names it explicitly. Only when no live server serves the workspace you want does one need starting. - If the health check fails, start
npx canary-lab uifrom the workspace in a visible long-running terminal; if this client cannot run long-lived commands, ask the user to runnpx canary-lab uifrom the workspace and confirm when it's up. - Do not reflexively call
list_featuresorlist_runsafter health. For random or new feature creation, callcreate_featuredirectly with a unique feature name; uselist_featuresonly to discover or choose an existing feature. - A healthy
/mcp/healthmeans the server is live. On the setup-installedcompactprofile, atomic names such asget_feature_coverageare deliberately absent fromtools/list; onlyexecis public. Callexecwith{"command":"list_tools","arguments":{}}before concluding the connection is missing. Only an unknown-tool error forexecmeans this session is not connected — ask the user to runnpx canary-lab setup --forceand reconnect/restart the client, then retry. Never drive/mcpwith a hand-written HTTP/JSON-RPC client (curl included; the health check above is the only direct HTTP use): a custom client bypasses client detection and reconnect handling.
Create or Extend a Feature
- Pick the path by what the request names:
- Extending an EXISTING feature ("author tests for <feature>", "add a test for the missing behavior"): do NOT call
create_feature— the feature and its skeleton already exist. To choose WHAT to test,get_feature_coverage(feature)names the untested / path-incomplete requirements (that IS the "choose a gap" step), andlist_feature_docs(feature)points at the requirement docs behind them. Author the new spec straight into<workspace>/features/<feature>/e2e/, and tag it with the requirement it covers —test('…', { tag: ['@req-R2'] }, …)— so the gap actually closes in the coverage ledger. - Creating a NEW feature: call
create_featuredirectly with a unique feature name. It creates the skeleton files and returns test-file rules, envset schema, and next-step tool hints. Do not calllist_featuresjust to avoid collisions; if the name you INVENTED already exists, retrycreate_featurewith a different unique name — but never rename away from a feature the user asked for (that is the extending path above).
- Extending an EXISTING feature ("author tests for <feature>", "add a test for the missing behavior"): do NOT call
- If the user asks to preserve existing
.env,.env.dev,application.properties, or similar repo config files, inspect the source repo enough to identify the files, then callcapture_feature_env_files. Do not paste secret values into chat; Canary Lab returns redacted previews only.write_envsetfills in or corrects individual envset values (it is confirm-gated). - Author or edit specs under
<workspace>/features/<feature>/e2e/— the Canary Lab WORKSPACE, not the product repo under test. Spec selection never depends on the envset. In the suite'splaywright.config.*, keeptestDir,testMatch,testIgnore,grepandgrepInvertas constant literals — never derived fromCANARY_LAB_MANIFEST_PATH,process.env, or the recorded env. A test that must not execute in some environment skips ITSELF at runtime:test.skip(process.env.VERIFICATION_ENV !== 'meta', 'needs the Meta sandbox'), reading the env from the envset's own values rather than the manifest. See Guardrails for why. - Specs must import:
import { test, expect } from 'canary-lab/feature-support/log-marker-fixture' - Call
start_external_draftwith a stablesession_idand a usefulconversation_name(do not passclient_kind— the bridge auto-detects it). This only creates a visible Canary Lab task so the user sees that this external agent session is authoring tests; it does not start an internal wizard agent. Carry thedraftIdit returns into every subsequentupdate_external_draft_stage/apply_external_draftcall for this draft. If it returnstype: "getting_started_busy", a Getting Started demo already owns the workspace — follow the active target it returns; do not start another workflow. - After
start_external_draftreturns, tell the user you are authoring tests and they can follow along live in the Canary Lab UI: the suite's Flight page shows this work on its Test authoring & coverage stage (that view is read-only while this client drives — it monitors, you act here). Continue writing specs locally, then callupdate_external_draft_stage(draftId, stage)as work progresses:scaffolding,authoring-tests,validating,ready,applied, orerror. - Call
apply_external_draftwithdraftId,confirm: true, andfiles: [{path, content}, …]for the externally authored files (omitfilesif you already wrote them directly under<workspace>/features/<feature>/e2e/— it then validates what's on disk), so Canary Lab validates and records the applied draft. Do not ask Canary Lab to spawn another Claude/Codex agent for MCP-created authoring. On a validation error, fix the named file and re-callapply_external_draft. get_feature_repo_status/checkout_feature_repo_branchinspect and switch the feature's bound repo branches when the user asks to test a different branch. The status also reports where the pinned branch stands against its upstream (upstreamSha,behindUpstream,aheadUpstream); when it is behind,update_feature_repo_branch(feature, repo, confirm: true)fast-forwards the checkout to the upstream tip so the next run boots the latest commit. It refuses — and changes nothing — when the checkout is dirty, detached, on another branch, or has diverged; report the reason and let the user reconcile rather than discarding their work. A repo declared withtrack: 'upstream'infeature.config.cjsis fast-forwarded automatically at every run start.
Envset source and target
Store actual values in the selected workspace at
features/<feature>/envsets/<env>/<slot>. A suite that reads .env normally uses
envsets/local/<feature>.env with target
$CANARY_LAB_PROJECT_ROOT/features/<feature>/.env. The envset file is the durable
source; the target is the temporary file the launcher and Playwright consume.
The runner applies it before startup and restores backed-up targets at teardown.
Verify that teardown also removes targets absent before the run, keeping new
suite .env targets absent at rest. If it does not, report or fix the lifecycle
gap within the authorized scope; preserve pre-existing user files.
Inspect each consumer before choosing a target. Never target .runtime/envsets,
the envset source directory itself, or a personal source checkout merely because
an existing environment variable points there. capture_feature_env_files
defaults an omitted target to sourcePath; pass an explicit consumer target when
importing values from elsewhere. Existing paths are evidence, not authority.
Never create pointer-only envsets that outsource their values to an unmanaged env file. Capture the actual values and update their launcher/configuration together. Keep separate slots for genuine file inputs (certificates, binary bundles, JSON) when their consumer requires that format; verify reference and target together. Do not flatten every suite into one slot or encode files as environment variables just for uniformity. For an all-suites request, inspect every suite and correct only bad mappings, preserving the working variants and existing values.
Verify source → target → consumer and teardown before declaring a migration done.
Keep secrets out of chat, logs, and commits. Do not invent .recovery trees or
duplicate credentials as a precaution; retain the original until its replacement
works, and let the runner manage its existing backup/restore lifecycle. The full
contract is also available through get_workflow_guide(workflow:"author").
Guardrails
- Write one variable declaration per statement, use descriptive names, and clearly separate setup, action, and assertions. Avoid comma expressions and nested conditionals. Draft acceptance splits ordinary grouped declarations and formats specs; it rejects syntax errors and comma expressions and reports nested conditionals for review. Preserve behavior while resolving any finding.
- Audit existing tests with
canary-lab test-readability <file-or-directory>; add--fixfor safe declaration fixes and formatting, or--rules-onlyto keep existing layout. Review the diff and rerun affected tests. Never weaken assertions or rewrite recorded run artifacts during cleanup. - Keep the same
session_idfor the whole conversation. - Test titles are read by non-engineers in the coverage ledger and exported
reports: write each as a plain-English sentence naming the user-visible
behavior —
user can reset their password after requesting a reset link, notPOST /reset-token returns 200. Keep a technical term only when it is the requirement's own vocabulary (an endpoint name in an API-contract requirement stays technical). - Canary Lab never writes the test body for external authoring — this client does.
- A suite declares ONE roster of tests, and every run of it declares the same
one. Playwright builds that roster by walking the suite with the config's
selection fields applied, before the first test starts, and that walk is the
run's evidence. A config that narrows it by environment does not hide tests
from a run — it deletes them from the record: a
metarun of a 45-test suite reports a 4-test suite, the other 41 absent rather than "not run", and two runs of one suite can no longer be compared.test.skip(condition, reason)keeps the roster whole; atestMatchfilter destroys it at the source. Canary Lab refuses both the draft that carries such a config and any run of the suite. - After authoring, the natural next steps live in sibling skills: map coverage (
canary-lab-coverage), run + heal (canary-lab-run), export the evaluation (canary-lab-export). Running the new test needsstart_run: on the setup/plugincompactconnection, invoke it as theexeccommand and followcanary-lab-run. On an intentionally narrow direct--profile authorconnection it is unavailable; reconnect withnpx canary-lab mcp --profile compactand then run.
04 同仓库更多 Skills
off-by-one
暂无简介
multi-failure-cascade
暂无简介
broken-delete-contract
暂无简介
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.
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).
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.