Canvas skill generated from one source manifest with drift check
Discovered from README cross-links · yesterday
One manifest renders the canvas skill folder and fails CI on any byte drift.
What they did
The author had a split-brain problem: the internal canvas agent received a 542-line system prompt, a style guide, a vocabulary and a contact sheet on every turn, but agents reaching canvas-mcp from T3 Code, Claude Code or Codex got none of it. Those external agents drew boards that violated the very rules the server lints against. Rather than duplicate the guidance by hand, they made the skill a build artifact. A new CLI subcommand, `bun packages/canvas-mcp/src/cli.ts guidance --write`, writes the whole `packages/canvas-mcp/skills/canvas` folder: a hand-written SKILL.md carrying the workflow and rules, references rendered from the layout-editor prompt, the state grammar, the aesthetic topic, the four guidance topics and the visual patterns, the contact sheet PNG, and a snapshot.json holding a sha256 per source. A single source manifest in canvas-agent feeds both snapshot.json and the `canvas_guidance` snapshot id, so the skill's own compare step can detect staleness. A companion `guidance --check` mode fails on any byte difference, including a missing or hand-edited SKILL.md. The work stacks on canvas PR 12, so the generated folder already carries the tenth visual pattern and the moved lints. SKILL.md frontmatter writes metadata as indented lines because the agent-config sync parser requires that shape. The SKILL.md names `canvas_check`, which lands in the separate canvas-create-check PR, and `canvas.link` in agent-config ships in its own PR. The prompt stays in the kernel catalog until wave 3 moves it. Review ran through sol-loop: two rounds with GPT 6.1 Sol, approved at high confidence. Built with Claude Opus 5.5 and Claude Fable 5.1 in T3 Code.
How it went
The skill folder is now reproducible from one manifest, and CI catches drift in either direction: a stale generated file or an edited SKILL.md both fail `guidance --check`. External agents get the same rules the server lints against, closing the gap that produced invalid boards. Review passed at high confidence after two sol-loop rounds. The change is stacked and depends on sibling PRs for `canvas_check` and `canvas.link`, so it is not standalone-mergeable yet.
Worth knowing
The SKILL.md is hand-written, so it is only partly generated; edits to it must be mirrored back or `--check` will fail. The frontmatter's indented-line format is dictated by the agent-config sync parser, not chosen freely. `canvas_check` and `canvas.link` live in separate PRs, so the skill references tooling that may not exist on the target branch. The prompt remains in the kernel catalog until wave 3, leaving a temporary duplicate source of truth. The post does not document the manifest schema or how the contact sheet PNG is regenerated.
Wiring
Entry point is packages/canvas-mcp/src/cli.ts, invoked with bun. The source manifest lives in canvas-agent and is the single input for two consumers: the generated snapshot.json (sha256 per source file) and the `canvas_guidance` snapshot id used by the skill's compare step. `guidance --write` reads the manifest plus the layout-editor prompt, state grammar, aesthetic topic, four guidance topics, visual patterns and contact sheet PNG, then emits packages/canvas-mcp/skills/canvas with SKILL.md, references/, the PNG and snapshot.json. `guidance --check` re-renders in memory and diffs bytes against disk, failing on any mismatch. SKILL.md frontmatter uses indented lines to satisfy the agent-config sync parser. The branch stacks on canvas PR 12 (tenth visual pattern, moved lints); `canvas_check` arrives via the canvas-create-check PR and `canvas.link` via an agent-config PR. The kernel catalog keeps the prompt until wave 3.
Try it yourself
In this repo, add a `guidance` subcommand to packages/canvas-mcp/src/cli.ts with two modes. `guidance --write` should render the skill folder at packages/canvas-mcp/skills/canvas from a single source manifest: a hand-written SKILL.md (workflow and rules, frontmatter metadata as indented lines), references rendered from the layout-editor prompt, the state grammar, the aesthetic topic, the four guidance topics and the visual patterns, the contact sheet PNG, and a snapshot.json with a sha256 per source. The same manifest must also feed the `canvas_guidance` snapshot id so the skill's compare step can detect staleness. `guidance --check` must exit non-zero on any byte difference, including a missing or edited SKILL.md. Wire it into CI. Do not duplicate the prompt text by hand anywhere.