@cloverleaf/reference-impl
v0.8.6
Published
Reference implementation of the Cloverleaf methodology as Claude Code skills. Implements the Tight Loop (Implementer + Reviewer).
Downloads
1,520
Maintainers
Readme
@cloverleaf/reference-impl
Reference implementation of the Cloverleaf methodology as a set of Claude Code skills. Lets a user drive a Task from pending to merged with state, events, and feedback recorded in the repo under .cloverleaf/.
Implements Cloverleaf Standard v0.3.0 at L2 (Exchange) conformance.
Install
From this directory:
npm install # pulls @cloverleaf/standard + deps
./install.sh # symlinks skills into ~/.claude/plugins/cloverleaf/
# or:
./install.sh --project # local install into ./.claude/plugins/cloverleaf/Scope (v0.3)
v0.2 implements both paths of the Delivery track:
- Fast Lane (
risk_class: "low"): Implementer → Reviewer → Human Merge - Full Pipeline (
risk_class: "high"): Implementer → Documenter → Reviewer → (UI Reviewer ifsite/**changed) → QA → Final Approval
Agents
| Agent | Status | Mechanism |
|---|---|---|
| Implementer | Real | Subagent, code + tests on feature branch |
| Documenter | Real (v0.2) | Subagent, doc-only commits per file-path rules |
| Reviewer | Real | Subagent, read-only review of diff |
| UI Reviewer | Real (v0.5) | Playwright + axe-core + pixelmatch; multi-browser outer loop (chromium/webkit/firefox); axe-core runs on axe.browser engine only (default chromium); maxCombinations cap with per-route warnings |
| QA | Real (v0.2) | Per-package test runner via git worktree |
| Plan | Stub | Deferred to v0.3 |
| Researcher | Stub | Deferred to v0.3 |
Skills
/cloverleaf-new-task— scaffold a Task (auto-setsrisk_class)/cloverleaf-implement— run Implementer/cloverleaf-document— run Documenter (new in v0.2)/cloverleaf-review— run Reviewer/cloverleaf-ui-review— run UI Reviewer (new in v0.2)/cloverleaf-approve-baselines— human baseline-approval gate; clearsbaselines_pendingand advancesui-review → qa(new in CLV-19)/cloverleaf-qa— run QA (new in v0.2)/cloverleaf-security-review— Security Reviewer: deterministic secret scan + LLM vulnerability judgment; runs whensecurity_classishigh/cloverleaf-merge— human gate (branches on state)/cloverleaf-run— orchestrator (dispatches byrisk_class)/cloverleaf-release— publish a new@cloverleaf/reference-implrelease; runs pre-flight checks then executesgit tag -a/git push origin main/git push origin <tag>/npm publish/gh release create; accepts[--dry-run] [--yes](new in CLV-63)
Configuration
Two JSON config files in config/ (overridable per consumer project):
config/ui-paths.json— glob patterns that trigger UI Reviewer (default:site/**)config/qa-rules.json— per-package test commands
Customizing for your repo
The package ships with cloverleaf-flavored defaults in config/. Your repo overrides any of them by placing a file of the same name at <repoRoot>/.cloverleaf/config/<name>.json. Consumer override is a full replacement — your file becomes the complete source of truth for that config.
Available overrides:
| Override file | Purpose |
|---|---|
| .cloverleaf/config/ui-paths.json | Controls detect-ui-paths — which diffs trigger the ui-review state |
| .cloverleaf/config/qa-rules.json | Per-package test commands for the QA agent |
| .cloverleaf/config/affected-routes.json | Rules for mapping diffs to site routes (UI Reviewer scope); includes contentRoutes for content-collection mapping |
| .cloverleaf/config/astro-base.json | Explicit Astro base path — avoids best-effort parsing of astro.config.* |
Example affected-routes.json override for a Next.js project:
{
"pageRoots": ["apps/web/app/"],
"globalPatterns": ["apps/web/components/**", "apps/web/styles/**"],
"routeScope": ["apps/web/**"],
"contentRoutes": {}
}Example astro-base.json:
{ "base": "/my-docs" }All overrides are read fresh on every skill invocation; no caching. Edit and the next /cloverleaf-run picks it up.
Known limitations
- Concurrent
/cloverleaf-runon the same repo may race on preview ports. - QA does not produce HTML reports (no
report_uri).
Prerequisites for UI Reviewer
The installer (install.sh) automatically runs the Playwright browser install step. If you need to install manually, run:
npx playwright install chromium webkit firefoxOn Linux, webkit additionally requires system-level dependencies. By default install.sh installs webkit deps only:
npx playwright install-deps webkitTo also install firefox system deps (enabling the full chromium + webkit + firefox browser matrix for the UI Reviewer), pass --with-cross-browser to the installer:
./install.sh --with-cross-browserThis runs npx playwright install-deps webkit firefox instead. When the flag is omitted, install.sh prints a note reminding you how to enable cross-browser support later.
Disk footprint: approximately 600–650 MB total across all three browsers in the default PLAYWRIGHT_BROWSERS_PATH location (~/.cache/ms-playwright/).
| Browser | Approx. size | |-----------|-------------| | chromium | ~300 MB | | webkit | ~150–170 MB | | firefox | ~150–180 MB |
To store browsers in a non-default location, set PLAYWRIGHT_BROWSERS_PATH before installing and before running the UI Reviewer skill:
export PLAYWRIGHT_BROWSERS_PATH=/mnt/data/playwright
npx playwright install chromium webkit firefoxSubsequent /cloverleaf-ui-review invocations reuse the cache — no re-download per run as long as PLAYWRIGHT_BROWSERS_PATH is set consistently.
Quick start — toy repo
cd examples/toy-repo
npm install
../../install.sh --projectIn a Claude Code session in that directory:
/cloverleaf-run DEMO-001Watch it walk the state machine, produce a branch cloverleaf/DEMO-001 with a multiply function + tests, and pause at the merge gate.
See CHANGELOG for the full release history and roadmap.
Branch topology
State commits (.cloverleaf/**) always land on main. Code commits land on a per-task feature branch named cloverleaf/<task-id>.
main: canonical audit trail. Every status-transition event, gate decision, and feedback envelope is committed here, in order.cloverleaf/<task-id>: code for one task. Branched from main; the Implementer agent lives here.
The skills handle the branch switching for you. After /cloverleaf-implement <TASK-ID> runs, you are back on main with the state updates committed; the cloverleaf/<task-id> branch holds the code ready for review. After /cloverleaf-merge, the audit trail reflects the merged state, and you push the code branch manually.
The Reviewer never switches branches. It reads files via git show and runs tests in a git worktree add sidecar to avoid clobbering main's .cloverleaf/.
Package layout
lib/— TypeScript library used by the CLI. State, events, feedback, IDs, paths. IncludesbuildBaselinePath(repoRoot, browser, slug, viewport)(lib/visual-diff.ts) for constructing canonical baseline paths under.cloverleaf/baselines/{browser}/.lib/ui-browser.tsexportsbuildBrowserEscalationFindingandapplyMaxCombinationsCap(used by the UI Reviewer prompt for per-engine escalation and combination-count capping).lib/ui-review-state.tsexportsreadUiReviewState,writeUiReviewState, anduiReviewStatePath— the baseline-approval sidecar API for.cloverleaf/runs/{taskId}/ui-review/state.json. The CLI exposeswrite-baseline <repoRoot> <taskId> <browser> <slug> <viewport> <sourceFile>as the safe write path for baselines; it enforces thebaselines_pendingguard and usesbuildBaselinePathinternally.lib/walker-config.tsexportsloadWalkerConfig()— reads~/.config/cloverleaf/walker.json(XDG-aware) for the user-levelmax_concurrentoverride; exposed viacloverleaf-cli walker-default-concurrency [--explain].lib/release-preflight.tsexportsrunPreflightChecks(repoRoot)— runs six blocking checks and two warnings, returning{ checks, version, tag, notes }; exposed viacloverleaf-cli release-preflight <repoRoot> [--json].lib/dag-overlap.tsexportscomputeOverlapEdges(tasks)andgetFirstSharedFile(taskA, taskB)— infers serialization edges fromscope.files_touchedand is used internally bysavePlanto augmenttask_dag.edgesbefore writing.lib/scope-check.tsexportsclassifyFiles(taskDoc, modifiedFiles, siblingScopes)— classifies branch-modified files intoown,contested, andextensionbuckets; exposed viacloverleaf-cli check-scope <repoRoot> <taskId> --branch <branchName>(prints JSON, exits 1 on missing branch/task doc) andcloverleaf-cli extend-scope <repoRoot> <taskId> --add <file>... --reason <text>(idempotently set-unions files intoscope.files_touchedand appends an audit entry to.cloverleaf/runs/plan/<PLAN-ID>/audit.jsonl).skills/— Claude Code skill markdown files.prompts/— Implementer/Reviewer subagent system prompts.examples/toy-repo/— standalone demo repo.tests/— Vitest suite.
Development
npm test # run the Vitest suite
npm run test:watchPlans vs RFC-direct tasks
Cloverleaf has two ways to get from an approved RFC to executed Tasks. Both are first-class; the right one depends on the size and shape of the work.
Plan-task (Discovery flow): Operator invokes /cloverleaf-discover. The Plan agent decomposes the RFC into a Plan with a task_dag; the operator approves the decomposition at task_batch_gate; tasks are materialised under the Plan; the walker drives them through Delivery. Use this when the work spans ≥3 related tasks AND there's value in reviewing the decomposition before any task materializes (the gate is a checkpoint, not ceremony).
RFC-direct task (skip the Plan layer): Operator invokes /cloverleaf-new-task --rfc=<RFC-ID> "<brief>". A single task is created with context.rfc set and parent absent — no Plan, no task_batch_gate. Use this for:
- Hotfixes after a Plan has delivered — a small bug or polish item surfaces after the Plan's tasks are all merged. Creating a new Plan for one task is pure overhead; an RFC-direct task is faster and equally trackable.
- Incremental RFC progress without batch decomposition — operator hasn't yet decided how to decompose the next chunk of work, but a single concrete task is clear. Create it now; defer the Plan formation until later (or skip Plans entirely if the work continues to arrive one task at a time).
Auto-advance: how the walker treats them
When the walker (/cloverleaf-run-plan) finishes a Plan's final task, it asks cloverleaf-cli rfc-tasks <repo_root> <RFC-ID> whether the parent RFC can also advance from approved to completed. The check considers BOTH sibling Plans AND RFC-direct tasks under the same RFC:
- An in-flight Plan (
drafting/gate-pending/approved) OR standalone task (any non-terminal state) blocks the RFC advance — there's still work pending under this RFC. - A delivered Plan (
completed) OR standalone task (merged) counts toward the at-least-one-delivered requirement — the RFC must have produced at least one successful piece of work to advance. - If all delivered work was rejected/escalated, the operator decides: abandon the RFC, re-decompose, or accept the RFC as not-shippable. The walker won't auto-advance.
Operator visibility
cloverleaf-cli rfc-tasks <repo_root> <RFC-ID> # compact JSON
cloverleaf-cli rfc-tasks <repo_root> <RFC-ID> --pretty # indented for humansReturns the RFC's status, all sibling Plans (with their child tasks), all standalone tasks, and a summary block with in-flight/delivered counts plus can_auto_advance_rfc. Pure read; no side effects.
The tradeoff to name
Skipping the Plan = skipping task_batch_gate. That's the right tradeoff for hotfixes (one task; no decomposition to review) and for one-task-at-a-time incremental work. It's the wrong tradeoff for a large multi-task scope where the human's review of the decomposition is the load-bearing checkpoint. Plans are a checkpoint, not ceremony.
Security review
The Security Reviewer (8th agent) runs when a task's effective security_class is high, off the automated-gates hub in both lanes — so it covers fast-lane backend work, not just full-pipeline UI work.
What triggers it. security_class (low/high, independent of the UI-keyed risk_class) is inferred at task creation from sensitive markers (keywords + paths) and re-checked against the actual diff at review time (defense in depth — a task whose brief never says "credential" but whose diff touches engine/exchange.py is caught). Override at creation with --security=high|low.
Two passes. (A) a deterministic secret scan (cloverleaf-cli secret-scan) over the diff's added lines — cloud keys, tokens, PEM headers, credentialed connection strings; (B) an LLM judgment pass reasoning about injection, broken authz, unsafe deserialization, SSRF, missing input validation, weak crypto.
Routing. Findings merge into one feedback envelope; the max severity sets the verdict — any blocker (e.g. a leaked credential) → escalated (a human must review); error/warning → implementing (the Implementer fixes); clean → automated-gates → onward.
Customizing. Both pattern sets are consumer-overridable: .cloverleaf/config/security-paths.json (sensitive paths + keywords) and .cloverleaf/config/secret-patterns.json (secret regexes + placeholder excludes).
Mechanical enforcement (v0.8.1+). As of v0.8.1, the security-review state is mechanically enforced via the security_gate annotation on the Standard 0.7.1 state machine. advance-status re-runs classify-security on every guarded transition and refuses bypass attempts with exit code 2, naming the required recovery action (advance to security-review, run the Security Reviewer, write a pass verdict, then retry). This is a belt-and-suspenders complement to the orchestrator prose — the CLI enforces the invariant even if the driving LLM omits the bookkeeping step.
License
MIT — see ../LICENSE.
