wicked-garden 12.53.0 → 12.53.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/scripts/qe/lib/campaign-scoreboard.mjs +3 -47
- package/scripts/qe/lib/gate.mjs +3 -38
- package/scripts/qe/lib/ledger-pkg.mjs +74 -0
- package/skills/learn/SKILL.md +2 -2
- package/skills/qe/refs/accept.md +60 -19
- package/skills/qe-acceptance-test-executor/SKILL.md +5 -0
- package/skills/qe-acceptance-test-reviewer/SKILL.md +3 -0
- package/skills/qe-acceptance-test-writer/SKILL.md +5 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name": "wicked-garden", "owner": {"name": "Mike Parcewski"}, "plugins": [{"name": "wicked-garden", "source": "./", "description": "Your coding agent already plans and swarms \u2014 Wicked Garden is the curated toolkit for what it can't: proof-not-claims gates, code links grep can't see, deterministic refactor, cross-session memory, multi-model second opinions (fallback seats labelled). Don't fight the harness; fill its gaps. The gate needs wicked-vault (a self-contained infra peer, installed directly) and re-derives through garden's built-in engine; estate/bus are opt-in layers (wicked-testing and wicked-brain are retired \u2014 QE ships in-catalog as the qe domain, memory lives in wicked-estate).", "version": "12.53.
|
|
1
|
+
{"name": "wicked-garden", "owner": {"name": "Mike Parcewski"}, "plugins": [{"name": "wicked-garden", "source": "./", "description": "Your coding agent already plans and swarms \u2014 Wicked Garden is the curated toolkit for what it can't: proof-not-claims gates, code links grep can't see, deterministic refactor, cross-session memory, multi-model second opinions (fallback seats labelled). Don't fight the harness; fill its gaps. The gate needs wicked-vault (a self-contained infra peer, installed directly) and re-derives through garden's built-in engine; estate/bus are opt-in layers (wicked-testing and wicked-brain are retired \u2014 QE ships in-catalog as the qe domain, memory lives in wicked-estate).", "version": "12.53.2"}], "version": "12.53.2"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wicked-garden",
|
|
3
|
-
"version": "12.53.
|
|
3
|
+
"version": "12.53.2",
|
|
4
4
|
"description": "Your coding agent's harness already plans and swarms; Wicked Garden is the curated toolkit for what it can't do alone. Proof, not claims \u2014 gates re-derive 'done' through the internal loom engine (fail-closed, independently attested via wicked-vault), so a self-asserted pass can't lie its way green. Relationships grep can't see \u2014 the wicked-estate code graph + injected bus/dispatch/capability/archetype edges power blast-radius & lineage. Plus deterministic multi-file refactor (wicked-patch), cross-session memory + knowledge (the mem domain over wicked-estate), multi-model second opinions (fallback seats labelled) (jam:council), portable expertise as on-demand skill-refs, and evidence-gated testing (the in-catalog qe domain). It reads the shape of your work to apply the right rigor \u2014 steering, not a pipeline \u2014 then gets out of the way. The compiler stamps a self-contained evidence gate into any repo that runs with no wicked-garden installed. Don't fight the harness; fill its gaps. The evidence gate requires wicked-vault, a self-contained infra peer wicked-garden installs directly; wicked-bus is an opt-in layer \u2014 install what you'll use, the toolkit works without the rest.",
|
|
5
5
|
"wicked_vault_version": "^0.5.0",
|
|
6
6
|
"wicked_ledger_version": "^0.6.0",
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [12.53.2] — 2026-10-11
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **qe accept runs in one turn inside a governed unit (PR #1291, #1290).** With `WICKED_RUN_ID` set, `wicked-garden-qe` accept runs writer → executor → reviewer inline in one turn, with no sub-agent dispatch, and ends only on the recorded verdict. A claude QE seat no longer ends its turn on the writer's test plan.
|
|
9
|
+
|
|
10
|
+
## [12.53.1] — 2026-10-11
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **One wicked-ledger resolver, `$WICKED_LEDGER_PKG_DIR` first (PR #1284, crew#951).** `wicked-garden-qe` accept, the gate and the campaign scoreboard resolve wicked-ledger through one resolver that honours `$WICKED_LEDGER_PKG_DIR` first (wicked-crew 0.9.7 sets it for a governed run), so a governed QE unit records its verdict without the repository installing wicked-ledger.
|
|
14
|
+
- **Learn: the author computes claim ids (PR #1288, E2E F-LEARN-1);** synthesize leaves them.
|
|
15
|
+
|
|
5
16
|
## [12.53.0] — 2026-10-11
|
|
6
17
|
|
|
7
18
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wicked-garden",
|
|
3
|
-
"version": "12.53.
|
|
3
|
+
"version": "12.53.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Curated toolkit for what AI coding agents can't do alone: evidence-gated work, codegraph relationships, deterministic multi-file refactor, multi-model second opinions, and cross-session memory. Installs as a Claude Code plugin.",
|
|
6
6
|
"keywords": [
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
94
94
|
import { join, dirname, resolve, isAbsolute } from "node:path";
|
|
95
95
|
import { pathToFileURL } from "node:url";
|
|
96
|
+
import { resolveLedgerModule } from "./ledger-pkg.mjs";
|
|
96
97
|
import { parseArgs } from "node:util";
|
|
97
98
|
|
|
98
99
|
import {
|
|
@@ -168,54 +169,9 @@ export function resolveLedgerRootLocal(repoRoot, env = process.env) {
|
|
|
168
169
|
return current;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
|
-
// --- wicked-ledger resolution (
|
|
172
|
-
|
|
173
|
-
function esmEntryForPackageDir(pkgDir) {
|
|
174
|
-
const pj = join(pkgDir, "package.json");
|
|
175
|
-
if (!existsSync(pj)) return null;
|
|
176
|
-
const pkg = readJsonSafe(pj);
|
|
177
|
-
if (!pkg) return null;
|
|
178
|
-
const dot = pkg.exports && pkg.exports["."] !== undefined ? pkg.exports["."] : pkg.exports;
|
|
179
|
-
const rel =
|
|
180
|
-
(dot && typeof dot === "object" && (dot.import || dot.default)) ||
|
|
181
|
-
(typeof dot === "string" ? dot : null) ||
|
|
182
|
-
pkg.module ||
|
|
183
|
-
pkg.main ||
|
|
184
|
-
"index.js";
|
|
185
|
-
return join(pkgDir, rel);
|
|
186
|
-
}
|
|
172
|
+
// --- wicked-ledger resolution: the shared resolver (./ledger-pkg.mjs) -----------
|
|
187
173
|
|
|
188
|
-
export
|
|
189
|
-
// 1. explicit override (tests, TH-6 wiring, unpublished-floor installs)
|
|
190
|
-
if (env.WICKED_LEDGER_PKG_DIR) {
|
|
191
|
-
const entry = esmEntryForPackageDir(env.WICKED_LEDGER_PKG_DIR);
|
|
192
|
-
if (entry && existsSync(entry)) return await import(pathToFileURL(entry).href);
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
// 2. bare import (global / hoisted install)
|
|
196
|
-
try {
|
|
197
|
-
return await import("wicked-ledger");
|
|
198
|
-
} catch {
|
|
199
|
-
/* fall through */
|
|
200
|
-
}
|
|
201
|
-
// 3. walk up from the target repo root
|
|
202
|
-
let dir = resolve(repoRoot);
|
|
203
|
-
for (let i = 0; i < 10; i++) {
|
|
204
|
-
const cand = join(dir, "node_modules", "wicked-ledger");
|
|
205
|
-
const entry = esmEntryForPackageDir(cand);
|
|
206
|
-
if (entry && existsSync(entry)) {
|
|
207
|
-
try {
|
|
208
|
-
return await import(pathToFileURL(entry).href);
|
|
209
|
-
} catch {
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
const parent = dirname(dir);
|
|
214
|
-
if (parent === dir) break;
|
|
215
|
-
dir = parent;
|
|
216
|
-
}
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
174
|
+
export { resolveLedgerModule } from "./ledger-pkg.mjs";
|
|
219
175
|
|
|
220
176
|
// --- evidence extraction ------------------------------------------------------
|
|
221
177
|
|
package/scripts/qe/lib/gate.mjs
CHANGED
|
@@ -83,50 +83,15 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
|
83
83
|
import { join, dirname, isAbsolute } from "node:path";
|
|
84
84
|
import { spawnSync } from "node:child_process";
|
|
85
85
|
import { createHash } from "node:crypto";
|
|
86
|
-
import { createRequire } from "node:module";
|
|
87
86
|
import { pathToFileURL } from "node:url";
|
|
88
87
|
import { parseArgs } from "node:util";
|
|
89
88
|
|
|
90
89
|
import { buildExclusionsClause } from "./flake-policy.mjs";
|
|
91
90
|
import { resolveVaultModule, applyVaultIntegrity, VaultEvidenceError } from "./vault-evidence.mjs";
|
|
92
91
|
import { crewRunStamp } from "./crew-run.mjs";
|
|
92
|
+
import { resolveLedgerModule } from "./ledger-pkg.mjs";
|
|
93
93
|
|
|
94
|
-
// --- wicked-ledger resolution
|
|
95
|
-
|
|
96
|
-
function esmEntryForPackage(resolvedFile) {
|
|
97
|
-
let dir = dirname(resolvedFile);
|
|
98
|
-
for (let i = 0; i < 10; i++) {
|
|
99
|
-
const pj = join(dir, "package.json");
|
|
100
|
-
if (existsSync(pj)) {
|
|
101
|
-
let pkg;
|
|
102
|
-
try { pkg = JSON.parse(readFileSync(pj, "utf8")); } catch { return null; }
|
|
103
|
-
const dot = pkg.exports && pkg.exports["."] !== undefined ? pkg.exports["."] : pkg.exports;
|
|
104
|
-
const rel =
|
|
105
|
-
(dot && typeof dot === "object" && (dot.import || dot.default)) ||
|
|
106
|
-
(typeof dot === "string" ? dot : null) ||
|
|
107
|
-
pkg.module || pkg.main || "index.js";
|
|
108
|
-
return join(dir, rel);
|
|
109
|
-
}
|
|
110
|
-
const parent = dirname(dir);
|
|
111
|
-
if (parent === dir) break;
|
|
112
|
-
dir = parent;
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async function resolveLedgerModule(cwd) {
|
|
118
|
-
try {
|
|
119
|
-
return await import("wicked-ledger");
|
|
120
|
-
} catch { /* fall through */ }
|
|
121
|
-
try {
|
|
122
|
-
const require = createRequire(join(cwd, "__qe_gate_anchor__.js"));
|
|
123
|
-
const located = require.resolve("wicked-ledger");
|
|
124
|
-
const esm = esmEntryForPackage(located) || located;
|
|
125
|
-
return await import(pathToFileURL(esm).href);
|
|
126
|
-
} catch {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
94
|
+
// --- wicked-ledger resolution: the shared resolver (./ledger-pkg.mjs, $WICKED_LEDGER_PKG_DIR first) ---
|
|
130
95
|
|
|
131
96
|
/**
|
|
132
97
|
* Resolve the ledger root the gate writes to (TH-6). MUST mirror the TH-2
|
|
@@ -357,7 +322,7 @@ export async function runGate({ projectId, runId, verdict, verdictSummary, ratio
|
|
|
357
322
|
process.stderr.write(
|
|
358
323
|
JSON.stringify({
|
|
359
324
|
error: "LEDGER_UNRESOLVABLE",
|
|
360
|
-
detail: "wicked-ledger is not resolvable
|
|
325
|
+
detail: "wicked-ledger is not resolvable — set WICKED_LEDGER_PKG_DIR (a governed crew run sets it) or npm i --no-save wicked-ledger",
|
|
361
326
|
}) + "\n"
|
|
362
327
|
);
|
|
363
328
|
process.exit(3);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE wicked-ledger resolver of garden's QE pipeline (accept, the gate, the campaign
|
|
3
|
+
* scoreboard). wicked-ledger is resolved for the TARGET repo — the plugin ships no node_modules —
|
|
4
|
+
* in this order:
|
|
5
|
+
*
|
|
6
|
+
* 1. `$WICKED_LEDGER_PKG_DIR` — an explicit package dir. wicked-crew exports its OWN bundled
|
|
7
|
+
* wicked-ledger here (wicked-crew#951), so a governed run's QE unit records its verdict with
|
|
8
|
+
* the very package crew's acceptance check reads it with, and needs no install in the
|
|
9
|
+
* worktree (a fenced governed seat cannot `npm i`, and an install would change the tree).
|
|
10
|
+
* Set but unusable ⇒ `null` (an explicit pin never falls back to a different package).
|
|
11
|
+
* 2. a bare `import("wicked-ledger")` (a global / hoisted install);
|
|
12
|
+
* 3. a walk up from the target repo for `node_modules/wicked-ledger`.
|
|
13
|
+
*
|
|
14
|
+
* `null` when none resolves; callers say so (never a silent no-op).
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
17
|
+
import { dirname, join, resolve } from "node:path";
|
|
18
|
+
import { pathToFileURL } from "node:url";
|
|
19
|
+
|
|
20
|
+
export const LEDGER_PKG_ENV = "WICKED_LEDGER_PKG_DIR";
|
|
21
|
+
|
|
22
|
+
/** The ESM entry file of a package dir (its `exports["."]` import/default, else module/main). */
|
|
23
|
+
export function esmEntryForPackageDir(pkgDir) {
|
|
24
|
+
const pj = join(pkgDir, "package.json");
|
|
25
|
+
if (!existsSync(pj)) return null;
|
|
26
|
+
let pkg;
|
|
27
|
+
try {
|
|
28
|
+
pkg = JSON.parse(readFileSync(pj, "utf8"));
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const dot = pkg.exports && pkg.exports["."] !== undefined ? pkg.exports["."] : pkg.exports;
|
|
33
|
+
const rel =
|
|
34
|
+
(dot && typeof dot === "object" && (dot.import || dot.default)) ||
|
|
35
|
+
(typeof dot === "string" ? dot : null) ||
|
|
36
|
+
pkg.module ||
|
|
37
|
+
pkg.main ||
|
|
38
|
+
"index.js";
|
|
39
|
+
return join(pkgDir, rel);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The resolved wicked-ledger module for `repoRoot`, or `null`. */
|
|
43
|
+
export async function resolveLedgerModule(repoRoot = process.cwd(), env = process.env) {
|
|
44
|
+
const pinned = env[LEDGER_PKG_ENV]?.trim();
|
|
45
|
+
if (pinned) {
|
|
46
|
+
const entry = esmEntryForPackageDir(pinned);
|
|
47
|
+
if (!entry || !existsSync(entry)) return null;
|
|
48
|
+
try {
|
|
49
|
+
return await import(pathToFileURL(entry).href);
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return await import("wicked-ledger");
|
|
56
|
+
} catch {
|
|
57
|
+
/* fall through */
|
|
58
|
+
}
|
|
59
|
+
let dir = resolve(repoRoot);
|
|
60
|
+
for (let i = 0; i < 10; i++) {
|
|
61
|
+
const entry = esmEntryForPackageDir(join(dir, "node_modules", "wicked-ledger"));
|
|
62
|
+
if (entry && existsSync(entry)) {
|
|
63
|
+
try {
|
|
64
|
+
return await import(pathToFileURL(entry).href);
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const parent = dirname(dir);
|
|
70
|
+
if (parent === dir) break;
|
|
71
|
+
dir = parent;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
package/skills/learn/SKILL.md
CHANGED
|
@@ -43,9 +43,9 @@ Relative paths in this skill are relative to the directory that contains this SK
|
|
|
43
43
|
|---|---|---|---|
|
|
44
44
|
| `scope` | neutral | nothing | Name the slug (kebab-case, at most 64 characters), the kind (`topic` or `event`), 3 to 7 questions to answer, what is out of scope, and the source policy: primary sources first (specs, official docs, release notes, the project's own site), dated reporting for events. Read `.wicked/knowledge/<slug>/` if it exists: then this run is a **refresh** (see refs/refresh.md). |
|
|
45
45
|
| `research` | neutral | nothing | Fetch sources with your web tools (or `curl -sL`). For each source, record the URL, title, published date when the page states one, and `observed_at` = now in UTC. Draft candidate claims, each tied to the sources that support it. No network: write `research: no web access` and stop; never answer from memory as if it were sourced. |
|
|
46
|
-
| `synthesize` | neutral | nothing | Turn the candidates into the claims ledger (refs/claims.md): one atomic, checkable statement per claim, deduplicated
|
|
46
|
+
| `synthesize` | neutral | nothing | Turn the candidates into the claims ledger (refs/claims.md): one atomic, checkable statement per claim, deduplicated. Leave new claim ids to the author (a neutral seat may not run scripts); on a refresh keep each existing id. Keep only claims that would help a fresh session in 3 months. On a refresh, output the diff against the existing ledger. |
|
|
47
47
|
| `walkthrough` | neutral | nothing | Teach it in the run thread: a 5-line summary, a worked example, what changed (on a refresh), the open questions, and 3 to 5 check questions. The operator answers, asks or corrects by sending the step back; answer each point, re-teach what was unclear, and mark which corrections you verified against a source. |
|
|
48
|
-
| `author` | creator | `.wicked/knowledge/<slug>/`, skills |
|
|
48
|
+
| `author` | creator | `.wicked/knowledge/<slug>/`, skills | Compute each new claim's id (`wicked-garden run scripts/learn/check.py --claim-id "<text>"`), write the files (refs/claims.md), then run the check below and paste its JSON and exit code. |
|
|
49
49
|
| `review` | evaluator | nothing | Re-run the check yourself; re-fetch and spot-check at least 3 claims (every retirement, too); judge the durability test; last line `VERDICT: PASS` or `VERDICT: FAIL`. |
|
|
50
50
|
| `check` | any | nothing | `wicked-garden run scripts/learn/check.py --repo . [--slug <slug>]` |
|
|
51
51
|
| `index` | human or daemon only | estate knowledge | `wicked-garden run scripts/learn/index.py --repo <default-branch checkout>` after the PR merged. It refuses inside a governed run. |
|
package/skills/qe/refs/accept.md
CHANGED
|
@@ -87,6 +87,24 @@ invocation.)
|
|
|
87
87
|
- `--phase review` — review existing evidence
|
|
88
88
|
- `--json` — emit JSON envelope
|
|
89
89
|
|
|
90
|
+
## Governed unit (`WICKED_RUN_ID` set): one turn, inline
|
|
91
|
+
|
|
92
|
+
A governed wicked-crew unit (`WICKED_RUN_ID` is set) is ONE headless turn: whatever you print
|
|
93
|
+
last is the unit's reply, and the engine reads its `VERDICT:` line. So, on every seat:
|
|
94
|
+
|
|
95
|
+
- Run writer → executor → reviewer **inline, in this one turn**. Carry out each hand-off below
|
|
96
|
+
yourself: open the worker skill (Skill tool, or its SKILL.md from your catalog), do its steps,
|
|
97
|
+
and come back here. Do not dispatch an `Agent` / `Task` sub-agent or a fork. A headless unit has
|
|
98
|
+
none, and a forked result returns to nobody.
|
|
99
|
+
- A worker's output (test plan, evidence report) is an **intermediate artifact**: save it under
|
|
100
|
+
`{EVIDENCE_DIR}` (`test-plan.md`, `evidence.json`) and continue to the next phase. Never end
|
|
101
|
+
your reply on it.
|
|
102
|
+
- Never end the turn before step 6 has written the verdict row and your reply's last line is
|
|
103
|
+
`VERDICT: PASS` or `VERDICT: FAIL`. If a step fails, still finish: record FAIL with
|
|
104
|
+
`reason: inconclusive — <why>` and print that verdict line.
|
|
105
|
+
- Reviewer isolation is evidence-only dispatch here: judge from the scenario, plan and evidence
|
|
106
|
+
files, never from what you saw while executing.
|
|
107
|
+
|
|
90
108
|
## Instructions
|
|
91
109
|
|
|
92
110
|
### Preflight: Validate Input
|
|
@@ -123,7 +141,15 @@ the run's canonical UUID. This serves three goals at once:
|
|
|
123
141
|
// Resolve the ledger root (wicked-ledger >= 0.6.0): WICKED_QE_LEDGER_DIR when set — inside a
|
|
124
142
|
// governed wicked-crew run, the run's own ledger OUTSIDE the worktree (crew#951) — else dual-read
|
|
125
143
|
// (Phase 6c): '.wicked-qe', or a legacy '.wicked-testing' root written before the rename. <!-- historical -->
|
|
126
|
-
|
|
144
|
+
// wicked-ledger through the ONE resolver ($WICKED_LEDGER_PKG_DIR — set by a governed crew run —,
|
|
145
|
+
// else an install the target repo resolves); see § wicked-ledger resolution.
|
|
146
|
+
import { pathToFileURL } from 'node:url';
|
|
147
|
+
import { join as joinPath } from 'node:path';
|
|
148
|
+
// {WT_LIB} is a native path (Windows too): import it as a file URL, never a bare string.
|
|
149
|
+
const { resolveLedgerModule } = await import(pathToFileURL(joinPath(String.raw`{WT_LIB}`, 'ledger-pkg.mjs')).href);
|
|
150
|
+
const ledger = await resolveLedgerModule(process.cwd());
|
|
151
|
+
if (!ledger) throw new Error("wicked-ledger is not resolvable: set WICKED_LEDGER_PKG_DIR or npm i --no-save wicked-ledger");
|
|
152
|
+
const { createDomainStore, resolveLedgerRoot } = ledger;
|
|
127
153
|
import { join } from 'node:path';
|
|
128
154
|
const LEDGER_ROOT = resolveLedgerRoot(process.cwd());
|
|
129
155
|
const store = createDomainStore({ root: LEDGER_ROOT });
|
|
@@ -162,9 +188,9 @@ repo under audit, etc.) could otherwise inject instruction-looking prose
|
|
|
162
188
|
writer's instruction turn. The writer has `allowed-tools: Read` so it can
|
|
163
189
|
open the scenario itself.
|
|
164
190
|
|
|
165
|
-
Hand off to the `wicked-garden-qe-acceptance-test-writer` worker skill (
|
|
191
|
+
Hand off to the `wicked-garden-qe-acceptance-test-writer` worker skill (an isolated context where the host forks one; inline in a governed unit):
|
|
166
192
|
|
|
167
|
-
**Hand-off** — open the `wicked-garden-qe-acceptance-test-writer` skill with the brief below as the argument; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog
|
|
193
|
+
**Hand-off** — open the `wicked-garden-qe-acceptance-test-writer` skill with the brief below as the argument; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog; either way carry it out inline in this turn (no sub-agent), then continue here.
|
|
168
194
|
|
|
169
195
|
```markdown
|
|
170
196
|
Generate an evidence-gated test plan for the acceptance scenario
|
|
@@ -187,20 +213,23 @@ at the path below.
|
|
|
187
213
|
6. Map every success criterion to specific assertions.
|
|
188
214
|
7. Flag any specification mismatches you discover.
|
|
189
215
|
|
|
190
|
-
|
|
216
|
+
Produce the complete test plan in the standard format. It is an intermediate
|
|
217
|
+
artifact of `qe accept`: hand it back and continue (garden#1290).
|
|
191
218
|
|
|
192
219
|
```
|
|
193
220
|
|
|
194
|
-
|
|
221
|
+
Save the plan to `{EVIDENCE_DIR}/test-plan.md` (the reviewer reads it from there).
|
|
222
|
+
|
|
223
|
+
If `--phase write`, stop here. Otherwise continue to step 3 in this same turn.
|
|
195
224
|
|
|
196
225
|
### 3. Phase: Execute (Evidence Collection)
|
|
197
226
|
|
|
198
227
|
The run record was already created in step 0 so the evidence dir could derive
|
|
199
228
|
from its UUID. Here we dispatch the executor against that dir.
|
|
200
229
|
|
|
201
|
-
Hand off to the `wicked-garden-qe-acceptance-test-executor` worker skill (
|
|
230
|
+
Hand off to the `wicked-garden-qe-acceptance-test-executor` worker skill (an isolated context where the host forks one; inline in a governed unit):
|
|
202
231
|
|
|
203
|
-
**Hand-off** — open the `wicked-garden-qe-acceptance-test-executor` skill with the brief below as the argument; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog
|
|
232
|
+
**Hand-off** — open the `wicked-garden-qe-acceptance-test-executor` skill with the brief below as the argument; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog; either way carry it out inline in this turn (no sub-agent), then continue here.
|
|
204
233
|
|
|
205
234
|
```markdown
|
|
206
235
|
Execute this test plan and collect evidence artifacts.
|
|
@@ -219,13 +248,14 @@ Execute this test plan and collect evidence artifacts.
|
|
|
219
248
|
5. Continue to next step even if current step fails
|
|
220
249
|
6. Record timestamps for every step
|
|
221
250
|
|
|
222
|
-
|
|
251
|
+
Produce the complete evidence report. It is an intermediate artifact of
|
|
252
|
+
`qe accept`: hand it back and continue (garden#1290).
|
|
223
253
|
|
|
224
254
|
```
|
|
225
255
|
|
|
226
256
|
Update run status in DomainStore after execution.
|
|
227
257
|
|
|
228
|
-
If `--phase execute`, stop here.
|
|
258
|
+
If `--phase execute`, stop here. Otherwise continue to step 4 in this same turn.
|
|
229
259
|
|
|
230
260
|
### 4. Phase: Pre-Review Cold Context (Optional, pre-dispatch validated)
|
|
231
261
|
|
|
@@ -271,7 +301,7 @@ if (result.rejected) {
|
|
|
271
301
|
|
|
272
302
|
Example safe query:
|
|
273
303
|
|
|
274
|
-
**Hand-off** — open the `wicked-garden-mem` skill and run its `recall` action with `<scenario-category> test rules` as the query; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog
|
|
304
|
+
**Hand-off** — open the `wicked-garden-mem` skill and run its `recall` action with `<scenario-category> test rules` as the query; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog; either way carry it out inline in this turn (no sub-agent), then continue here.
|
|
275
305
|
|
|
276
306
|
If the knowledge layer is absent, skip this phase entirely — no `context.md` is
|
|
277
307
|
written and the reviewer still has everything it needs (scenario + plan +
|
|
@@ -283,7 +313,7 @@ evidence).
|
|
|
283
313
|
It does NOT receive the executor's conversation, reasoning, or stdout/stderr directly.
|
|
284
314
|
Pass paths, not content, where possible.
|
|
285
315
|
|
|
286
|
-
**Hand-off** — open the `wicked-garden-qe-acceptance-test-reviewer` skill with the brief below as the argument; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog
|
|
316
|
+
**Hand-off** — open the `wicked-garden-qe-acceptance-test-reviewer` skill with the brief below as the argument; on Claude Code this is the Skill tool, on any other seat open the named skill from your catalog; either way carry it out inline in this turn (no sub-agent), then continue here.
|
|
287
317
|
|
|
288
318
|
```markdown
|
|
289
319
|
Review the evidence against the test plan assertions.
|
|
@@ -306,9 +336,11 @@ flag as CONTEXT_CONTAMINATION and return `VERDICT: FAIL` with
|
|
|
306
336
|
2. Read the test plan file at the path above
|
|
307
337
|
3. Read evidence files from the evidence directory (including context.md if present)
|
|
308
338
|
4. Evaluate each assertion against evidence
|
|
309
|
-
5. End with one plain-text line `VERDICT: PASS` or `VERDICT: FAIL`
|
|
310
|
-
|
|
311
|
-
CONTEXT_CONTAMINATION is FAIL with `reason: inconclusive — <why
|
|
339
|
+
5. End the review with one plain-text line `VERDICT: PASS` or `VERDICT: FAIL`
|
|
340
|
+
(never quote another VERDICT line); missing evidence or
|
|
341
|
+
CONTEXT_CONTAMINATION is FAIL with `reason: inconclusive — <why>`. Hand the
|
|
342
|
+
review back: `qe accept` still writes the verdict (step 6) and prints that
|
|
343
|
+
line last (garden#1290)
|
|
312
344
|
6. For any EQUIVALENT_TO_BASELINE assertion, also return the equivalence facet
|
|
313
345
|
{ baseline_ref, baseline_sha, method, diff_count, tolerance, matched } so the
|
|
314
346
|
orchestrator can persist it on the verdict (see `verdict.equivalence`).
|
|
@@ -394,7 +426,7 @@ const verdictRecord = store.create('verdicts', {
|
|
|
394
426
|
});
|
|
395
427
|
|
|
396
428
|
// 3. Materialize the public manifest at the contract path
|
|
397
|
-
|
|
429
|
+
const { buildManifest, emitBusEvent } = ledger; // the same resolved wicked-ledger as step 0
|
|
398
430
|
import { readFileSync } from 'node:fs';
|
|
399
431
|
const pkgVersion = JSON.parse(readFileSync('package.json','utf8')).version;
|
|
400
432
|
const runAfter = store.get('runs', run.id);
|
|
@@ -424,6 +456,9 @@ emitBusEvent('wicked.test.evidence.captured', {
|
|
|
424
456
|
|
|
425
457
|
### 7. Output
|
|
426
458
|
|
|
459
|
+
The reply's LAST line is the reviewer's `VERDICT: PASS` or `VERDICT: FAIL`, printed
|
|
460
|
+
only after step 6 wrote the verdict row. This is what ends the turn.
|
|
461
|
+
|
|
427
462
|
**Without `--json`** — Present the full verdict:
|
|
428
463
|
|
|
429
464
|
```markdown
|
|
@@ -475,7 +510,13 @@ WT_LIB="$(wicked-garden path scripts/qe/lib)"
|
|
|
475
510
|
## wicked-ledger resolution
|
|
476
511
|
|
|
477
512
|
`wicked-ledger` (npm) is the QE data layer — DomainStore, oracle queries, and
|
|
478
|
-
manifest building.
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
`.
|
|
513
|
+
manifest building. The snippets above load it through `{WT_LIB}/ledger-pkg.mjs`,
|
|
514
|
+
the one resolver the gate shares:
|
|
515
|
+
|
|
516
|
+
1. `$WICKED_LEDGER_PKG_DIR`. Inside a governed wicked-crew run it is set to crew's
|
|
517
|
+
own wicked-ledger, the package crew's acceptance check reads the verdict with.
|
|
518
|
+
Do not `npm i` in a governed run: a fenced seat is refused the install, and it
|
|
519
|
+
would change the tree under review.
|
|
520
|
+
2. otherwise, an install the target repo resolves (`npm i --no-save wicked-ledger`).
|
|
521
|
+
|
|
522
|
+
The pinned range lives in `.claude-plugin/plugin.json` → `wicked_ledger_version`.
|
|
@@ -133,6 +133,11 @@ python3 -c "import json,sys; sys.stdout.write(json.dumps({...}))" 2>/dev/null \
|
|
|
133
133
|
|
|
134
134
|
### 6. Compile Evidence Report
|
|
135
135
|
|
|
136
|
+
**Opened from `qe accept`** (garden#1290): your evidence report is an intermediate artifact of that
|
|
137
|
+
pipeline, not the end of the turn. Hand it back and the pipeline continues to the reviewer in the
|
|
138
|
+
same turn. Never end the turn on it, above all in a governed unit (`WICKED_RUN_ID` set), where your
|
|
139
|
+
last output is the unit's reply.
|
|
140
|
+
|
|
136
141
|
Return a text evidence report with all captured data:
|
|
137
142
|
|
|
138
143
|
```markdown
|
|
@@ -180,6 +180,9 @@ Review any specification notes from the test plan writer. Factor these into your
|
|
|
180
180
|
```markdown
|
|
181
181
|
## Overall Verdict
|
|
182
182
|
|
|
183
|
+
**Opened from `qe accept`** (garden#1290): hand this review back and continue. `qe accept` writes the
|
|
184
|
+
verdict row (its step 6) and then prints the `VERDICT:` line last; that, not this review, ends the turn.
|
|
185
|
+
|
|
183
186
|
### Status: {PASS | FAIL | PARTIAL | INCONCLUSIVE}
|
|
184
187
|
|
|
185
188
|
### Summary
|
|
@@ -26,6 +26,11 @@ Your test plans are designed so that:
|
|
|
26
26
|
|
|
27
27
|
You do NOT execute tests. You do NOT grade results. You produce test plans.
|
|
28
28
|
|
|
29
|
+
**Opened from `qe accept`** (garden#1290): your test plan is an intermediate artifact of that
|
|
30
|
+
pipeline, not the end of the turn. Hand it back and the pipeline continues to the executor in the
|
|
31
|
+
same turn. Never end the turn on it, above all in a governed unit (`WICKED_RUN_ID` set), where your
|
|
32
|
+
last output is the unit's reply.
|
|
33
|
+
|
|
29
34
|
## Why You Can Query Brain
|
|
30
35
|
|
|
31
36
|
You have `Skill` access so you can query the knowledge layer (wicked-estate,
|