@deeeed/metamask-harness 0.7.1 → 0.7.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/CHANGELOG.md +9 -0
- package/dist/cli-commands.js +1 -0
- package/dist/cli.js +2 -0
- package/dist/commands/recipe-quality.js +93 -0
- package/dist/mm-harness-cli.js +23 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.2
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **`recipe-quality build`** — the single worker surface for producing `recipe-quality.json`: fronts @farmslot/agent-runtime's canonical builder (no reimplementation), validates against @farmslot/protocol `RecipeQualityArtifact` before writing (invalid input writes nothing, exit 5 with a teaching escape naming the invalid field). New production dependency: `@farmslot/agent-runtime`.
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- `@farmslot/protocol` dependency raised to `^0.7.3` so one protocol version serves both the harness and the builder.
|
|
10
|
+
- The packed-install contract test now executes `recipe-quality build` from the published layout, guarding the new dependency's packaging path.
|
|
11
|
+
|
|
3
12
|
## 0.7.1
|
|
4
13
|
|
|
5
14
|
### Added
|
package/dist/cli-commands.js
CHANGED
|
@@ -16,6 +16,7 @@ const SPEC = {
|
|
|
16
16
|
{ name: "actions", desc: "List runnable recipe actions", flags: ["--json"] },
|
|
17
17
|
{ name: "doctor", desc: "Check harness/orchestration health", flags: ["--json", "--target", "--adapter", "--runtime-dir", "--expect-live", "--cdp-port"] },
|
|
18
18
|
{ name: "run", desc: "Execute a proof recipe", args: ["recipe.json"], flags: ["--list"] },
|
|
19
|
+
{ name: "recipe-quality", desc: "Build the recipe-quality artifact from compact JSON", args: ["build"], flags: ["--input", "--output", "--json"] },
|
|
19
20
|
{ name: "interactive", aliases: ["menu"], desc: "Interactive command menu" },
|
|
20
21
|
{ name: "prepare", desc: "Install harness (+ optional validate)", flags: ["--target", "--runtime-dir", "--json"] },
|
|
21
22
|
{ name: "runtime-status", desc: "Structured runtime status JSON", flags: ["--json", "--target", "--cdp-port", "--runtime-dir"] }
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ import { handleLaunch } from "./commands/launch/index.js";
|
|
|
17
17
|
import { handleLogs } from "./commands/logs.js";
|
|
18
18
|
import { handleDebug } from "./commands/debug.js";
|
|
19
19
|
import { handleFixtures } from "./commands/fixtures.js";
|
|
20
|
+
import { handleRecipeQuality } from "./commands/recipe-quality.js";
|
|
20
21
|
import { parseArgs, targetPath } from "./commands/parse-args.js";
|
|
21
22
|
import { runOneNode } from "./commands/run-engine.js";
|
|
22
23
|
const COMMANDS = {
|
|
@@ -121,6 +122,7 @@ async function main(argv) {
|
|
|
121
122
|
if (command === "logs") return handleLogs(argv.slice(1));
|
|
122
123
|
if (command === "debug") return handleDebug(argv.slice(1));
|
|
123
124
|
if (command === "fixtures") return handleFixtures(argv.slice(1), { runOneNode });
|
|
125
|
+
if (command === "recipe-quality") return handleRecipeQuality(argv.slice(1));
|
|
124
126
|
const handler = COMMANDS[command];
|
|
125
127
|
if (!handler) throw new Error(`Unknown command: ${command}`);
|
|
126
128
|
return handler(parseArgs(argv.slice(1), command));
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
buildRecipeQualityArtifact
|
|
5
|
+
} from "@farmslot/agent-runtime";
|
|
6
|
+
import { EXIT, usageOut } from "./shared.js";
|
|
7
|
+
import { optionFlag, optionString, parseArgs } from "./parse-args.js";
|
|
8
|
+
const BUILD_USAGE = "mm-harness recipe-quality build --input <compact.json> --output <path> [--json]";
|
|
9
|
+
function errorMessage(error) {
|
|
10
|
+
return error instanceof Error ? error.message : String(error);
|
|
11
|
+
}
|
|
12
|
+
function invalidOut(json, message, source) {
|
|
13
|
+
const userAction = `fix ${source} (${message}), then re-run: ${BUILD_USAGE}`;
|
|
14
|
+
if (json) {
|
|
15
|
+
console.log(
|
|
16
|
+
JSON.stringify(
|
|
17
|
+
{
|
|
18
|
+
schemaVersion: 1,
|
|
19
|
+
command: "recipe-quality",
|
|
20
|
+
action: "build",
|
|
21
|
+
status: "fail",
|
|
22
|
+
exitCode: EXIT.validation,
|
|
23
|
+
error: { code: "RECIPE_QUALITY_INVALID", message, userAction }
|
|
24
|
+
},
|
|
25
|
+
null,
|
|
26
|
+
2
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
} else {
|
|
30
|
+
console.error(`\u2717 mm-harness recipe-quality: ${message}
|
|
31
|
+
Next: ${userAction}`);
|
|
32
|
+
}
|
|
33
|
+
return EXIT.validation;
|
|
34
|
+
}
|
|
35
|
+
async function handleRecipeQuality(argv) {
|
|
36
|
+
const { positional, options } = parseArgs(argv, "recipe-quality");
|
|
37
|
+
const json = optionFlag(options, "json");
|
|
38
|
+
const action = positional[0];
|
|
39
|
+
if (action !== "build") {
|
|
40
|
+
const message = action ? `unknown action '${action}'` : "missing action";
|
|
41
|
+
return usageOut(json, "recipe-quality", message, BUILD_USAGE);
|
|
42
|
+
}
|
|
43
|
+
return buildArtifact(options, json);
|
|
44
|
+
}
|
|
45
|
+
function buildArtifact(options, json) {
|
|
46
|
+
const input = optionString(options, "input");
|
|
47
|
+
const output = optionString(options, "output");
|
|
48
|
+
if (!input) return usageOut(json, "recipe-quality", "missing --input <compact.json>", BUILD_USAGE);
|
|
49
|
+
if (!output) return usageOut(json, "recipe-quality", "missing --output <path>", BUILD_USAGE);
|
|
50
|
+
const inputPath = path.resolve(input);
|
|
51
|
+
let raw;
|
|
52
|
+
try {
|
|
53
|
+
raw = fs.readFileSync(inputPath, "utf8");
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return usageOut(
|
|
56
|
+
json,
|
|
57
|
+
"recipe-quality",
|
|
58
|
+
`cannot read --input ${input}: ${errorMessage(error)}`,
|
|
59
|
+
`write the compact recipe-quality JSON to that path, then: ${BUILD_USAGE}`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = JSON.parse(raw);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return invalidOut(json, `--input ${input} is not valid JSON: ${errorMessage(error)}`, `--input ${input}`);
|
|
67
|
+
}
|
|
68
|
+
let artifact;
|
|
69
|
+
try {
|
|
70
|
+
artifact = buildRecipeQualityArtifact(parsed);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return invalidOut(json, errorMessage(error), `--input ${input}`);
|
|
73
|
+
}
|
|
74
|
+
const outputPath = path.resolve(output);
|
|
75
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
76
|
+
fs.writeFileSync(outputPath, `${JSON.stringify(artifact, null, 2)}
|
|
77
|
+
`);
|
|
78
|
+
if (json) {
|
|
79
|
+
console.log(
|
|
80
|
+
JSON.stringify(
|
|
81
|
+
{ schemaVersion: 1, command: "recipe-quality", action: "build", status: "ok", outputPath: output, artifact },
|
|
82
|
+
null,
|
|
83
|
+
2
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
console.log(`\u2713 recipe-quality build \u2192 ${output} (verdict: ${artifact.verdict})`);
|
|
88
|
+
}
|
|
89
|
+
return EXIT.ok;
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
handleRecipeQuality
|
|
93
|
+
};
|
package/dist/mm-harness-cli.js
CHANGED
|
@@ -139,6 +139,28 @@ Example:
|
|
|
139
139
|
mm-harness doctor --adapter extension --target /path/to/checkout --cdp-port 6662 --expect-live
|
|
140
140
|
mm-harness doctor --adapter mobile --target /path/to/checkout`
|
|
141
141
|
},
|
|
142
|
+
{
|
|
143
|
+
name: "recipe-quality",
|
|
144
|
+
summary: "Build the recipe-quality artifact from a compact verdict JSON (validates before writing).",
|
|
145
|
+
example: "mm-harness recipe-quality build --input compact.json --output artifacts/recipe-quality.json",
|
|
146
|
+
helpText: `mm-harness recipe-quality build [flags]
|
|
147
|
+
|
|
148
|
+
Build artifacts/recipe-quality.json from the compact fields a recipe-quality pass
|
|
149
|
+
produces (verdict + reasons + optional guidance/dimensions/findings/delta/training).
|
|
150
|
+
The artifact is validated against the RecipeQualityArtifact schema before it is
|
|
151
|
+
written \u2014 an invalid input never reaches disk.
|
|
152
|
+
|
|
153
|
+
--input <compact.json> Compact verdict JSON: { "verdict": "pass|warn|fail", "reasons": [..],
|
|
154
|
+
"betterVersionGuidance"?: [..], "dimensions"?: {..}, "trainingFields"?: {..}, \u2026 }
|
|
155
|
+
--output <path> Where to write the built artifact (parent dirs created)
|
|
156
|
+
--json Machine-readable envelope { status, outputPath, artifact }
|
|
157
|
+
|
|
158
|
+
Exit: 0 built \xB7 2 missing/unreadable args \xB7 5 invalid input (teaching escape names the invalid field).
|
|
159
|
+
|
|
160
|
+
Example:
|
|
161
|
+
mm-harness recipe-quality build --input compact.json --output artifacts/recipe-quality.json
|
|
162
|
+
mm-harness recipe-quality build --input compact.json --output artifacts/recipe-quality.json --json`
|
|
163
|
+
},
|
|
142
164
|
{
|
|
143
165
|
name: "provision",
|
|
144
166
|
summary: "Install the cached Runway iOS dev client on a prepared mobile slot (no deps, no Metro).",
|
|
@@ -393,7 +415,7 @@ const HELP_GROUPS = [
|
|
|
393
415
|
{
|
|
394
416
|
title: "PROVE",
|
|
395
417
|
blurb: "run recipes and inspect readiness",
|
|
396
|
-
commands: ["run", "doctor"]
|
|
418
|
+
commands: ["run", "doctor", "recipe-quality"]
|
|
397
419
|
},
|
|
398
420
|
{
|
|
399
421
|
title: "RUNTIME OVERLAY",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deeeed/metamask-harness",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mm-harness": "bin/mm-harness"
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"check:syntax": "find . -name '*.mjs' -print0 | xargs -0 -n1 node --check"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@farmslot/
|
|
19
|
+
"@farmslot/agent-runtime": "^0.1.0",
|
|
20
|
+
"@farmslot/protocol": "^0.7.3",
|
|
20
21
|
"@farmslot/recipe-harness": "^0.3.3",
|
|
21
22
|
"commander": "^12.0.0",
|
|
22
23
|
"viem": "^2.54.3"
|