OpenCode plugin for automated quality gate evaluation via test baselining. Ships two skills and two slash commands for use under any dot-agents-compatible agent (Claude Code, OpenCode, etc.); OpenCode-specific bindings are layered on top.
bun run check # TypeScript type check (may show tsconfig warnings in dev env)
bun test # Run unit tests| Command | Description |
|---|---|
/test-baseline init |
Grill for tiers, generate testing-protocol.md, capture first baseline (BL-001) |
/test-baseline eval |
Compare current tests against baseline; auto-updates the baseline when PASS + thresholds exceeded (DEFAULT) |
/test-baseline update |
Manual escape hatch: re-baseline on request — accept a FAIL's new metrics, force a fresh baseline, or approve inspected numbers |
/regression-check |
Answer quality questions (proactive or reactive) |
Two-skill system:
test-baselining— Runs tests, captures metrics, compares against baseline; builds the consumer's protocol + baseline oninitregression-checking— Interprets results, answers quality questions, emits decision signals for agents
Asset structure:
skills/test-baselining/
├── SKILL.md
├── refs/ # Bundled reference assets — non-authoritative guidance
│ ├── source-controls.md # Always-relevant: VCS discovery + change-detection commands (git, Mercurial, Subversion, Pijul, Fossil, **Unity VCS**, Perforce, Bazaar, Darcs)
│ ├── backends-ref.md # Init-only: backend-toolchain map and tier-grill scaffolding (C#, JVM, Go, Rust, Python, Node, Elixir, …)
│ └── frontend-refs.md # Init-only: frontend-stack map and tier-grill scaffolding (React, Vue, Svelte, Angular, Solid, **Aurelia 2**, Lit, Ember, HTMX, …)
└── templates/
├── testing-baseline.xml # Baseline XML template (adapted to consumer tiers on init)
└── testing-protocol.md # Threshold/pass-fail criteria template (tailored on init)
skills/regression-checking/
└── SKILL.md # Loads test-baselining, reads protocol for thresholds
commands/
├── test-baseline.md
└── regression-check.md
manifest.json # Optional-dependencies declaration (optionalDependencies)
Install model — dot-agents universal, OpenCode-extras on top:
- Universal install —
src/plugin.ts→src/installer.tscopies skills, commands, and agents to a dot-agents layout (SKILL.mdper skill folder). Other agents consume them directly. - OpenCode accommodation — The harness additionally registers the plugin in
opencode.json, sets theagent.task.permission.skillallowlist for both skills, and migrates a rootopencode.jsonto.opencode/opencode.jsonwhen present. OpenCode'sloadSkill({ name })tool resolves skills through the same layout.
Skill bodies stay agent-agnostic. OpenCode-specific bindings live in a tail section of each SKILL.md and in the command frontmatter (a command-specific subtask: false for /test-baseline so it stays in the main conversation, true for /regression-check so it spawns a subagent). Commands no longer pin an agent, so each runs under the current agent.
After /test-baseline init, two files appear at the consumer project root:
| File | Purpose |
|---|---|
testing-protocol.md |
Workflow stages, thresholds, pass/fail criteria — tailored to this consumer's tiers (code or non-code) |
testing-baseline.xml |
Baseline metrics and changelog (BL-001, BL-002, …) |
init grills the user for the actual tier set (code: toolchain per tier; non-code: repeatable verification procedures) and adapts both files to match. The shipped XML/Protocol templates are starting points, not the protocol.
File-location rule: skills locate these files at the consumer's source-control working-tree root, falling back to cwd. The VCS-agnostic lookup table lives in refs/source-controls.md (bundled with test-baselining). Never invent a path; warn if found elsewhere (e.g. a monorepo subpackage or a Unity Packages/com.<vendor>.<name>/).
- New command: Create
commands/<name>.mdwith a command-appropriatesubtask(falseto run in the current agent's main conversation, e.g./test-baselinefor its grilling flow;trueto spawn a subagent, e.g./regression-check) (OpenCode-specific — ignored by other agents). The body typically loads the corresponding skill.
New skill: Create skills/<name>/SKILL.md with required frontmatter (name, description). Use a templates/ subdirectory for files that should be copied to consumer projects. Body must be agent-agnostic; put any OpenCode-specific bindings in a tail ## OpenCode section.
Skill reference pattern:
!`tool loadSkill({ name: "skill-name" })`- Baseline markers use
BL-NNNformat (zero-padded, e.g.,BL-001) - Changelog is append-only and FIFO-pruned to 10 entries
- Changelog auto-generates summaries based on which thresholds were exceeded — build-artifact deltas are first-class in the summary, never buried under test deltas
regression-checkingdelegates totest-baseliningand readstesting-protocol.mdfor threshold interpretation- Commands do not pin an agent; the frontmatter
subtaskdrives routing —falsekeeps the command in the current agent's main conversation,trueforces a subagent (OpenCode-only — other agents use their own routing) - Skill bodies are agent-agnostic; OpenCode bindings live in a tail section per skill
refs/is reference, not policy. Files underskills/<name>/refs/are bundled with the skill and copied to the consumer; the skill body consults them during guided flows (init,Locating the Consumer Files,Caching Logic) but they are explicitly non-authoritative — the consumer'stesting-protocol.mdis the truth once it is written.source-controls.mdis always-relevant;backends-ref.mdandfrontend-refs.mdare init-only.- Skills are VCS-agnostic at the body level. Git-specific wording is a stand-in; the lookup table lives in
refs/source-controls.mdand the agent consults it for the consumer's actual source control. Coverage: Git, Mercurial, Subversion, Pijul, Fossil, Unity VCS (Unity Version Control / Plastic SCM), Perforce, Bazaar, Darcs. - Skills are backend-language and frontend-framework agnostic at the body level. Stack-specific guidance lives in
refs/backends-ref.mdandrefs/frontend-refs.mdand is used only duringinit— once the user configures their protocol, the references have no bearing. - Build artifacts are part of every eval and update. Captured per-tier (file count, total MB, build time, gzipped KB on critical files, lint-warning categories) in Stage 1, surfaced alongside test deltas in the eval output, and required for any
updatewrite — a baseline update that drops artefact fields is invalid. - Hooks never throw (ADR 0007). The Effect-first plugin definition (
src/plugin.ts) wraps its entire effect body so any failure degrades to a console warn naming the exact remediation (bunx … install, plus the~/.cache/opencode/npm/<name>@<version>dir to clear for cache rot); the effect's error channel staysnever, so OpenCode still launches. Hard errors stay CLI-only; the effect never auto-deletes the cache (races in-flight installs). Registration detection (src/registration.ts,isPluginInConfigBase) is format-tolerant: bothopencode.jsonandopencode.jsoncare honored in the global config dir,.opencode/, and the repo root. - Installer recommendations are non-blocking. The installer (
src/installer.ts#detectAurelia,detectOptionalSkills) appends advisory messages toInstallResult.recommendationsafter a successful install when a known stack or optional skill is detected.detectAureliais project-driven (looks atpackage.json);detectOptionalSkillsis environment-driven (probes<configBase>/skills/<name>/). Recommendations suggest the right install path for the consumer's agent (OpenCode plugin config ornpx skills add/use) but never modify the consumer config autonomously. - Skill dependencies are advisory. A skill may document optional dependencies in its frontmatter (
metadata.optional-deps:) and chain to them at runtime vialoadSkill. The frontmatter fields are non-functional — no host honors them; they exist for human/agent readers. The machine layer for optional dependencies ismanifest.json(manifestVersion: 1; entries carryid,kind(skill|agent|mcp|plugin),description, and a typedsource— bundled path, external-skill repo, plugin npm spec, or MCP command-or-url), validated on read by the loader insrc/optional-deps.ts. The plugin never auto-installs dependencies. At install time the package's declarations are unioned byidinto the consumer-side<name>.manifest.jsonoptionalDependenciessection with per-dependency state:pending(declared, undecided),accepted, ordeclined(both sticky; revisitable via the interactive menu). The merge is idempotent — existing accepted/declined state is preserved; a new or changed declaration (kindorsource) flips back topending, while description-only edits refresh the stored text without resetting state. When an optional dep is missing,detectOptionalSkillsderives its non-blocking recommendation from the manifest and appends it toInstallResult.recommendations(mirroringdetectAurelia). The runtimeloadSkillcall is best-effort and no-ops when the dep is absent. Currently the only declared optional dependency isgrillingfrommattpocock/skills(MIT), loaded bytest-baselining initwhen the consumer's tier set cannot be inferred from the source-control working-tree root.
Issues live as GitHub issues; use the gh CLI. See docs/agents/issue-tracker.md.
Default five-role triage vocabulary (needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix). See docs/agents/triage-labels.md.
Single-context: one CONTEXT.md and docs/adr/ at the repo root. See docs/agents/domain.md.