A bounded, hard-gated graph-engineered state machine, written as a skill — runs on any agent harness, tuned best for opencode so far: full skill, mini variant, and A/B benchmark harness
Overview
Vibeweaver doesn't make a model stronger; it makes the ability already there actually count. Restart opencode and ask for the work; the skill triggers on implement / modify / debug / deploy coding tasks (not on Q&A or pure consulting). Saying "strictly follow vibeweaver" at the start of the request makes triggering essentially certain. Plugins, optional extras, and the Windows path: Install. Give the human brain free rein and it runs on cognitive bias and after-the-fact rationalization. Science is the countermeasure we built for it: preregistration, blind review, lab notebooks, reproducibility. An LLM is the same kind of machine — brilliant at pattern completion, and just as good at making up its reasoning after the fact. Vibeweaver puts coding work under the same discipline: - Acceptance criteria are written before any action and cannot be relaxed mid-loop — preregistration.
README
Vibeweaver
Vibeweaver doesn’t make a model stronger; it makes the ability already there actually count.
Quickstart
git clone https://github.com/logandoo/vibeweaver
bash vibeweaver/vibeweaver/install.sh # mkdir -p + idempotent (cp -r breaks on missing parents / nests on re-run)
Restart opencode and ask for the work; the skill triggers on implement / modify / debug / deploy coding tasks (not on Q&A or pure consulting). Saying “strictly follow vibeweaver” at the start of the request makes triggering essentially certain. Plugins, optional extras, and the Windows path: Install.
Why it exists
Give the human brain free rein and it runs on cognitive bias and after-the-fact rationalization. Science is the countermeasure we built for it: preregistration, blind review, lab notebooks, reproducibility. An LLM is the same kind of machine — brilliant at pattern completion, and just as good at making up its reasoning after the fact.
Vibeweaver puts coding work under the same discipline:
- Acceptance criteria are written before any action and cannot be relaxed mid-loop — preregistration.
- Reviewers and fresh-context verifiers judge the diff and the evidence, never the implementation’s reasoning — blind review.
- Every hypothesis, diagnosis and falsification lands in an on-disk ledger, distilled into memory at task end — the lab notebook.
- Missing evidence blocks delivery mechanically — the publication gate.
None of this ages with model capability. The discipline stays no matter how strong the model gets — even the smartest person still reaches for pen and paper when the reasoning has to hold up.
A coding agent should be able to bring this discipline on its own, but opencode and Codex don’t ship it as a default: they hand you hooks and permissions, and leave the policy to skills and plugins.
Coding agents fail on real projects in familiar ways: they delete files, refactor code nobody asked them to touch, or break feature B while implementing feature A. Most of these are process failures, not capability failures: the agent doesn’t know what “done” means, so it declares victory without proof. It skips the verification it could have run. It forgets what the previous session learned, and drifts over long tasks.
A stronger model doesn’t fully fix this, and a longer prompt doesn’t either: at this point, LLM output is still probabilistic, and drift is nearly unavoidable. Most SOTA models already know the right method; they still have lapses. That is what Vibeweaver is for: when the output drifts, stop the model; when the approach is wrong, make it start over. With the context kept in order and negative verdicts from an external judge, the model usually knows how to correct itself. The skill fixes two things at once:
- The process: decompose the request, search for prior art, choose between at least two approaches, design before code, test first, verify against runtime evidence, review before shipping.
- The standard: what counts as evidence, who grades it, and what happens when it is missing.
It adds no capability; it removes the ways capability gets wasted. It has a floor, though: the model has to be able to remember the injected rules. The benchmarks below show both directions: the weakest model in the set loses ground under the full skill (it can’t follow the process, and the context flood makes things worse), while a capable model turns its existing ability into a perfect score once the discipline is enforced.
The enforcement is not a prompt. A gate plugin and an auditor plugin watch the
session and the files on disk; a missing artifact comes back as a failed tool call.
Prompts are suggestions; GATE-BLOCKED is not.
The project is opencode-only for now. A DeepSeek Harness port is released separately as vibeweaver-dsh. Codex already ships the relevant pieces (a Stop hook, Goals, an off-by-default memory pipeline); it just doesn’t wire them into an evidence loop by default, and this skill hasn’t been tested on it. Claude Code: haven’t looked at the code. Forks welcome.
How it works
Ask for a change in plain language. Before touching code, the agent decomposes the request, searches for prior art, and states the approach it picked. Logic-bearing code is written test-first.
When a change touches runtime behavior, the agent runs the app, captures
screenshots or video, and hands them to a verifier for grading; failures enter a
bounded fix loop (cap=5, stall=3×) with a diagnosis attached to every retry.
Before the final answer it runs the project’s artifact checker, writes what the
next session must know into memory/, and prints a completion table. The gate
plugin checks that the evidence exists; if it is missing, the agent’s next write is
blocked. None of this makes the model smarter; all of it makes the result
checkable.
What it does
- No test, no done. Every code change is followed by tests that actually ran, with evidence on disk: log files, screenshots, screen recordings, page audio. “It builds” is not evidence.
- Test-first, no exceptions. Logic-bearing code is written RED→GREEN: a failing
test first, its failure pasted into
tests/verification_log.md, then the minimal implementation. A test that passes on the first run proves nothing. Regression tests must complete the full revert-and-fail cycle before they count. - A trusted oracle, not self-certification. Only the project’s own tests, or
external ones, can certify a task. Generated tests must pass qualification first
(fail on the stub, pass on a known-correct solution, fail on a plausible wrong
one) and still count as weak evidence; self-written tests are the weakest. A
contract that isn’t visible in the spec becomes an open question, never an
invented interface. When a project exposes a deterministic checker
(
script/check.sh,tests/check.py, or thevw_check.pytemplate in APPENDIX §A11), that checker drives the loop. - A self-starting verification loop. The moment a change touches runtime
behavior, the agent enters
Act → Capture → Verify → Fix → Logon its own. The verifier is picked at task start by a behavioral probe (see the mm-sensor hookup): a multimodal model grades its own screenshots under a strict protocol, mm-sensor grades them independently, or DOM and log inspection carries the evidence. Video and audio are captured when the verifier supports them. - API-doc-driven backend tests. For backend-only changes the loop is: update
the API doc, audit doc↔code consistency once, write test cases from the doc (not
from the implementation), then run the httpx test→fix→test loop until everything
passes. Cross-endpoint changes additionally require real-HTTP workflow scenarios
with on-disk traces (
tests/workflows/*.trace.log); direct service-layer calls are not E2E and don’t count. - Script-only lifecycle. Builds and service start/stop/restart go through
script/scripts. Rawnpm run build,vite,npm start,uvicornare forbidden. Stop scripts use the.pid-file pattern;pkill -f "uvicorn"on a shared box kills your coworker’s service. - Research before code. The first action on any task is decomposing the problem (asking when anything is unclear, one question at a time) and searching the web (exa MCP + Context7) for prior art, evaluating at least two approaches. Skipped only for a trivial typo or config change. The philosophy: nothing new under the sun. If a genuine search turns up no precedent, the task is too novel to improvise.
- Project memory. opencode has no native memory system; every session starts with a fresh brain. Vibeweaver builds one from files and rules: an index plus topic files, trust tiers (⛔ Forbidden / ❌ Failed / ✅ Verified / ⏳ Unverified), and a fix state machine. Full mechanism below.
- Working memory between the log and the lessons. Append-only logs answer
“what happened”; curated
memory/answers “what is true about this project”. A task that spans iterations also needs “what holds right now”:tests/working_note.mdkeeps the live hypothesis ledger (confirmed / doubted / excluded / open), key file:line discoveries, this task’s dead ends and the next action — rewritten each update, read first on any resume, distilled intomemory/and deleted at task end (the deletion is machine-checked by the completion-time--finalrun). The gate plugin carries that ledger across context loss: the note is pushed into every compaction prompt, re-injected on the session’s first request after asession.compactedevent, and pointed to by a cue on the first gated write — deliveries counted in.vibeweaver/state.json(memoryDeliveries), with a harness-owned snapshot that keeps boundary delivery alive even if the note file itself disappears mid-task. - Memory that arrives at the moment it matters. A topic file can declare
triggers:path globs in its frontmatter; when the agent edits a matching file, the gate plugin injects a one-line cue into the tool result — even when the gate is red, even on the task’s very first write. Delivery is deterministic, because a memory consulted zero times is indistinguishable from no memory. Globs are capped (≤2**groups, ≤200 chars, no control characters) — memory text compiles to regex, so complexity caps are the injection boundary — and a glob whose literal prefix no longer exists fails the artifact check instead of silently never firing. - An outer loop for backlogs. Point it at a queue:
tests/backlog.json(one item, onepassesflag), an append-onlytests/progress.txtchronicle, fresh context per item, one small task per iteration, green-before-commit as the loop’s immune system, explicit stop signals (COMPLETE / BLOCKED / DECIDE / budget — exhaustion is a top-up, not a failure), supervised first and bounded unattended batches later.scripts/backlog_check.pyfails anypasses: truethat no executed-test line names. - Enforcement teeth, kept honest. The artifact checker lints the log itself
(a FAIL whose diagnosis is a placeholder is not an iteration); the session
auditor requires the completion-time
--finalrun to leave its log line (otherwise its checks never provably ran); the stall observer fires once per stall signature and re-arms on a new pass, because a warning that floods trains blindness. - Bounded loops. Every verification loop is capped at
cap=5iterations per sub-problem withstall=3×: the same criterion failing three times in a row means stop, change direction, record the dead end. - A loop-guard for degenerate output. When the model’s own generation runs
away — the same block repeating, a meaningless bare echo sequence
(
1,2,…,179,a,b,…,kf, with or without newlines), a counter wall (≥16 tail lines of identical shape whose digits step strictly +1), or a punctuation-only wall past 2 KB — the auditor plugin detects it from the text stream (reasoning parts included, on their own budget), interrupts the session, and posts a corrective prompt (once per episode, budgeted per session;VIBEWEAVER_LOOPGUARD=offturns it off). A per-turn ceiling (64 KB) backstops shapes no periodic detector can see. It watches a second channel too: tool calls. A model that announces a tool (“use Read now”) and then issues bareecho "…"narration markers instead of calling it is interrupted the same way (≥4 consecutive no-op bash calls); two more tool-channel detectors cover call storms — the identical call re-issued ≥4 times (identical-tool-run, canonicalized-args identity over distinct part ids) and one tool hammered ≥20 consecutive calls with varying arguments (tool-frequency). All channels keep independent episode budgets so one can never starve the other. - Honest coverage, and a second pair of eyes. The completion output carries a
[Coverage] criteria: N/M | unchecked: …line: what was checked is named with evidence, what was not checked is named too — an unchecked item can never be phrased as done, andUNVERIFIEDcells can’t be laundered intona. When the strongest green evidence is the agent’s own tests, a fresh-context verifier re-runs the checks without having seen the implementation reasoning. - Ceremony economy. Code and green tests land first; memory writes, review packages and decision prose are assembled at completion time from the one-line-per-iteration log. A budget check at each iteration keeps a time-boxed run converging on a deliverable instead of dying mid-ceremony, and safety rules stay resident while debugging/review protocols load only when their trigger fires.
- Action triage and state revision. Every planned step is tagged critical/exploratory/noisy before it runs; noise is revised, not executed. When evidence kills an assumption, the artifact that carried it is rewritten in place — an appended correction beside a stale plan keeps contaminating later decisions (the AEWM failure mode this guards against).
- Task classification, proportional paths. Before any action the change
set’s file kinds decide the class —
Class: CODE(logic-bearing source) >Class: CONFIG(config/scripts/CI, no control flow) >Class: DOC(prose and office assets), first match wins, uncertain goes UP. Each class gets its own path card: a prose edit keeps its acceptance criteria, iteration log and gate line, drops tests, capture loop, baseline and the 8-column table tona (reason)with a 3-column lite table in their place; a config change keeps its smoke checks and baseline; code changes are untouched. A gate with no named risk is process inflation, so docs update only on named drift (docs-drift: —), never because the flow says so. - A render gate for document deliverables. A shipped
report.docx,.xlsxor.pptxis verified the way doc tooling says it must be: render the pages, run layout QA, grade the page images —NO RENDER, NO DONE, in every task class. Authoring delegates to the specialist skills (readme-weaver for README prose, docx/xlsx/pptx-manipulation to write, office-docx to verify, office-mcp to fall back on); a missing toolchain degrades to a flaggedrender: N/A ()and anUNVERIFIED-layoutmark, never a quiet done. Macros and embedded scripts are found by a named check at delivery time and escalate the task. - The whole SDLC, not one slice of it. New-project scaffolding with design docs first (FLOW / PAGE / DATABASE / BACKEND), config management, acceptance checklists, task-type routing (build / audit / deploy / ops / CLI-library / backlog outer-loop / feasibility spike), an 8-column completion table, and two enforcement plugins.
Install
git clone https://github.com/logandoo/vibeweaver
bash vibeweaver/vibeweaver/install.sh # Linux/macOS (mkdir -p + idempotent)
# Windows, from a clone of this repo:
vibeweaver\install.bat
Restart opencode. The skill triggers whenever you ask for a build, a fix, a debug session, or a deploy.
install.sh / install.bat also install the enforcement plugins (the gate and
the auditor). Installing them by hand:
cp ~/.config/opencode/skills/vibeweaver/vibeweaver-gate.js ~/.config/opencode/plugins/
cp ~/.config/opencode/skills/vibeweaver/vibeweaver-audit.js ~/.config/opencode/plugins/
The gate is the enforcement layer and the skill is the instruction layer; both work independently, so the skill runs fine without the plugins.
Both plugins are a single file each that supports opencode v1 (≥ 1.18.29) and
opencode v2 (≥ 2.0.0) at the same time: the module default-exports
{ id, server, setup }, v1’s loader calls server() for the v1 hook map, and
v2’s loader decodes { id, setup } and calls setup(ctx) for the domain-API
hooks. Same logic, same .vibeweaver/ state, same behavior on both generations.
Optional extras, in rough order of how much they matter:
- Playwright and mm-sensor: a designed pair. Without them the verification loop gets meaningfully weaker (self-grading instead of independent grading).
- ffmpeg (video transcode) and exa MCP + Context7 (research).
None are required for the skill to function.
Usage
Ask for the work in plain language (“add OAuth login”, “fix this 502”, “can we do X?”); the skill routes by task type. What lands on disk after a task:
| Artifact | What it proves |
|---|---|
tests/acceptance.md |
the stop condition, written before the work (> cap=5 stall=3× on the first line) |
tests/verification_log.md |
every capture→verify→fix iteration, each failure carrying a diagnosis |
| media evidence | screenshots / video / audio, graded by the verifier picked at task start |
memory/*.md |
what future sessions must know (forbidden approaches, verified fixes) |
With the gate plugin installed, a missing artifact blocks the agent’s next write
with GATE-BLOCKED (see the gate and the auditor);
VIBEWEAVER_GATE=off turns the gate off.
Repo layout
This repository contains three sub-projects:
| Directory | What |
|---|---|
vibeweaver/ |
The full skill; this README describes it |
vibeweaver-mini/ |
Small-model kit: a 1.7 KB deterministic loop (“run the checker, fix the first failure, repeat”) plus scripts/vw_check.py, a checker that prints a repair packet and refuses to run if the test set changed. Benchmarked on a 3B-active model: loop + real tests 4/4, loop + self-written tests 1/4; the oracle decides, not the prose |
vibeweaver-eval/ |
Benchmark rig: 16-task + flow A/B configs, grading scripts, raw runs, round reports |
Which one to pick: strong model → full skill (force-injected); weak instruction-following model → mini, always-on; very weak (~3B active) → mini plus the checker, force-injected.
The repo root also holds the skill’s own test machinery: verify_skill.py
(integrity check over the skill package), tests/ (self-test suite with pass/fail
fixture projects), and .github/workflows/verify.yml (runs both on every push,
Ubuntu / macOS / Windows). The skill is checked the way it demands projects be
checked.
Does it actually work?
Every table below is evidence for the claim at the top: the skill adds no ability; it changes how much of the existing ability gets delivered. All of them use the same three setup modes:
- baseline: no skill at all.
- available: the skill is installed and listed in
available_skills; the model decides whether to load it. Whether the model ever loads it is the trigger rate, listed per arm. - force-injected: the skill’s full text is pasted into the system prompt; the model has no choice.
How the eval is designed
The numbers come from one fixed, reproducible benchmark rig (vibeweaver-eval),
designed to make rounds comparable and hard to game:
- A fixed task set: the same 16 tasks for every per-model round (10 Aider polyglot
- 6 SWE-bench Lite real-repo issues), with the same prompts and scoring.
- Hidden-test grading: solutions are graded by tests the agent never sees: Exercism-style for polyglot, FAIL_TO_PASS + P2P regression guards for SWE-bench.
- Isolated arms: every arm runs in its own XDG config directory; the only difference between arms is the skill (or its absence). The no-skill arm is the control group; the rest are treatment arms.
- Gold-validated before admission: every SWE-bench instance must fail on base and pass on gold before it’s allowed into the set.
- Headless and scripted:
opencode run --auto, everything published: rig, configs, gold checks, raw runs, grading scripts. - Two skill generations. The per-model rounds below ran in Aug 2026 against the then-current 71 KB skill and 2.2–5.7 KB minis. Waves 6–7 (Sep 2026) re-ran the key comparisons against the slimmed 41.8 KB skill and the 1.7 KB deterministic mini kit; those numbers are closest to what you install today.
Before / after: qwen3.6-35b-a3b (the weakest model yet)
34.6B MoE with ~3B active params, GGUF Q5 quantized, llama.cpp. This is where the size→trigger rule breaks down at the low end:
| Arm | Pass rate (16 tasks) | Trigger rate |
|---|---|---|
| No skill (baseline) | 6/16 (37.5%) | — |
| mini, available | 6/16 (37.5%) | 0/10 |
| Full skill, available | 7/16 (43.8%) | 0/10 |
| mini, force-injected | 7/16 (43.8%) | — |
| Full skill, force-injected | 5/16 (31.3%) | — |
- Below a capability threshold the skill never gets loaded: the model never calls the skill tool (0/10 triggers for both mini and full).
- Force-injection is the only way in, and only the small version helps: the 5.7 KB mini was the one positive path (7/16 vs the 6/16 baseline, polyglot 4/10 against the 2/10 baseline), while the then-current 71 KB full skill was context poison (5/16, SWE-bench 1/6, five “no diff produced”, nine timeouts).
- Wave 6 found the shape that actually works for this model: not prose, a deterministic program. The 1.7 KB mini kit + the checker + the project’s real tests took it from 1/4 to 4/4 on the four tasks every prompt-only arm failed (12–36 checker runs per task, zero test tampering), while the same loop on self-written or unqualified generated tests stayed at 1/4. On a ~3B-active model the oracle decides, not the prose. Read that 4/4 as a capability probe (the checker saw the canonical tests), not as benchmark-valid coding.
- Wave 7’s 8-task subset A/B on this model: 4/8 before, 3/8 after, within noise; a text-only skill change is neutral here.
Before / after: qwen3.6-27B
| Arm | Pass rate (16 tasks) | Trigger rate |
|---|---|---|
| No skill (baseline) | 7/16 (44%) | — |
| Full skill (71KB), available | 6/16 (38%) | 0/16 |
| Full skill (improved description), available | 9/16 (56%) | 2/16 |
| Full skill, force-injected | 9/16 (56%) | — |
| mini, available | 10/16 (62.5%) | 10/16 |
This is the round that made the mini variant exist:
- mini beat even the force-injected full version (62.5% vs 56%) purely by getting loaded: a short rulebook the model actually reads beats a 71 KB masterpiece it never opens.
- Size drives triggering. 71 KB → 0/16, mini → 10/16.
Before / after: deepseek-v4-flash-0731
| Arm | Pass rate (16 tasks) | Trigger rate |
|---|---|---|
| No skill (baseline) | 11/16 (68.8%) | — |
| Full skill, available | 11/16 (68.8%) | 0/16 |
| mini, available | 11/16 (68.8%) | 12/16 |
| Full skill, force-injected | 14/16 (87.5%) | — |
A strong model already has the discipline natively, so mini becomes useless from this tier up. The full version’s gain starts to show, but the model will never load it on its own (0/16 available); the skill has to be force-injected into the context. The edge lives in polyglot: 8/10 vs 5/10.
Before / after: qwen3.8-27B
| Arm | Pass rate (16 tasks) | Trigger rate |
|---|---|---|
| No skill (baseline) | 13/16 (81%) | — |
| mini, available | 13/16 (81%) | 10/10 (polyglot) |
| Full skill, available | 15/16 (94%) | 12/16 |
| Full skill, force-injected | 16/16 (100%) | — |
Two findings: the bare model improved on its own (44% → 81% vs qwen3.6), and 3.8-27B’s willingness to load skills grew a lot. qwen3.8 loaded the full skill on its own 12/16 times, producing the best score ever recorded on this benchmark. Force-injecting the full skill then completed the sweep: 16/16, the first perfect round in the eval’s history (polyglot 10/10 with every task at full marks, SWE-bench 6/6). But the perfection is pricey: 1820s/task avg vs 518s self-triggered (+251%), which is exactly what “the full verification loop, every single time” costs. mini is worthless here too, same as on deepseek-v4-flash-0731.
The four models, one table (16-task rounds, Aug 2026)
| qwen3.6-35b-a3b | qwen3.6-27B | deepseek-v4-flash-0731 | qwen3.8-27B | |
|---|---|---|---|---|
| Bare model | 6/16 (37.5%) | 7/16 (44%) | 11/16 (69%) | 13/16 (81%) |
| Full skill, available | 7/16 (43.8%) | 9/16 (56%)† | 11/16 (69%) | 15/16 (94%) |
| Full skill, force-injected | 5/16 (31.3%) | 9/16 (56%) | 14/16 (87.5%) | 16/16 (100%) |
| mini, available | 6/16 (37.5%) | 8–10/16 (best 62.5%) | 13/16 (81%)* | 13/16 (81%) |
| mini, force-injected | 7/16 (43.8%) | 8/16 (50%) | — | — |
| Best config | mini, force-injected | mini, available | full, force-injected | full, force-injected |
* deepseek’s mini: first run 11/16, clean-environment rerun 13/16, both within noise of its 11/16 baseline. † qwen3.6’s full skill: the plain version scored 6/16 (never loaded); 9/16 is the improved-description variant.
Waves 6–7 (Sep 2026, current skill): what actually makes it work
The four-model table above is the 16-task benchmark. Later rounds asked a narrower question: when a small model does use the skill, what makes the difference? Not more rules.
Controls (deepseek-v4-flash, 16 tasks, forced injection). No-skill 11/16. A generic 39 KB engineering playbook, same size and tone, 11/16: a long structured prompt alone changed nothing. The skill 15/16. Against the playbook the discordant pairs were +4/−0 (McNemar p=0.125, directionally clear, underpowered at n=16).
The oracle experiment (qwen3.6-35B-A3B, 4 tasks every arm failed). With a deterministic checker and the project’s real tests (a capability probe, because the checker saw the canonical tests): 1/4 → 4/4, 12–36 checker runs per task, zero test tampering. Same loop, self-written tests: 1/4, with one task regressing below baseline. Generated tests, even from a strong model, even after qualification (fail-on-stub, pass-on-gold, fail-on-plausible-wrong): 1/4 with verified false greens.
The delivered solution passed the generated suite and still failed the hidden tests
on area_code and exact error strings that appear nowhere in the visible spec. The
loop was never the bottleneck; the oracle was. Wave 7 codified that into A4.8 and
APPENDIX §A11.
Wave 7 A/B (text-only non-inferiority, forced injection). deepseek-flash 16 tasks: 13/16 → 16/16 (the before arm was a low draw; the same-size skill scored 15/16 in wave 6, so read this as no regression). qwen3.6-35B 8-task subset: 4/8 → 3/8, one flip each way. The checker and oracle machinery is validated by the experiments above, not by this A/B.
Wave 11 (Sep 2026): ceremony economy + AEWM triage
The first protocol upgrade wave (lanes, FCV, coverage honesty) was validated in two A/B rounds on deepseek-v4.1-flash and qwen3.8-27b — and the runs themselves turned up two design faults. Weak models spent the cell budget on loading the discipline instead of shipping code, and the 420s cell cap was silently counting truncation as behavioral failure. Wave 11 fixes both: the ship order puts working code and green tests before ceremony, budgets reserve a completion margin, and timed-out cells are classified budget-invalid (excluded from behavioral rates; completion rate is reported separately; wall time is a cost metric, not a verdict). TDD/new-feature fixtures are budgeted 2h per cell. With adequate budget, both arms complete the bugfix and spec-conflict tasks with full compliance — the earlier “skill arm loses” readings were truncation artifacts. The wave also borrows AEWM’s contamination guards (arXiv:2609.28416): per-action critical/exploratory/noisy triage, state revision by editing the stale artifact rather than appending critiques, and the rule that a local green is never task completion.
Wave 12 (Sep 2026): objective A/B evaluation
The A/B harness itself was put on trial after a round that seemed to show the upgraded skill doing worse and costing more. It did — at measuring the wrong things: the assertions rewarded the skill’s own new output fields (circular), the agent could see the scoring criteria, and a deliberately wrong fixture test on the conflict task rewarded silent test rewriting while punishing honest conflict flagging. Wave 12 replaces the runbook with an objective hierarchy: hidden fail-to-pass tests grade the outcome, test-file hashes and conflict discipline grade anti-cheat integrity, Effective Mutation Score (delivered suite must pass on the gold implementation before its mutant kills count) grades suite quality, and wall time is demoted to a cost column. Six measurement pitfalls discovered in real voided rounds are codified in §V8. First objective results (N=3, directional): outcome 8/8 vs 7/8 in favor of the upgraded skill; integrity 5/5 vs 3/5 — the old skill silently rewrote the contradictory test twice to force green, the new one implemented per spec, flagged the conflict, and never touched the test. The earlier “high mutation score” of the old arm was the tampering premium. Cost remains the real trade: about 1.35× slower on this suite.
Wave 13 (Sep 2026): task classification + document gates
Three changes to the contract, none of them benchmarked against a model yet — verified by fixture suites, adversarial review and fresh-context probes instead, which is evidence about the mechanism, not about model behavior.
- COV-13 / §V11 Task Class.
Class: CODE > CONFIG > DOCfrom file kinds; per-class path cards (gate ↔ named risk); lite completion table for prose and config work; doc-drift trigger; Class × Lane as separate axes. Motivation: a CHANGELOG edit was walking the full verification path, and the path was pushing README updates around on its own. - §V11.9 DOC-asset render gate. Office deliverables stay Class DOC but take
render-and-verify evidence (
NO RENDER, NO DONE); doc-skill delegation table; named executable-behavior check (vbaProject / PDF JS / macro sheet) at delivery; flagged toolchain fallback with anUNVERIFIED-layoutmark. - Blind-spot hardening. Two hunts (own probes + a fresh-context semantic
reviewer) closed nine real holes: the gate now triggers on file kind in every
class (a mixed CODE wave shipping a sample docx owes the render), evidence
binds to the current task block and per asset (COV-5 probe images, prior-block
citations, placeholder
render: N/Alines and quoted echoes don’t license), the asset set is read from the whole change wave rather than the working tree (a committed asset is still a delivery), and the exec-check moved to delivery time with a log token. - §V12 stop-guard. A coherent “context exhausted, stopping here” slips past
every byte-level loop detector, so it gets its own syntax-level guard: the
audit plugin spots stop-euphemisms in the last assistant message
(quote-stripped, meta-discussion-aware, cessation intent required), consults a
session-scoped terminal-state whitelist (PAUSED packet · Class-E stop · gate
marker · explicit user directive), then posts ONE corrective prompt — budget
2/session, never thrash, four legal stops named. v1 hosts quote the measured
context fill; v2 degrades to a journaled stop-debt replayed into every audit
report. Output-limit truncations (
finish:"length") count as continuations, not completions. - Evidence. Fixture suite 166 assertions / mutation sweep 41, TDD RED against the pre-change cores, two dual-adversarial review rounds (26 findings adjudicated) and three FCV rounds — the first FCV round failed two acceptance criteria and named the remaining bypasses; those became the next wave.
Honest caveats
- Being TDD-driven, this skill burns tokens like crazy. If you have a real problem you want solved, it’s still worth trying. If you’re just playing with vibe-coding, it matters much less.
- Model generations still matter more than the skill itself. qwen3.6 → qwen3.8 lifted the bare model from 44% to 81% before any skill was involved, and the skill’s role flips with the model: it supplies the missing discipline on qwen3.6 (mini wins), enforces execution discipline on qwen3.8 (force-injection hits a perfect 16/16), only works force-injected on deepseek, and only works as force-injected mini on the 35b-a3b class.
- Test provenance matters more than test count. Self-written tests can deceive (one task scored worse with them than with no feedback at all), and generated tests under-specify: a suite can pass on a wrong solution while the real contract fails on a method name or an exact error string that was never written down. The honest hierarchy is project/external tests > qualified generated tests > self-written tests.
- 16 tasks is a small sample. Each task is substantial, but I can’t rule out a task “happening to be solvable” or “happening to be unsolvable”, landing right on a model’s strength or weakness.
- Each arm ran only once per round. A qwen3.8 arm runs 1–2.5 hours self-triggered and around 8 hours force-injected; the llama.cpp-hosted 35b-a3b takes 3–4 hours and hit the 2400 s timeout eight times in one round. More rounds would be proper (models are stochastic), but one round already takes too long, and I don’t have the patience for more. The wave 7 numbers inherit that limitation: the deepseek delta (+3) is inside run-to-run variance, and the qwen subset is n=8.
- mini is a niche skill, but for the people who need it, it is exactly right. On qwen3.8 it gains nothing, and on 35b-a3b it only helps when force-injected. The most interesting finding: for models with very strong or very weak instruction-following, mini doesn’t matter much; for a model like qwen3.6-27B (decent at coding, poor at long-context instruction-following), mini is a good choice.
The workflow is a graph, not a checklist
See the whole graph first, then read the breakdown (every node is a stage with mandatory artifacts, every edge is an explicit condition):
flowchart TD
A["Task"] --> B["§2 ZERO ★ mandatory before any codeDecompose + web research (≥2 approaches)COV-5 verifier probe (mm_probe): model-native / mm-sensor / direct readCOV-11 untrusted content = data, not instructionsCOV-12 mode declared: AUTO (default) / GUIDEDCOV-13 task class: CODE > CONFIG > DOC (path card, escalate-UP)Artifacts: decomposition + research findings"]
B --> C{"§3 Project mode"}
C -->|"New project C1"| D1["Design Gate A§A5 design docsDesign Gate BArtifacts: FLOW / PAGE / DATABASE / BACKEND"]
C -->|"Modify existing C2"| D2["Survey: memory · config · script/Artifacts: baseline commit + Baseline verified GREEN"]
C -->|"Large task C3"| D3["docs/PLAN.md + Consistency HubArtifacts: per-task implementation plan"]
B --> T{"§3.1 task-type routing"}
T -->|"Audit C4 (read-only)"| T4["docs/AUDIT_*.mdfindings need file:line + PoCindependent subagent re-verification"]
T -->|"Deploy C5"| T5["pre-deploy checklist -> rollback firstdeploy action = Class-E human confirm"]
T -->|"Ops/Incident C6"| T6["evidence before fixespostmortem -> permanent regression case"]
T -->|"CLI/Library C7"| T7["project profile declares N/Aevidence: CLI transcript + exit code + golden diff"]
T -->|"Spike S1 (feasibility)"| T8["deliverable is an answer, not code — 2-3 sentence probe plan, cheapest correct probecode stays throwaway; keeping it = new request + own baseline"]
D1 --> E["Implementation (changes)"]
D2 --> E
D3 --> E
T5 --> E
T6 --> E
T7 --> H
T4 --> O
E --> F{"Change type"}
F -->|"Runtime-visible"| G1["§A4.1 capture-verify loopAct → Capture → Verify → Fix → LogArtifacts: verification_log.md + media evidence"]
F -->|"Backend-only"| G2["§A4.7 doc-driven API tests+ A4.7b cross-endpoint workflow trace"]
F -->|"Logic-bearing code"| G3["§A4.8 TDD + trusted oracleRED evidence first, then GREEN implementationproject tests certify · checker drives the loop"]
G1 --> H{"Acceptance all green?"}
G2 --> H
G3 --> H
H -->|"No · within cap=5"| E
H -->|"stall=3× / cap=5"| I["§A4.10 parameterized escapechange direction · fresh-brain retry"]
I --> E
H -->|"Yes"| J{"COV-8 major change?"}
J -->|"Yes"| K["§A4.9 independent review dispatchArtifacts: review record + ruling"]
K --> L["§A4.4 completion gateconvergence line + 8-column tableassert_artifacts.py exit 0"]
J -->|"No"| L
L --> M["Memory GateA7.9 memory write + A7.10 passed"]
M --> N{"Plugin audit Tier 0/1/2"}
N -->|"BAD → GATE-BLOCKED / RED latch"| E
N -->|"OK"| O["Deliver (C4 audit reports converge here)"]
- Nodes are stages with mandatory artifacts. ZERO (decompose + research) → project-mode detection → design gates → implementation → verification loop → independent review dispatch → completion table. A stage is not “done” because the model said so; it is done when its required outputs actually exist on disk.
- Edges are explicit conditions, not model mood. A new project forks to one workflow, modify-existing to another; the verifier capability probe branches the capture and grading set into three verifier modes; backend-only changes swap the browser loop for the doc-driven API test loop.
- Cycles are bounded by construction. Every loop shares one termination
contract (
cap=5iterations per sub-problem,stall=3×), and the stop condition is written down by the user first, so the graph is guaranteed to have an exit. - Traversal is soft, gating is hard. The model walks the graph by interpreting
prose; that part stays soft. But each guard condition is machine-checkable:
literal tokens in the final answer, on-disk evidence byte-checked by
tests/assert_artifacts.py, and (with the plugins) a tool-level hook that blocks the agent’s own writes while any gate is red.
That is what makes it a state machine instead of a promise to behave: the current stage is always verifiable from the files, and no transition may be declared without its evidence. The gate and auditor below are the same idea one layer down: the graph’s final guards, executed by opencode itself instead of the model.
Enforcement: the gate and the auditor
Prompts are just suggestions. A model that has just been told “NO TEST, NO DONE” will still, occasionally, declare done without a single test. The companion plugins enforce the evidence rules mechanically, at the tool level.
vibeweaver-gate: the stop hook.
- It hooks opencode’s
tool.execute.afterfor everywrite/edit. If the project is vibeweaver-active (it has atests/verification_log.md), the plugin runs the project’stests/assert_artifacts.py(trying all four flag combos). - If verification evidence is missing or falsified (no iteration entries in the
log, no
> cap=5 stall=3×first line inacceptance.md, cited screenshots or media missing or zero bytes), the plugin throws aGATE-BLOCKEDerror into the tool result. The agent cannot proceed; its own tool call comes back red. The hook doesn’t ask the model to slow down; it prevents the completion. - Structure-level gaps (missing
memory/, design docs, README) are appended asGATE-WARNING, non-blocking. - A
session.idletripwire writes awarnentry to the opencode log if the session goes quiet while the gate is still red. - The gate is deliberately re-checkable, not a dead stop: fix the artifacts, and
the next
write/editre-runs the check automatically. VIBEWEAVER_GATE=offturns it off.
vibeweaver-audit: the mechanical auditor. At session idle it re-runs the
project’s tests/assert_artifacts.py (the same script the gate runs), grades the
final output against its own claim checks, and re-checks the on-disk evidence.
A BAD grade latches a session-scoped RED state that blocks the agent’s writes
until the evidence is actually fixed. Because the latch is session-scoped, a
truncated session can never brick a project again: the latch self-releases on
session change, on TTL expiry, via legacy-state migration — or when the latching
session itself starts its NEXT task (rewriting tests/acceptance.md is the
protocol’s own first action, and tests/ stays writable under the latch), so a
multi-wave session never needs another session, a TTL wait, or an env-off restart
to keep working. Stale-buffer re-audits with an unchanged failure signature can
neither refresh a live latch’s timestamp nor resurrect a released one — a new
completion claim re-arms the teeth honestly. Every release is journaled and
surfaced in the audit report (see the 2026-08-21 and 2026-10-02 entries in
CHANGELOG.md). A forbidden raw command (C8) flags only once per
project — the latch always stays self-clearable on the next clean audit.
The same observation channel also runs the loop-guard: a bounded tail scan of
the assistant text stream for runaway generation — an identical line-group
repeating (any block period, line-aligned or a no-newline stream; a single line
needs 4 copies, multi-line blocks 3), a trailing run of ≥12 bare tokens stepping
+1 (integers or bijective base-26 letters), a counter wall (≥16 consecutive tail
lines with identical non-digit shape whose every digit run steps strictly +1 —
strictness is what keeps timestamp logs and page N of M clean), or a
punctuation-only wall once the wall itself passes 2 KB. The same machinery runs
a reasoning channel too: reasoning parts get their own buffer and episode budget
(a wall living only in reasoning text was invisible to the old guard), and
trailing whitespace is normalized at scan entry, so a runaway ending in a
newline or stray spaces no longer hides its own seed. On a hit it interrupts the
session (v1 session.abort / v2 session.interrupt({continue:false})) and posts
a corrective prompt naming the pattern; one intervention per episode (re-armed
after clean text or a new turn), two per session at most, further episodes are
log-only. A per-turn absolute ceiling — one turn’s streamed output beyond 64 KB —
raises the same interrupt with its own corrective prompt. Near-misses are
designed out: numbered lists with content are not bare tokens, a 2× repeat is
below the bar, and separator rules / ASCII art stay clean.
The guard also watches the tool channel, which is where a nastier failure
lives: intent-action decoupling. The model narrates a tool call (“use Read now”,
“final”, “grading”) and then emits bare echo "…" bash calls instead — every one
exits 0, the strings vary, and none of the text detectors can see it because the
loop never touches the text stream. The detector is content-level, not
byte-level: echo/printf/true/: with literal arguments and no side
effects count as no-op, and four consecutive distinct no-op bash calls trip the
same interrupt. Streamed re-observations of one tool part dedupe by part id,
status-only observations can’t mask the run, and truncated recorded commands
break it (truncation can forge a literal). Two more detectors cover the storm
shapes the echo classifier cannot see: identical-tool-run (the same tool with
identical canonicalized arguments — deep key-sort JSON identity, DISTINCT part
ids only, so observation-collapsing is never used — re-issued ≥4 times) and
tool-frequency (one tool hammered ≥20 consecutive calls with varying
arguments). Every interrupt is itself the stall declaration (- stall: noop-bash … / - stall: identical-tool-run … / - stall: tool-frequency … before any
completion claim — the tool-frequency line only for genuine stalls;
legitimate bulk work writes a one-line note instead, never a stall that did
not happen), and every pattern is fully values-free (sanitized tool name +
key count + argsLen) so tool arguments can never steer the corrective prompt. The two
channels keep independent episode arming and budgets, so a text-degeneration
episode can never consume the tool channel’s interrupt. The corrective prompt
demands the real progress move — or the completion output if the criteria really
are all passing. Honest scope: bare literal runs, identical-call repeats, and
single-tool storms are caught; semantic no-ops (sleep, ls) and echo/read
oscillation are documented gaps, not claimed coverage.
The gate is also skill-agnostic: it fires on any project that has
tests/verification_log.md, so it covers vibeweaver-mini too; mini’s artifact
formats are deliberately aligned with its evidence floor. If you only run mini and
want the hard floor, installing this one plugin is the whole job.
One honest caveat: the plugins speak opencode’s plugin API — both generations of
it (v1’s server() hook map and v2’s setup(ctx) domain API, from one file each;
v1 needs ≥ 1.18.29). Whether Claude Code or Codex have an equivalent mechanism, I
haven’t checked; forks welcome. The vibeweaver-dsh port ships the same
assert_artifacts.py evidence checks.
The memory system: opencode forgets, the files don’t
opencode has no native memory. A fresh session is a fresh brain: the model has no idea that a JWT refactor was already tried and vetoed three sessions ago, or that the previous engineer spent two days chasing a session TTL mismatch. Every session it re-derives the same dead ends and re-proposes the same rejected plans. Vibeweaver builds a memory out of files and rules:
-
An index plus topic files.
memory/MEMORY.mdis a table of contents, not the memory itself (load cap: 200 lines / 25 KB). Each memory lives in its ownmemory/*.mdfile with YAML frontmatter: type (user/feedback/project/reference/fix), status, the commit hash it describes, and the file references it cites. -
Selective recall, not full recall. At session start the index loads first; then the agent greps the topic files for keywords from your request and loads only the top 3-5 most relevant entries. Memory is consulted before code is touched, but never trusted blindly: every file/line citation is verified against the current code, and entries older than 14 days get a “this may be stale” warning. Even a ✅ Verified entry self-ages: if it hasn’t been re-validated in 14 days or its cited code changed, it’s demoted back to ⏳ until re-verified.
-
Trust tiers, because not all memories are facts. ⛔ Forbidden = methods proven to fail; never retry. ✅ Verified = confirmed by the user. ⏳ Unverified = the agent’s own fix that passed tests but nobody confirmed. ❌ Failed = a ⏳ that later failed; it carries the same “don’t retry” weight as ⛔.
-
A state machine for fixes. The agent fixes something and tests pass → written as ⏳ (never ✅; only the user can verify). You report the same symptom next session → the entry is auto-demoted to ❌ and the agent must try a genuinely different direction. You confirm it works → promoted to ✅. Three or more failures on the same problem → everything escalates into a ⛔ Forbidden file.
-
Written every session, gated at the end. Memory writing is a non-negotiable session-end step, checked by a Final Memory Gate before the completion table. Fix entries must carry the commit hash of the change they describe, plus the failed approaches and rejected alternatives that were considered, so a future session can look at the memory, look at the exact code state, and skip the dead end entirely.
-
Two scopes, merged. User-global memory (
~/.config/opencode/vibeweaver/memory/) holds your cross-project preferences and conventions; project-local memory holds everything project-specific. Both load at session start; project-local wins on conflict. -
Housekeeping. The index has a consolidation trigger (150 lines / 20 KB, or
15 topic files): ⛔ / ✅ / user / feedback entries survive consolidation, stale ⏳ entries get pruned, and a
.session-scratchpad.mdtracks mid-session backtracking before being deleted when the real memories are written.
In short: filesystem plus rules doing the job of a memory layer, so the model doesn’t relearn your project from zero every session.
The cognitive overlay: state management beyond the tools
The evidence rules solve “the model lied about what it did”. They don’t solve “the model quietly stopped knowing what state it’s in”. Drift, spin, and goal evaporation over long tasks live one level up; a recent revision borrowed a set of mechanisms from J-Space Cognition Suite (credit in Attribution) for exactly that layer:
- Untrusted content is data, not instructions (COV-11). The skill mandates web research (exa MCP + Context7), and fetched content is precisely where “ignore all previous instructions” lives. Fetched / tool / third-party text may inform, it may not command; a fetched “solution” still has to pass the ≥2-approach evaluation; and the asymmetry rule applies: a hit is strong evidence, while “found nothing suspicious” is not a clearance; absence is established with a named check, never by the model’s own monitor staying silent.
- Consistency hub (write once, read many). Big tasks carry one canonical row per shared name / config key / value / signature in the plan. Later steps cite the hub row instead of re-deriving it. A rename changes the hub first, then the old spelling is grepped to zero hits, and the zero-hit grep output is the completion evidence. This kills the classic long-task drift where one settled value turns up in three spellings.
- Diagnosis-carrying retries. Every
- iter N FAIL:line inverification_log.mdmust carrydiagnosis:, machine-checked (assert group 12). A retry without its diagnosis is the same attempt again: same cost, buys nothing. - Stall escape: parameterize, don’t spin. When
stall=3×fires, the next direction is generated, not guessed: the open unknown becomes a finite candidate set, each with the cheapest test that could refute it, and only then does the direction shift (abstraction / strategy / empirics). Differential verification demands the reference implementation not share the candidate’s assumptions; a brute force that inherits the cleverness inherits the bug. And when two cheap independent verification paths exist, take both: agreement earns the conclusion, disagreement locates the faulty assumption. - Re-entry after gaps. After a compaction, session boundary, or long idle, the
agent re-reads
verification_log.mdin full, re-reads the goal line by line, re-reads the covenants, and only then names its next action, in that order, before touching the work (§3.3). - Mechanized stall observation. The gate plugin keeps
.vibeweaver/state.json(atomic writes): the same file edited 3× with no new PASS entry in between triggers aGATE-WARNINGstall note pointing at the escape protocol.stall=3×used to be a bound the model counted for itself; now the plugin counts too.
The skill practices the progressive-disclosure discipline it preaches: the
~120-line embedded assertion script became the canonical
scripts/assert_artifacts.py, and the four backend / TDD / review protocols moved
to TESTING_PROTOCOLS.md. The entry file went from a 79 KB single file to today’s
767 lines / 47.8 KB, with every new rule costing one compact covenant line plus a
pointer.
The mm-sensor hookup: partner, not rival
mm-sensor and vibeweaver are designed as a pair; the skill has built-in detection and invocation for it. Running without it works, but results take a small hit. The division of labor:
- A three-stage verifier tree (COV-5, behavioral probe, not self-declaration).
At task start vibeweaver runs its self-multimodality probe
scripts/mm_probe.py: the script generates a probe image carrying a token and a color (tests/probe_vision.png); the model reads the image and reports the token and color it sees; thenmm_probe.py --checkverifies the report. - PASS → announce
Verifier: model-native [image]; the model grades its own screenshots under the §A4.1.1 Visual Verification Protocol (observation-first, per-criterion verdicts with quoted evidence, DOM/log cross-check, UNCERTAIN=FAIL). FAIL with mm-sensor installed → announceVerifier: mm-sensor [video+audio|video|image]for independent grading. Neither →Verifier: direct read(DOM/log inspection is the primary evidence). - vibeweaver makes the evidence exist. Its rules force the agent to actually run the app, drive it with Playwright, and leave screenshots / screen recordings / page audio on disk.
- mm-sensor grades it independently. The maker/checker split: while mm-sensor is the verifier, the model that wrote the code is forbidden from grading its own screenshots. Vibeweaver alone falls back to direct-read self-grading when the model fails its own probe (weaker), and it demands extra cross-checks against DOM and logs.
- A capability probe decides how much evidence gets captured. At task start,
vibeweaver runs
vision.py --probeto ask the model behind mm-sensor what it can actually perceive. Full-modal models get the[video+audio]mode: Playwright records the whole flow as video, captures in-page audio via Web Audio, plus a terminal-state screenshot. Image-only models degrade to[video]or[image]mode. The mode is fixed per task, and every captured file is graded withvision.py --detail high. - If the environment is lacking, the loop degrades gracefully. No ffmpeg → grade the raw webm via frame-sampling. Model can’t hear audio → mm-sensor reports the skip explicitly and the loop continues on video + screenshots. Audio is an added signal, never a criterion by itself.
In one line: vibeweaver decides what must be captured; the verifier (model-native or mm-sensor) decides what the evidence actually says.
Design-copy fidelity: measurement before judgment
When the acceptance criteria name pixel or geometry fidelity — copying a page from an existing HTML source or a screenshot — vibeweaver adds a third evidence channel beside the verifier tree: §A4.1.2’s measure-then-judge tiers. The point is not to look harder: 2025-26 VLM research shows comparative visual measurement (a 3 px shift, an occluding overlap, a wrong box size) is exactly what vision-language judges are least reliable at, so geometry is never certified by a model’s eye.
- T1 geometry/occlusion — element-box dumps from both sides feed
scripts/ui_fidelity.py boxes: per-element Δsize/Δposition, missing/extra elements, non-containment overlaps, andoccluded_by(elementsFromPoint sampling at capture time). - T2 pixel — same-condition captures feed
scripts/ui_fidelity.py diff(pixelmatch v5.3.0 math ported to stdlib: YIQ color delta + anti-aliasing detection) and return a diff image plus a cluster list for diagnosis. - T3 semantics stays §A4.1.1 (VLM observation-first grading). Verifier modes
are unchanged — T1/T2 are deterministic, so even
direct readtasks get full fidelity verification. Capture recipe + DOM-dump snippet: APPENDIX §A12.
Stack compatibility
vibeweaver is stack-agnostic. It never assumes a language, framework, or database:
- New projects: declare the stack, or the skill asks once before scaffolding. Then
it generates design docs,
config.tomllayout,script/lifecycle scripts, and dependency manifests around your stack. - Existing projects: it reads what’s already there (memory, config, scripts, structure) and adapts every rule to match. It will not “helpfully” introduce React into your Vue project.
- Windows: yes, it knows.
install.batandscript/windows/exist.
The default stack, and how to change it
New-project scaffolding has a built-in default (REFERENCE.md, Part B1):
FastAPI + React + Vite + PostgreSQL: Python/FastAPI backend with OAuth2 auth on
every endpoint, frontend mounted at /static with history-routing fallback, React +
Vite responsive frontend (desktop / tablet / mobile). When you say “new project”
and nothing else, this is what comes out.
Two ways to get a different stack:
-
Per project, without touching the skill. Declare your stack when asking (“new Go + Vue + MySQL project”) and the skill scaffolds around that. The default only wins when you don’t pick anything. The core rules (Part A) are universal; the skill reads your declared stack, fills in the real build commands, and adapts the
[database]config block to your actual database. -
Permanently, by editing the skill’s Part B. To bake in a different default, edit the stack description in
REFERENCE.md§B1 (the “Default New Project Stack” section), and mirror the change inAPPENDIX.md:- §A5: the
config.tomlfull template (adapt to your backend / database) - §A6: the script templates (
script/linux/project_build.sh,start.sh,stop.sh,restart.sh+ the Windows.battwins) so they produce your stack’s real build/start/stop commands instead of the npm/uvicorn ones
Rule of thumb when adapting (Part B2): apply all Part A principles (they’re universal), swap the script templates for your build tooling, adjust the config template to your database, and keep the
script/directory discipline; the mechanics matter more than the commands inside. - §A5: the
vibeweaver vs superpowers
Superpowers is the closest well-known relative: a skills-based development methodology for coding agents. Both are MIT, both are skill ecosystems, but they bet on different things:
| Dimension | vibeweaver | superpowers |
|---|---|---|
| Workflow | Decompose → web research (near-mandatory) → task-type routing (build / audit / deploy / ops / non-web / spike) → design docs / plan (when scoped) → test-first → evidence gates | Classify the request (spike / bounded / architectural) → design approval → spec + bite-sized plan (architectural path) → subagent-per-task execution |
| Core bet | Research-first + evidence-gated completion, near-mandatory web search before code (nothing new under the sun), tests must run and leave artifacts, enforced by a tool-level plugin gate | Planning-first + approval-first, no implementation before the human approves the intent; the ceremony scales with the task, the approval gate never does |
| Human involvement | AUTO by default: the agent settles defined interaction points itself and logs an ADR; GUIDED (more checkpoints) on request | Approval is the hard gate on every path: a spike gets a nod, a bounded task gets a yes to an in-chat design, and an architectural one is approved section by section |
| Execution model | Same session, verifier continuity, memory and evidence accumulate across the task; subagents are read-only reviewers | Fresh subagent per task, context isolation; the coordinator reviews between tasks |
| Verification | Self-starting capture loop graded by an independent multimodal verifier; evidence is byte-checked by assert_artifacts.py; major changes get an independent review with a spec-fidelity triad |
Evidence-before-claims iron law (fresh run, read the output), process-enforced, no tool gate |
| Project memory | Built-in memory subsystem with trust tiers | Not a core feature |
| Model requirements | Engineered for small models too (mini variant, benchmarked down to ~3B-active) | Assumes strong models, long specs, subagent delegation |
| Agent support | opencode (with a plugin gate; vibeweaver-dsh is the DeepSeek port; Claude Code / Codex unknown, forks welcome) | Claude Code, Codex, Cursor, Gemini CLI, Copilot, opencode, etc. |
| Public benchmark | Published A/B vs no-skill baseline, multiple models | None |
Short version: both start by decomposing, then planning. The weight differs: superpowers invests in the plan and keeps a human gate on every path; vibeweaver makes the research step near-mandatory, lets the agent proceed by default (AUTO), and gates completion on evidence. They’re not enemies; you could run both, if you have that kind of token budget. Honestly, I don’t know whether running both makes the agent’s context explode and give up; untested, feedback welcome.
Files
| File | Purpose |
|---|---|
SKILL.md |
The binding operational contract + router (~48 KB, size-guarded) |
COMPLETION_GATE.md |
Completion output spec · artifact gates · §AUDIT audit protocol · pre-output checklist |
CODING_PRINCIPLES.md |
The 4 iron rules (Think Before Coding · Simplicity First · Surgical Changes · Goal-Driven Execution) + Fowler’s 12-smell reviewer baseline |
ENGINEERING_STD.md |
Detailed engineering standards |
REFERENCE.md / APPENDIX.md |
Part B/C workflow full text + §A5.1 / executable templates (§A1–§A12: scripts, workflow traces, oracle + checker, design-copy capture) |
TESTING_PROTOCOLS.md |
§A4.1 loop + §A4.1.1/§A4.1.2 fidelity + §A4.6 debugging + canonical §A4.7–§A4.11 protocols (§A4.11 modes/pause) |
WORKFLOWS_EXTENDED.md |
§M dual modes + Class-E list + ADR/PAUSED formats · C4 audit / C5 deploy / C6 ops / C7 non-web / S1 spike · profile reference |
MEMORY_RULES.md / MEMORY_TEMPLATES.md |
Project memory subsystem |
VERIFICATION_UPGRADES.md |
§V1 FCV · §V2 test integrity · §V3 coverage honesty · §V4 adversarial review · §V5 lanes · §V11 task class + doc-skill delegation and the DOC-asset render gate |
scripts/assert_artifacts.py |
The canonical assertion script projects copy into tests/ (19 groups: artifact presence, evidence integrity, diagnosis/claim lint, secret scan, test-change guard, risk-tier, DOC-asset render gate, exec-check, task-class coherence, working-note lifecycle) |
scripts/mm_probe.py |
Behavioral self-multimodality probe + comparative sub-probe (verifier selection, COV-5) |
scripts/ui_fidelity.py |
Design-copy fidelity measurement (§A4.1.2): pixel diff (pixelmatch v5.3.0 port) + clusters, DOM box Δ/overlap/occlusion verdicts + reference-image region extraction — stdlib only |
scripts/scan_secrets.py |
Standalone secret scan for the completion checklist (assert group 14) — credential-looking strings on the change-wave diff |
scripts/backlog_check.py |
Backlog-ledger guard — fails any passes: true that no executed-test log line names |
vibeweaver-gate.js |
The stop-hook plugin (opencode) + mechanized stall observer |
vibeweaver-audit.js |
Three-tier mechanical auditor (Tier 0/1/2), session-scoped RED latch, journaled auto-release, stale-latch healing |
scripts/vibeweaver-audit-core.js |
Pure triage core (headless-testable) |
scripts/audit_selftest.mjs / scripts/mutation_sweep.mjs |
324 fixture checks (T24 loop-guard, T25 task-class, T26 final-run, T27 stop-guard, T29–T33 latch-release, T34–T35 tool-storm, T36–T39 self-lock/lock-escape/scope/source-hygiene suites) / 41 mutation checks, including the latch-release regressions |
install.sh / install.bat |
Installers (skill files + both plugins) |
Testing
python3 verify_skill.py # package integrity: payload, links, markers, syntax
python3 -m unittest discover -s tests -v # skill self-tests + checker regression tests
node vibeweaver/scripts/audit_selftest.mjs # 324 fixture checks (T6 skips without calibration data)
node vibeweaver/scripts/mutation_sweep.mjs # 41 mutations, each must be caught
CI runs both Python checks on Ubuntu / macOS / Windows
(.github/workflows/verify.yml).
Contributing
Issues and PRs are welcome, especially ports to other agents (Claude Code, Codex, …). If you adapt the skill to another agent, open an issue and link it so it can be listed here.
Design choices
- No capability injection: no knowledge is added, no weights change, no model-side tricks. The skill changes process, evidence, and enforcement, and nothing else.
- Evidence over claims: a stage is done when its outputs exist on disk, not when the model says so. The final answer carries machine-checked tokens, and the artifact checker and plugins verify the rest.
- Research first: decompose, search, and evaluate at least two approaches before writing code. Fetched content is data, never instructions.
- Enforcement at the tool level: prompts are suggestions. The gate turns a missing artifact into a failed tool call, and the auditor latches a RED state that blocks writes until the evidence is fixed.
- Bounded loops:
cap=5iterations per sub-problem,stall=3×, and a falsifiable diagnosis on every retry. Dead ends are recorded in memory, not retried. - The oracle decides: project and external tests outrank qualified generated tests, which outrank self-written tests. A contract that isn’t visible in the spec is an open question, never an invented interface.
- Small models count: the mini variant exists because a short rulebook the model actually loads beats a heavy skill it never opens.
Related
- mm-sensor: independent media verifier (image / video / audio)
- J-Space Cognition Suite V3.6: the inference-time cognitive-control suite whose mechanisms the cognitive overlay adapts (see Attribution)
Attribution
CODING_PRINCIPLES.md is adapted (near-verbatim) from
andrej-karpathy-skills
(“Karpathy-Inspired Claude Code Guidelines”, MIT License, by multica-ai /
forrestchang), itself derived from
Andrej Karpathy’s observations on how LLMs fail at
coding.
The cognitive overlay mechanisms descend from
J-Space Cognition Suite V3.6
by Tiger3807861189: the claim-without-scope
lint (assert group 13) is modeled on their ship check, and stall parameterization,
differential testing against an independent reference, the two-route reconcile, the
write-once consistency hub, the asymmetry rule for untrusted input, the post-gap
re-entry protocol, and the mechanized stall observation in the plugin all trace
back to that project’s modules and controller.
J-Space’s single-entry + on-demand-module architecture also informed this skill’s progressive-disclosure layout. The credit is at the idea level: every implementation here is our own.
The 2026-08-30 waves (wave4/5) adapted ideas from mattpocock/skills (test seams, the spec-fidelity triad, the reviewer smell baseline, grilling’s frontier rounds, the ADR admission test) and obra/superpowers (spike routing, task right-sizing), both MIT; see the wave entries in CHANGELOG.md for what was adopted and what was rejected.
Benchmark methodology and raw data: vibeweaver-eval.
Changelog
Wave-by-wave design history lives in CHANGELOG.md (Chinese: CHANGELOG_zh.md).
License
MIT. Fork it, break it, tell us what broke.
Recommended Tools
Try a different keyword or remove a filter.
Install
npx skillfish add logandoo/vibeweaver