wicked-garden 12.58.0 → 12.59.0
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/components.json +2 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +20 -1
- package/install.mjs +28 -12
- package/package.json +1 -1
- package/schemas/README.md +1 -0
- package/schemas/build-guide.v1.json +210 -0
- package/scripts/build_guide/_guide.py +543 -0
- package/scripts/build_guide/check.py +116 -0
- package/scripts/build_guide/discover.py +250 -0
- package/scripts/build_guide/probe.py +114 -0
- package/scripts/build_guide/rehearse.py +405 -0
- package/scripts/domain/validate_domain_model.py +13 -1
- package/skills/build-guide/SKILL.md +203 -0
- package/skills/build-guide/assets/seeds/cargo-libtest.json +118 -0
- package/skills/build-guide/assets/seeds/pytest-short-summary.json +114 -0
- package/skills/build-guide/assets/seeds/vitest-junit.json +96 -0
- package/skills/build-guide/refs/contract-notes.md +161 -0
- package/skills/build-guide/refs/discover.md +72 -0
- package/skills/build-guide/refs/propose.md +47 -0
- package/skills/build-guide/refs/results.md +97 -0
- package/skills/core/SKILL.md +1 -0
- package/skills/core/refs/setup.md +7 -1
- package/skills/mcp-scaffold/assets/typescript/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"_comment": "Issue #328: Component declarations for wicked-garden plugin. Claude Code plugin.json does not yet support inline component declarations beyond path overrides. This manifest documents all components for tooling, validation, and future schema support. When plugin.json gains a 'components' field, merge this data into plugin.json. The plugin is skills-only: former commands/ became actions of consolidated per-domain skills, and former agents/ became standalone context:fork worker skills (enumerated under fork_skills). Regenerate derived blocks with scripts/ci/sync_components.py.",
|
|
3
3
|
"domains": ["agentic", "crew", "data", "demo", "engineering", "jam", "mem", "persona", "platform", "product", "qe", "search"],
|
|
4
4
|
"summary": {
|
|
5
|
-
"skills":
|
|
5
|
+
"skills": 139,
|
|
6
6
|
"fork_skills": 69,
|
|
7
7
|
"hooks": 13,
|
|
8
8
|
"specialists": 7
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"agentic-performance-analyst": ["agentic-performance-analyst"],
|
|
14
14
|
"agentic-safety-reviewer": ["agentic-safety-reviewer"],
|
|
15
15
|
"archetype": ["archetype"],
|
|
16
|
+
"build-guide": ["build-guide"],
|
|
16
17
|
"classify": ["classify"],
|
|
17
18
|
"core": ["core"],
|
|
18
19
|
"data": ["data"],
|
|
@@ -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.
|
|
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.59.0"}], "version": "12.59.0"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wicked-garden",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.59.0",
|
|
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.8.0",
|
|
6
6
|
"wicked_ledger_version": "^0.6.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wicked-garden",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.59.0",
|
|
4
4
|
"description": "The skills your coding agent can't build alone: \"done\" re-checked from evidence, graph-aware search and multi-file refactor, 40 QE specialists, review panels from other models, and cross-session memory. Works in Claude Code, Codex, Antigravity, OpenCode and Pi, in CI, or in a wicked-crew job.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coding-agent",
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [12.59.0] — 2026-10-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **`wicked-garden-build-guide`: discover how a repo builds and tests, and propose its build/test guide (#1332, DES-BUILD-GUIDE; pairs with wicked-core#1066).** The guide is `.wicked/build-guide.json` in contract v1. The wicked-core floor interprets it instead of hardcoding runners, and reads it from the base tree.
|
|
9
|
+
- **Discover.** `scripts/build_guide/discover.py` reads CI config first, then the manifests, follows `make`/`just`/`npm` one level into what they run, and lists every test candidate with its `file:line`. It holds no runner table. The agent then learns each runner's formats and its list, run-one and deselect flags from the runner's own `--version` and `--help`.
|
|
10
|
+
- **Results.** Structured results come first, but only when their ids round-trip through `list`, `alone` and `deselect`. Otherwise the skill writes a text parser: RE2-only, `^…$` rules on the runner's own final summary.
|
|
11
|
+
- **Validate.** The skill writes two mutation probes (`mutation`, `mutation2`), then runs `wicked-core floor probe`, which alone writes `verified`. It stops after at most 3 attempts per check. When the probe is unavailable, it says plainly that the guide is unverified and the floor will not use it for exclusion.
|
|
12
|
+
- **Propose.** The guide lands as a PR, or through the deliver gate inside a crew run. It is never written silently.
|
|
13
|
+
- **Scripts.** `check.py` validates a guide against `schemas/build-guide.v1.json`, vendored byte for byte from wicked-core main (72da31b, the file as #1066 landed it) and pinned to its git blob by a test. The stdlib validator implements `propertyNames`, so the schema's env-name rule is checked. For a test check (one with `list`), it flags what the floor requires: a non-empty `failedExit`, `alone`, `deselect`, a `text`/`junit` kind and two distinct mutation probes. It also flags a missing `version` piece and any required probe that did not pass. It reports the floor's load-time refusals in core's words: an empty `run`, a bad `stage`, a `list` with no `failedExit`, a `0` in `failedExit`, an invalid `cwd` (`""`, a `.` or empty segment, `..`, `\`, `:` or a drive), a check `name` that is not 1-64 of `A-Z a-z 0-9 . _ -` (or is `.`/`..`), an env name that is not `[A-Z_][A-Z0-9_]*` or is a loader/shell hook, and `{ids:re|}` among the per-id tokens or beside `{q}`. JUnit is read with a real XML parser (`xml.etree`), as core reads it with roxmltree. With `--repo`, it warns for every CI step that no check declares in that step's working directory. In the directories its checks cover, a guide's checks replace the floor's detection, so gates such as install, build and lint must be declared too, sub-packages included. `rehearse.py` mirrors the core probe (`list`, `run`, `mutation`, `ids`, `alone`, `deselect`, `multi`, `affected`, `version`) in a scratch copy. Like core, it needs a green clean run. When any probe fails, it re-runs the whole probe once on a fresh copy and records that retry, each result marked `(retried)`. It composes argvs around `--` as core does, and it skips gates. The skill tells the user to onboard from a green commit. `probe.py` wraps the core command, and the probe records `runnerVersion` from the check's `version` piece. Like core, `rehearse.py` runs the guide's `install` step for the check's `cwd` first in every fresh copy (a failed install fails every probe; with an install step nothing is linked to the host repo), and writes a mutation file only inside the copy, never through a link. A check name is unique per `cwd` (one `install` per directory). `discover.py` resolves a step's `make`/`just`/`npm` command against its own `working-directory`, ends a `- run: |` block at the step's other keys, and counts a CI wrapper whose recipe runs the tests (`make check`) as a candidate; `check.py --repo` counts a recipe as declared only when every command in it is, reports a schema-invalid guide instead of crashing, and no longer flags an escaped metacharacter (`C\++`) as a non-RE2 construct.
|
|
14
|
+
- **Seeds** for cargo/libtest (reconciled with wicked-core's own probed guide: merged stderr, binary-qualified ids), pytest (text on the short summary, `--force-short-summary`) and vitest (JUnit, `results.id: ["name"]`); each test check carries two mutation probes and a `version` piece, and each seed declares its fixture's CI gates.
|
|
15
|
+
- **Onboarding.** Full onboarding in `wicked-garden-core` `setup` (step E) hands off to it.
|
|
16
|
+
- **Tests and evals.** `tests/build_guide/` holds real-runner tests on five fixture repos: cargo with a text parser, pytest with JUnit, vitest with a JUnit reporter, a fake runner with no structured output, and a repo with no tests. It also holds five eval cases with a deterministic grader.
|
|
17
|
+
- **Contract notes.** The skill's `refs/contract-notes.md` records the pinned semantics and the coordinator's rulings: `{id:re}`/`{ids:re|}` regex placeholders, the `version` piece, retry once, exit-code classes, and guide checks replacing detection. It also explains why the pytest seed is text: JUnit cannot rebuild a class method's node id.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Constrain the MCP TypeScript template's `@opentelemetry/api` dependency to `~1.9.0`, so a fresh `npm install` no longer hits the `@opentelemetry/sdk-logs` peer conflict now that API 1.10.0 is published (#1344).
|
|
21
|
+
- **`install.mjs` finds a binary on PATH without spawning a shell (#1345).** `findBin` ran `command -v` (`where` on Windows) under a 2-second timeout, so on a loaded machine a slow fork read as "not installed": `pack check` said Python was missing, and `install` skipped `uv sync` as if uv were absent. Found by the build guide's floor probe on a host at load 50-110, where `tests/packs/*` and `test_uv_sync_failure_is_surfaced_not_swallowed` failed for that reason alone. It now scans PATH itself and returns the absolute path of the first executable file `command -v` or `where` would name: an empty POSIX entry is the current directory, a relative entry is read against the current directory, and Windows looks in the current directory first and tries each `PATHEXT` extension unless the name already ends with one. The dry-run spawn-guard test's positive control now plants a `python3` on PATH, and its negative plants a `uv` the install would run; new tests pin that uv is found without a child process, that a non-executable file is not a binary, and that relative and empty PATH entries resolve as `command -v` resolves them.
|
|
22
|
+
|
|
5
23
|
## [12.58.0] — 2026-10-20
|
|
6
24
|
|
|
7
25
|
### Added
|
|
@@ -1179,7 +1197,8 @@ through `v9.2.18`. Major themes across that span:
|
|
|
1179
1197
|
|
|
1180
1198
|
For each of those releases, see the corresponding tag in git history.
|
|
1181
1199
|
|
|
1182
|
-
[Unreleased]: https://github.com/mikeparcewski/wicked-garden/compare/v12.
|
|
1200
|
+
[Unreleased]: https://github.com/mikeparcewski/wicked-garden/compare/v12.59.0...HEAD
|
|
1201
|
+
[12.59.0]: https://github.com/mikeparcewski/wicked-garden/compare/v12.58.0...v12.59.0
|
|
1183
1202
|
[12.58.0]: https://github.com/mikeparcewski/wicked-garden/compare/v12.57.0...v12.58.0
|
|
1184
1203
|
[12.57.0]: https://github.com/mikeparcewski/wicked-garden/compare/v12.56.0...v12.57.0
|
|
1185
1204
|
[12.56.0]: https://github.com/mikeparcewski/wicked-garden/compare/v12.55.1...v12.56.0
|
package/install.mjs
CHANGED
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
* diagnostic names where the previous and the failed trees were left).
|
|
50
50
|
*/
|
|
51
51
|
import {
|
|
52
|
-
closeSync, constants, cpSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync,
|
|
53
|
-
readdirSync, readFileSync, realpathSync, renameSync, rmSync,
|
|
52
|
+
accessSync, closeSync, constants, cpSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync,
|
|
53
|
+
readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync,
|
|
54
54
|
} from "node:fs";
|
|
55
|
-
import { join, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
55
|
+
import { delimiter, join, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
56
56
|
import { homedir } from "node:os";
|
|
57
57
|
import { fileURLToPath } from "node:url";
|
|
58
58
|
import { randomBytes } from "node:crypto";
|
|
59
|
-
import {
|
|
59
|
+
import { spawnSync } from "node:child_process";
|
|
60
60
|
|
|
61
61
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
62
62
|
const pkg = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf8"));
|
|
@@ -97,16 +97,32 @@ function skip(src) {
|
|
|
97
97
|
return false;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// The first `name` on PATH, as `command -v` (POSIX) or `where` (Windows) would find it, read from
|
|
101
|
+
// the filesystem: no subprocess. The old `command -v` spawn had a 2 s timeout, and on a loaded
|
|
102
|
+
// machine a slow fork read as "not installed": pack tooling said Python was missing, and `install`
|
|
103
|
+
// skipped `uv sync` as if uv were absent. Parity with those commands: an empty POSIX entry is the
|
|
104
|
+
// current directory; Windows looks in the current directory first and tries each PATHEXT extension
|
|
105
|
+
// (unless the name already ends with one). The result is absolute, so a caller may run it from
|
|
106
|
+
// another working directory.
|
|
100
107
|
function findBin(name) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
const win = process.platform === "win32";
|
|
109
|
+
const pathext = (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
110
|
+
const exts = win && !pathext.some((e) => name.toLowerCase().endsWith(e.toLowerCase())) ? pathext : [""];
|
|
111
|
+
const dirs = (process.env.PATH || "").split(delimiter).map((d) => (d === "" && !win ? "." : d)).filter(Boolean);
|
|
112
|
+
if (win) dirs.unshift(".");
|
|
113
|
+
for (const dir of dirs) {
|
|
114
|
+
for (const ext of exts) {
|
|
115
|
+
const candidate = resolve(dir, name + ext);
|
|
116
|
+
try {
|
|
117
|
+
if (!statSync(candidate).isFile()) continue;
|
|
118
|
+
if (!win) accessSync(candidate, constants.X_OK);
|
|
119
|
+
return candidate;
|
|
120
|
+
} catch {
|
|
121
|
+
// not here, or not executable: keep looking
|
|
122
|
+
}
|
|
123
|
+
}
|
|
109
124
|
}
|
|
125
|
+
return undefined;
|
|
110
126
|
}
|
|
111
127
|
|
|
112
128
|
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wicked-garden",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.59.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The skills your coding agent can't build alone: \"done\" re-checked from evidence, graph-aware search and multi-file refactor, 40 QE specialists, review panels from other models, and cross-session memory. Works in Claude Code, Codex, Antigravity, OpenCode and Pi, in CI, or in a wicked-crew job.",
|
|
6
6
|
"keywords": [
|
package/schemas/README.md
CHANGED
|
@@ -26,6 +26,7 @@ cosmetic and pre-dates them):
|
|
|
26
26
|
| Schema | Format it defines | Version field | Validated by |
|
|
27
27
|
|--------|-------------------|---------------|--------------|
|
|
28
28
|
| `wicked-pack.schema.json` | Third-party skill-pack manifest (`wicked-pack.json`) | `spec` (currently 1) | `npx wicked-garden pack check <dir>` (`scripts/pack/check.py`) |
|
|
29
|
+
| `build-guide.v1.json` | A repo's build/test guide (`.wicked/build-guide.json`, DES-BUILD-GUIDE contract v1). **Vendored byte for byte from wicked-core** main (re-vendor whenever core's copy changes) | `version` (1) | `scripts/build_guide/check.py`; `tests/build_guide/test_build_guide_check.py` pins the copy to core's git blob |
|
|
29
30
|
| `campaign-recon.schema.json` | qe campaign recon + plan artifact (capability inventory, environment-manifest ref, dependency-ordered scenario ladder with pass criteria, claim ceilings and per-rung `isolation` — ADR 0006) | `spec` (1 \| 2 — v2 is the TH-16+TH-22 shared bump: rung `isolation` + desktop stub-eligibility; v1 plans still validate) | `tests/qe/test_campaign_recon_schema.py` (fixture round-trip + nonconforming rejection). The sibling evidence contract (`scenario_evidence` + `claim_level`) is owned by wicked-ledger (manifest 2.1). |
|
|
30
31
|
|
|
31
32
|
## Usage
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://wickedagile.com/schemas/build-guide.v1.json",
|
|
4
|
+
"title": "Build guide (DES-BUILD-GUIDE, contract v1)",
|
|
5
|
+
"description": "A repository's build/test guide: `.wicked/build-guide.json`, committed, read by the repo-checks floor from the BASE tree only. When the base carries a guide, its `checks` (for the stage) ARE the floor's checks for the directories they cover (their `cwd`s, at any stage): there their argv, cwd and stage replace detection (a build, lint or install step is declared as a check), while a detected package no check covers keeps its detected checks, exit codes only. A STALE guide (a `derivedFrom` file changed on the base since the guide was last committed or since a check was verified, or the change touches one) may name outdated commands: in the directories it covers, the floor then runs the UNION of its checks and the detected ones (an identical argv in the same directory once), more checks and never fewer. Accepted by design: a directory whose checks are all `verify`-only has no checks at the creator floor; the creator floor is fast feedback, and the verify floor runs every check before delivery. With no guide, or one that does not parse or fails the load-time checks (a non-empty `run`, `stage` values, `failedExit` on a check with a `list`), detection is the whole floor. Each check's pieces are checked by `wicked-core floor probe`; the floor relies on a check's exclusion only when every probe passed on a commit that is an ancestor of the base, no `derivedFrom` or `invalidatedBy` file changed on the base since, and the change touches neither (a deletion, a rename's old path and a type change, such as a file replaced by a link, count as touching). All regexes are RE2 syntax, applied to one line at a time.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "checks"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"version": { "const": 1 },
|
|
11
|
+
"derivedFrom": {
|
|
12
|
+
"description": "Repo-relative paths (git pathspecs: globs such as `crates/*/Cargo.toml` match) the guide was derived from (CI files, manifests): a change to one, on the base since the guide or a check's verification or in the change itself, makes the guide stale: no check's exclusion is relied on, and detection runs beside the guide's checks where they cover a directory.",
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": { "type": "string" }
|
|
15
|
+
},
|
|
16
|
+
"checks": { "type": "array", "items": { "$ref": "#/$defs/check" } }
|
|
17
|
+
},
|
|
18
|
+
"$defs": {
|
|
19
|
+
"argv": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
20
|
+
"regex": { "type": "string", "minLength": 1 },
|
|
21
|
+
"mutation": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"required": ["file", "content", "expectId"],
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"properties": {
|
|
26
|
+
"file": { "type": "string", "description": "Relative to `cwd`." },
|
|
27
|
+
"content": { "type": "string", "description": "A deliberately failing test." },
|
|
28
|
+
"expectId": { "type": "string" },
|
|
29
|
+
"expectQ": { "type": "string" }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"check": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"description": "A test check has a `list` (and so `results`); a gate check (a build, a lint, an install) has neither and gates on its exit code alone. A check named `install` is the floor's install step: the install timeout, never compared with the base, and a failure reads as an environment finding; declare it before the checks that need it (the floor's sandbox confines writes, not the network). `version` is for test checks only.",
|
|
35
|
+
"required": ["name", "run"],
|
|
36
|
+
"dependentRequired": { "list": ["results", "failedExit"], "version": ["list"] },
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"properties": {
|
|
39
|
+
"name": { "type": "string", "pattern": "^(?!\\.\\.?$)[A-Za-z0-9._-]{1,64}$", "description": "1-64 of `A-Z a-z 0-9 . _ -`, never `.` or `..` (it keys files the engine writes). A check named `install` is the floor's install step." },
|
|
40
|
+
"cwd": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"default": ".",
|
|
43
|
+
"description": "Relative to the repo root: `.` or `/`-separated segments, none empty, `.` or `..`, and no `\\` or `:` (no Windows drive).",
|
|
44
|
+
"pattern": "^(\\.|(?!.*(^|/)\\.\\.?(/|$))[^/\\\\:]+(/[^/\\\\:]+)*)$"
|
|
45
|
+
},
|
|
46
|
+
"stage": {
|
|
47
|
+
"description": "The floor stages the check runs at; absent or empty = both.",
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": { "enum": ["creator", "verify"] }
|
|
50
|
+
},
|
|
51
|
+
"run": {
|
|
52
|
+
"$ref": "#/$defs/argv",
|
|
53
|
+
"description": "The exact argv. Exclusion happens only for a floor check whose argv equals this exactly: the guide is the allowlist."
|
|
54
|
+
},
|
|
55
|
+
"failedExit": {
|
|
56
|
+
"description": "Exit codes that mean 'tests failed'. Any other non-zero exit (a crash, a build error) decides the check `could_not_run`. A failing exit whose results name no test gives the base no candidates (`base_red_unseparated`), and a deselected head run that fails with nothing named is still a failure (`new_failure`): exclusion never passes a run that failed.",
|
|
57
|
+
"type": "array",
|
|
58
|
+
"minItems": 1,
|
|
59
|
+
"items": { "type": "integer", "not": { "const": 0 } }
|
|
60
|
+
},
|
|
61
|
+
"results": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"required": ["kind"],
|
|
64
|
+
"additionalProperties": false,
|
|
65
|
+
"properties": {
|
|
66
|
+
"kind": {
|
|
67
|
+
"enum": ["text", "junit", "json-lines", "tap"],
|
|
68
|
+
"description": "v1 reads `text` and `junit`; `json-lines` and `tap` are reserved."
|
|
69
|
+
},
|
|
70
|
+
"how": {
|
|
71
|
+
"type": "object",
|
|
72
|
+
"additionalProperties": false,
|
|
73
|
+
"properties": {
|
|
74
|
+
"argvAppend": {
|
|
75
|
+
"description": "Added to every argv whose results are read (the base run, the probes' runs). Composition with an argv that has an end of options (`--`), for this and for `deselect.append`: the tokens before the list's own `--` (all of them when it has none) go just before the argv's `--` (at the end when it has none); the tokens after it go last, behind ONE `--`. A second `--` is never emitted.",
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": { "type": "string" }
|
|
78
|
+
},
|
|
79
|
+
"env": { "type": "object", "propertyNames": { "pattern": "^(?!(LD_|DYLD_))(?!(BASH_ENV|ENV|SHELLOPTS|BASHOPTS|IFS|GCONV_PATH|LOCPATH)$)[A-Z_][A-Z0-9_]*$" }, "additionalProperties": { "type": "string" }, "description": "Set on the command INSIDE the floor sandbox only (never on the sandbox launcher). Names are `[A-Z_][A-Z0-9_]*` and never a loader or shell hook: `LD_*`, `DYLD_*`, `BASH_ENV`, `ENV`, `SHELLOPTS`, `BASHOPTS`, `IFS`, `GCONV_PATH`, `LOCPATH`." },
|
|
80
|
+
"path": { "type": "string", "description": "The results file, relative to `cwd`, when not stdout." },
|
|
81
|
+
"merge": {
|
|
82
|
+
"type": "boolean",
|
|
83
|
+
"description": "Capture stderr into the same stream as stdout, in order (a runner that names its test binaries on stderr)."
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"id": {
|
|
88
|
+
"description": "(junit) The testcase attributes whose values, joined by `idJoin`, form an id. Default [\"classname\", \"name\"].",
|
|
89
|
+
"type": "array",
|
|
90
|
+
"items": { "type": "string" }
|
|
91
|
+
},
|
|
92
|
+
"idJoin": {
|
|
93
|
+
"description": "(junit) What joins the `id` attributes (default `::`), so the ids can be the list's.",
|
|
94
|
+
"type": "string"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"parser": {
|
|
99
|
+
"description": "Only for results.kind = text.",
|
|
100
|
+
"type": "object",
|
|
101
|
+
"additionalProperties": false,
|
|
102
|
+
"properties": {
|
|
103
|
+
"section": {
|
|
104
|
+
"$ref": "#/$defs/regex",
|
|
105
|
+
"description": "Lines that open a qualifier scope (a test binary), with a named group `q`; ids are (q, id)."
|
|
106
|
+
},
|
|
107
|
+
"failed": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": { "$ref": "#/$defs/regex" },
|
|
110
|
+
"description": "Per-line failures, each with a named group `id`."
|
|
111
|
+
},
|
|
112
|
+
"blocks": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"required": ["start", "item", "end"],
|
|
117
|
+
"additionalProperties": false,
|
|
118
|
+
"properties": {
|
|
119
|
+
"start": { "$ref": "#/$defs/regex" },
|
|
120
|
+
"item": { "$ref": "#/$defs/regex", "description": "With a named group `id`." },
|
|
121
|
+
"end": { "$ref": "#/$defs/regex" },
|
|
122
|
+
"use": {
|
|
123
|
+
"enum": ["last-before-end", "all"],
|
|
124
|
+
"default": "last-before-end",
|
|
125
|
+
"description": "A block is the contiguous item lines (blank lines allowed) after a start; any other line ends it. At an end, the last block since the previous end (or every one) is taken."
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"list": {
|
|
133
|
+
"type": "object",
|
|
134
|
+
"required": ["run", "item"],
|
|
135
|
+
"additionalProperties": false,
|
|
136
|
+
"properties": {
|
|
137
|
+
"run": { "$ref": "#/$defs/argv" },
|
|
138
|
+
"item": { "$ref": "#/$defs/regex", "description": "With a named group `id`." },
|
|
139
|
+
"section": {
|
|
140
|
+
"$ref": "#/$defs/regex",
|
|
141
|
+
"description": "With a named group `q`. Without it ids carry no qualifier, and results are compared by id alone."
|
|
142
|
+
},
|
|
143
|
+
"merge": { "type": "boolean" }
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"alone": {
|
|
147
|
+
"type": "object",
|
|
148
|
+
"required": ["run"],
|
|
149
|
+
"additionalProperties": false,
|
|
150
|
+
"properties": { "run": { "$ref": "#/$defs/argv", "description": "With `{id}` (and optionally `{q}`, `{id:re}`, `{ids:re|}`, as in `deselect.append`): values fill whole argv elements and never pass through a shell, so no escaping is needed." } }
|
|
151
|
+
},
|
|
152
|
+
"deselect": {
|
|
153
|
+
"type": "object",
|
|
154
|
+
"required": ["append"],
|
|
155
|
+
"additionalProperties": false,
|
|
156
|
+
"properties": {
|
|
157
|
+
"append": {
|
|
158
|
+
"type": "array",
|
|
159
|
+
"items": { "type": "string" },
|
|
160
|
+
"description": "`{ids:re|}` and `{q}` never appear in the same `deselect.append` (the pattern cannot bind ids to qualifiers). Tokens before the first one with `{id}`/`{q}` are appended once, the tokens from the first through the last such one are repeated once per id, the rest once. So a flag and its value must be ONE token (`--skip={id}`, not `--skip`, `{id}`). `{id}`/`{q}` values fill whole argv elements verbatim and never pass through a shell: no escaping is needed. For a runner that takes a regex: `{id:re}` is the id regex-escaped, repeated per id like `{id}`; `{ids:re|}` is EVERY id, regex-escaped and joined by `|`, in ONE token that is never repeated (`--testNamePattern=^(?!(?:{ids:re|})$)`); a guide that puts `{ids:re|}` among the per-id tokens is refused. The tokens are then composed onto the argv around its `--` (see `results.how.argvAppend`)."
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"affected": {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"required": ["run"],
|
|
167
|
+
"additionalProperties": false,
|
|
168
|
+
"properties": { "run": { "$ref": "#/$defs/argv", "description": "With `{files}`; absent = the full run at every stage." } }
|
|
169
|
+
},
|
|
170
|
+
"version": {
|
|
171
|
+
"description": "The runner's version command. `floor probe` runs it and records its first output line (stdout and stderr merged) as `verified.runnerVersion`; the floor runs it too, and a check whose runner now prints something else is stale (exit codes only).",
|
|
172
|
+
"type": "object",
|
|
173
|
+
"required": ["run"],
|
|
174
|
+
"additionalProperties": false,
|
|
175
|
+
"properties": { "run": { "$ref": "#/$defs/argv" } }
|
|
176
|
+
},
|
|
177
|
+
"invalidatedBy": {
|
|
178
|
+
"description": "Globs (`**`, `*`, `?`): a file that matches one, changed on the base since the check was verified or touched by the change (deleted, renamed away or type-changed included), disables exclusion for this check.",
|
|
179
|
+
"type": "array",
|
|
180
|
+
"items": { "type": "string" }
|
|
181
|
+
},
|
|
182
|
+
"probes": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"additionalProperties": false,
|
|
185
|
+
"properties": {
|
|
186
|
+
"mutation": { "$ref": "#/$defs/mutation" },
|
|
187
|
+
"mutation2": {
|
|
188
|
+
"$ref": "#/$defs/mutation",
|
|
189
|
+
"description": "A second deliberately failing test (another file): with both written, both must be parsed and deselecting both must run clean."
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"verified": {
|
|
194
|
+
"description": "Written by `wicked-core floor probe`, which first runs the guide's `install` check for the same `cwd` in every fresh copy it probes (an install that fails fails every probe). `results` keys: list, run, ids, alone, deselect, mutation, multi, plus affected and version when the check has that piece. The probes need a green clean run. When any probe fails, the whole probe re-runs once on a fresh copy and that retry's results are recorded, each marked ` (retried)`: `pass (retried)` counts as a pass, `fail: … (retried)` does not.",
|
|
195
|
+
"type": "object",
|
|
196
|
+
"additionalProperties": false,
|
|
197
|
+
"properties": {
|
|
198
|
+
"baseSha": { "type": "string" },
|
|
199
|
+
"runnerVersion": { "type": "string", "description": "The `version` command's first output line when the probes ran; empty without a `version` piece." },
|
|
200
|
+
"at": { "type": "string" },
|
|
201
|
+
"results": {
|
|
202
|
+
"type": "object",
|
|
203
|
+
"additionalProperties": { "type": "string", "pattern": "^(pass( \\(retried\\))?|fail: .*)$" }
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|