@deeeed/metamask-harness 0.92.21 → 0.92.23

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.
@@ -1,242 +0,0 @@
1
- import { EXIT } from "@farmslot/recipe-cli/harness";
2
- import { spawnSync } from "node:child_process";
3
- import fs from "node:fs";
4
- import { createRequire } from "node:module";
5
- import path from "node:path";
6
- import { HANDOFF_INPUT } from "@farmslot/agent-runtime";
7
- import { enumerateChecklistCheckboxes, isTerminalWorkerSignalStatus } from "@farmslot/protocol";
8
- const require2 = createRequire(import.meta.url);
9
- const MARK_SCRIPT = require2.resolve(
10
- "@farmslot/agent-runtime/scripts/mark-checklist-step.cjs"
11
- );
12
- const { resolveChecklistPaths } = require2(
13
- "@farmslot/agent-runtime/scripts/checklist-target.cjs"
14
- );
15
- const { readSubtaskIndex, SubtaskRefusal } = require2("@farmslot/agent-runtime/scripts/subtask-unit.cjs");
16
- const USAGE = "mm-harness checklist <mark <task-dir> <step> | closeout <task-dir>> [options]";
17
- const CHECKLIST_VALUE_OPTIONS = /* @__PURE__ */ new Set([
18
- "--reason",
19
- "--checklist",
20
- "--signal",
21
- "--config",
22
- "--destination",
23
- "--metadata"
24
- ]);
25
- function parseChecklistArgv(argv) {
26
- const positionals = [];
27
- for (let index = 0; index < argv.length; index += 1) {
28
- const arg = argv[index] ?? "";
29
- if (arg.startsWith("-")) {
30
- const option = arg.split("=", 1)[0] ?? arg;
31
- if (CHECKLIST_VALUE_OPTIONS.has(option) && !arg.includes("=")) index += 1;
32
- continue;
33
- }
34
- positionals.push({ index, value: arg });
35
- }
36
- const consumed = new Set(positionals.slice(0, 2).map(({ index }) => index));
37
- return {
38
- action: positionals[0]?.value,
39
- taskDir: positionals[1]?.value,
40
- step: positionals[2]?.value,
41
- forwarded: argv.filter((_, index) => !consumed.has(index))
42
- };
43
- }
44
- function handoffCommand() {
45
- if (process.env.HANDOFF_BIN) {
46
- try {
47
- fs.accessSync(process.env.HANDOFF_BIN, fs.constants.X_OK);
48
- return { command: process.env.HANDOFF_BIN, prefix: [] };
49
- } catch {
50
- return { command: process.execPath, prefix: [process.env.HANDOFF_BIN] };
51
- }
52
- }
53
- return {
54
- command: process.execPath,
55
- prefix: [require2.resolve("@farmslot/handoff/cli")]
56
- };
57
- }
58
- function closeoutArgs(taskDir, args) {
59
- const normalized = args.flatMap((arg) => {
60
- const option = ["--config", "--destination", "--metadata"].find(
61
- (name) => arg.startsWith(`${name}=`)
62
- );
63
- return option ? [option, arg.slice(option.length + 1)] : [arg];
64
- });
65
- if (process.env.METAMASK_AGENTIC_LEARNINGS_DIR && !normalized.includes("--destination")) {
66
- return [
67
- "closeout",
68
- taskDir,
69
- ...normalized,
70
- "--destination",
71
- process.env.METAMASK_AGENTIC_LEARNINGS_DIR
72
- ];
73
- }
74
- return ["closeout", taskDir, ...normalized];
75
- }
76
- function runCloseout(taskDir, args, stdio) {
77
- try {
78
- const { command, prefix } = handoffCommand();
79
- return spawnSync(command, [...prefix, ...closeoutArgs(taskDir, args)], {
80
- encoding: "utf8",
81
- stdio
82
- });
83
- } catch (error) {
84
- const message = error instanceof Error ? error.message : String(error);
85
- return {
86
- status: 1,
87
- stdout: "",
88
- stderr: message,
89
- error: new Error(message)
90
- };
91
- }
92
- }
93
- function stageLearningPackage(taskDir, step, markArgs) {
94
- if (!["complete", "no-change"].includes(step ?? "") || markArgs.includes("--skip-learnings") || !fs.existsSync(path.join(taskDir, HANDOFF_INPUT))) {
95
- return;
96
- }
97
- try {
98
- const result = runCloseout(taskDir, ["--json"], "pipe");
99
- if (result.status === 0) return;
100
- } catch {
101
- }
102
- console.error(
103
- `Warning: learning capture could not be staged; rerun: mm-harness checklist closeout ${taskDir}; task verdict is unchanged.`
104
- );
105
- }
106
- function terminalSignalStatus(taskDir) {
107
- const { signalPath } = resolveChecklistPaths(taskDir);
108
- let signal;
109
- try {
110
- signal = JSON.parse(fs.readFileSync(signalPath, "utf8"));
111
- } catch {
112
- return null;
113
- }
114
- return isTerminalWorkerSignalStatus(signal.status) ? signal.status ?? null : null;
115
- }
116
- function preserveTerminalSignal(taskDir, step) {
117
- if (step !== "start" && numericMarkStep(step) === null) return false;
118
- const status = terminalSignalStatus(taskDir);
119
- if (!status) return false;
120
- console.log(
121
- `signal already terminal: status=${status}; ignoring non-terminal mark ${step}`
122
- );
123
- return true;
124
- }
125
- function numericMarkStep(step) {
126
- const stepNumber = Number(step);
127
- return Number.isInteger(stepNumber) && stepNumber >= 1 ? stepNumber : null;
128
- }
129
- function checklistStepRequiresDiffPass(checklist, stepNumber) {
130
- const step = enumerateChecklistCheckboxes(checklist).find((item) => item.stepNumber === stepNumber);
131
- return step !== void 0 && /mm-harness check diff/u.test(step.rawLabel);
132
- }
133
- function checkDiffGateReady(taskDir, step, parentChecklist) {
134
- const stepNumber = numericMarkStep(step);
135
- if (stepNumber === null) return true;
136
- const taskPath = parentChecklist ? path.join(taskDir, parentChecklist) : resolveChecklistPaths(taskDir).taskPath;
137
- let checklist = "";
138
- try {
139
- checklist = fs.readFileSync(taskPath, "utf8");
140
- } catch {
141
- return true;
142
- }
143
- if (!checklistStepRequiresDiffPass(checklist, stepNumber)) return true;
144
- return checkDiffSummaryReady(taskDir, step);
145
- }
146
- function checkDiffSummaryReady(taskDir, step) {
147
- const summaryPath = path.join(
148
- taskDir,
149
- "artifacts",
150
- "validation-summary.json"
151
- );
152
- try {
153
- const summary = JSON.parse(fs.readFileSync(summaryPath, "utf8"));
154
- if (summary.command === "check" && summary.action === "diff" && summary.status === "pass") {
155
- return true;
156
- }
157
- } catch {
158
- }
159
- console.error(
160
- `check-diff gate ${step} requires a task-local PASS at ${summaryPath}`
161
- );
162
- console.error(
163
- `Run: mm-harness check diff [--fix] --artifacts-dir ${path.dirname(summaryPath)}`
164
- );
165
- console.error("Then rerun the same checklist mark command.");
166
- return false;
167
- }
168
- function teachRecipeCompletion(taskDir, step) {
169
- if (step !== "complete") return;
170
- const artifactsDir = path.join(taskDir, "artifacts");
171
- if (!fs.existsSync(path.join(artifactsDir, "recipe.json"))) return;
172
- const qualityPath = path.join(artifactsDir, "recipe-quality.json");
173
- const coveragePath = path.join(artifactsDir, "recipe-coverage.md");
174
- const missingQuality = !fs.existsSync(qualityPath);
175
- const missingCoverage = !fs.existsSync(coveragePath);
176
- if (!missingQuality && !missingCoverage) return;
177
- console.error("Recipe completion needs two closure artifacts; derive them from the real recipe run and evidence (do not stub them):");
178
- if (missingCoverage) {
179
- console.error(` - ${coveragePath}: map each proof target to its recipe node and evidence, or record a reasoned N/A.`);
180
- }
181
- if (missingQuality) {
182
- const compactPath = path.join(artifactsDir, "recipe-quality-input.json");
183
- console.error(" First run: mm-harness help");
184
- console.error(` - ${qualityPath}: write ${compactPath} as:`);
185
- console.error(' {"verdict":"pass|warn|fail","reasons":["evidence-backed reason"]}');
186
- console.error(` then run: mm-harness recipe-quality build --input ${compactPath} --output ${qualityPath}`);
187
- }
188
- console.error("Then rerun the same checklist complete command.");
189
- }
190
- async function handleChecklist(argv) {
191
- const { action, taskDir, step, forwarded } = parseChecklistArgv(argv);
192
- if (!taskDir) {
193
- console.error(`usage: ${USAGE}`);
194
- return EXIT.usage;
195
- }
196
- const resolvedTaskDir = path.resolve(taskDir);
197
- if (action === "closeout") {
198
- const result2 = runCloseout(resolvedTaskDir, forwarded, "inherit");
199
- if (result2.error) {
200
- console.error(`mm-harness checklist closeout: ${result2.error.message}`);
201
- return EXIT.runtime;
202
- }
203
- return result2.status ?? EXIT.runtime;
204
- }
205
- if (action !== "mark" || !step) {
206
- console.error(`usage: ${USAGE}`);
207
- return EXIT.usage;
208
- }
209
- if (preserveTerminalSignal(resolvedTaskDir, step)) return EXIT.ok;
210
- if (step === "sub" && forwarded[2] === "complete") {
211
- try {
212
- const unit = readSubtaskIndex(resolvedTaskDir)?.units.find((unit2) => unit2.id === forwarded[1]);
213
- if (unit && !checkDiffGateReady(resolvedTaskDir, String(unit.parent.stepNumber), unit.parent.checklist)) return EXIT.runtime;
214
- } catch (error) {
215
- if (!(error instanceof SubtaskRefusal)) throw error;
216
- console.error(error.message);
217
- return error.code;
218
- }
219
- }
220
- if (!checkDiffGateReady(resolvedTaskDir, step)) return EXIT.runtime;
221
- teachRecipeCompletion(resolvedTaskDir, step);
222
- const result = spawnSync(
223
- process.execPath,
224
- [MARK_SCRIPT, resolvedTaskDir, ...forwarded],
225
- { stdio: "inherit" }
226
- );
227
- if (result.error) {
228
- console.error(`mm-harness checklist mark: ${result.error.message}`);
229
- return EXIT.runtime;
230
- }
231
- const status = result.status ?? EXIT.runtime;
232
- if (status === EXIT.ok) {
233
- stageLearningPackage(resolvedTaskDir, step, forwarded);
234
- }
235
- return status;
236
- }
237
- export {
238
- checkDiffSummaryReady,
239
- handleChecklist,
240
- runCloseout,
241
- teachRecipeCompletion
242
- };
@@ -1,57 +0,0 @@
1
- import { optionFlag, optionString, parseArgs, targetPath, usageError } from "@farmslot/recipe-cli/harness";
2
- import {
3
- changedFiles,
4
- classifyDomain,
5
- configPath,
6
- discoverLibraries,
7
- readConfig,
8
- REVIEW_ADAPTERS
9
- } from "../review/knowledge.js";
10
- import { adapterFromOptions } from "./review.js";
11
- async function handleDomain(argv) {
12
- const parsed = parseArgs(argv);
13
- const target = targetPath(parsed.options);
14
- const json = optionFlag(parsed.options, "json");
15
- const declared = optionString(parsed.options, "domain") ?? process.env.MM_HARNESS_DOMAIN;
16
- const detected = adapterFromOptions();
17
- const adapter = detected === "unscoped" ? void 0 : detected;
18
- if (declared) {
19
- emit(json, { domain: declared, source: "declared", adapter: adapter ?? null, target });
20
- return 0;
21
- }
22
- if (!adapter) {
23
- throw usageError(`No MetaMask checkout detected: pass --adapter <${REVIEW_ADAPTERS.join("|")}> or --domain <name>.`);
24
- }
25
- const config = readConfig(configPath());
26
- const libraries = discoverLibraries({ target, config });
27
- const { base, files } = changedFiles(target, optionString(parsed.options, "base"));
28
- const matches = classifyDomain(files, adapter, libraries);
29
- const best = matches[0];
30
- emit(json, {
31
- domain: best?.domain ?? null,
32
- source: best ? "owned-paths" : "none",
33
- adapter,
34
- target,
35
- base,
36
- changedFiles: files.length,
37
- libraries: libraries.map((library) => ({ name: library.name, root: library.root, source: library.source, revision: library.revision ?? null })),
38
- matches: matches.map((match) => ({ domain: match.domain, library: match.library.root, matched: match.matched }))
39
- });
40
- return 0;
41
- }
42
- function emit(json, payload) {
43
- if (json) {
44
- process.stdout.write(`${JSON.stringify({ command: "domain", ...payload }, null, 2)}
45
- `);
46
- return;
47
- }
48
- process.stdout.write(`${payload.domain ?? "none"}
49
- `);
50
- const best = payload.matches?.[0];
51
- const detail = payload.source === "declared" ? "declared via --domain or MM_HARNESS_DOMAIN" : best ? `owned-paths match in ${best.library} (${best.matched.length} of ${payload.changedFiles} changed files)` : `no library owns the ${payload.changedFiles} changed files (base ${payload.base}; libraries scanned: ${payload.libraries?.length ?? 0})`;
52
- process.stderr.write(`domain: ${detail}
53
- `);
54
- }
55
- export {
56
- handleDomain
57
- };
@@ -1,28 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import { createRequire } from "node:module";
3
- const require2 = createRequire(import.meta.url);
4
- async function handleExecutionTemplate(argv) {
5
- let entrypoint;
6
- try {
7
- entrypoint = require2.resolve(
8
- "@farmslot/agent-runtime/scripts/execution-template-cli.mjs"
9
- );
10
- } catch (error) {
11
- console.error(
12
- `mm-harness execution-template: installed @farmslot/agent-runtime does not expose the catalog command: ${error instanceof Error ? error.message : String(error)}`
13
- );
14
- return 1;
15
- }
16
- const result = spawnSync(process.execPath, [entrypoint, ...argv], {
17
- env: process.env,
18
- stdio: "inherit"
19
- });
20
- if (result.error) {
21
- console.error(`mm-harness execution-template: ${result.error.message}`);
22
- return 1;
23
- }
24
- return result.status ?? 1;
25
- }
26
- export {
27
- handleExecutionTemplate
28
- };
@@ -1,99 +0,0 @@
1
- import { adapterDetectNext, EXIT, flag, parseFlags, contextAdapter, spawnInherit, str, targetOf, usageOut } from "@farmslot/recipe-cli/harness";
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import { createLogsOptions } from "../provider-logs.js";
5
- import { getAdapterSurface } from "../adapters/surface.js";
6
- const LOGS_BOOLEANS = /* @__PURE__ */ new Set(["full", "json", "window"]);
7
- async function handleLogs(argv) {
8
- const { options } = parseFlags(argv, LOGS_BOOLEANS);
9
- const json = flag(options, "json");
10
- const target = targetOf(options);
11
- const adapter = contextAdapter(target);
12
- if (!adapter) {
13
- return usageOut(json, "logs", `could not detect the MetaMask repo type for ${target}`, adapterDetectNext());
14
- }
15
- const surface = getAdapterSurface(adapter);
16
- if (surface.headless) {
17
- return usageOut(json, "logs", "core is headless; it has no dev server logs.", surface.hints.launch);
18
- }
19
- const logSources = surface.logSources(target);
20
- const appLogSource = surface.appLogSource(target);
21
- const sourceLabels = logSources.map((entry) => entry.label);
22
- const appSourceLabel = appLogSource?.label ?? "app";
23
- const defaultSource = appLogSource && appSourceLabel !== "app" ? appSourceLabel : sourceLabels[0];
24
- const source = str(options, "source") ?? defaultSource;
25
- const validSources = [...sourceLabels, ...appLogSource ? [appSourceLabel] : [], ...appLogSource && appSourceLabel !== "app" ? ["app"] : []];
26
- if (!validSources.includes(source)) {
27
- return usageOut(json, "logs", `--source must be one of: ${validSources.join(", ")}.`, `mm-harness logs --source ${defaultSource}`);
28
- }
29
- const events = str(options, "events");
30
- if (events !== void 0) {
31
- if (!/^\d+$/u.test(events)) {
32
- return usageOut(json, "logs", `--events must be numeric (got: ${events}).`, "mm-harness logs --events 20");
33
- }
34
- process.env.RECIPE_LOG_EVENTS = events;
35
- }
36
- const isAppSource = source === "app" || source === appSourceLabel;
37
- const requested = isAppSource ? appLogSource : logSources.find((entry) => entry.label === source);
38
- const ordered = isAppSource ? requested ? [requested] : [] : requested ? [requested] : logSources;
39
- const logFile = ordered.find((entry) => fs.existsSync(entry.path))?.path;
40
- if (!logFile) {
41
- if (isAppSource && appLogSource) {
42
- const message = `application console unavailable for this checkout (${path.basename(appLogSource.path)} is absent).`;
43
- const userAction = surface.hints.launch;
44
- if (json) {
45
- console.log(JSON.stringify({
46
- schemaVersion: 1,
47
- command: "logs",
48
- adapter,
49
- source,
50
- status: "fail",
51
- error: { code: "APP_LOG_UNAVAILABLE", message, userAction },
52
- exitCode: EXIT.runtime
53
- }, null, 2));
54
- } else {
55
- console.error(`\u2717 logs: ${message}`);
56
- console.error(` Next: ${userAction}`);
57
- }
58
- return EXIT.runtime;
59
- }
60
- const names = isAppSource && appLogSource ? path.basename(appLogSource.path) : logSources.map((entry) => path.basename(entry.path)).join(" / ");
61
- return usageOut(
62
- json,
63
- "logs",
64
- `nothing running for this checkout (no ${names}).`,
65
- surface.hints.launch
66
- );
67
- }
68
- if (flag(options, "window")) {
69
- const result = await createLogsOptions(surface).window({
70
- target,
71
- logFile: logSources[0].path
72
- });
73
- if (json) console.log(JSON.stringify({ schemaVersion: 1, command: "logs", action: "window", adapter, ...result }, null, 2));
74
- return result.exitCode;
75
- }
76
- if (json) {
77
- console.log(JSON.stringify({ schemaVersion: 1, command: "logs", adapter, source, logFile, exitCode: EXIT.ok }, null, 2));
78
- return EXIT.ok;
79
- }
80
- process.stderr.write(
81
- `${source} log: ${logFile}
82
- tail it yourself: tail -f ${logFile} \xB7 page it: less +F ${logFile}
83
- following below (Ctrl-C to stop) \u2026
84
- `
85
- );
86
- const full = flag(options, "full");
87
- if (full) {
88
- return spawnInherit("tail", ["-n", "+1", "-F", logFile], target) === 0 ? EXIT.ok : EXIT.runtime;
89
- }
90
- return createLogsOptions(surface).compact({
91
- target,
92
- logFile,
93
- events: process.env.RECIPE_LOG_EVENTS ?? "20",
94
- mode: process.env.RECIPE_LOG_UI_MODE ?? "compact"
95
- });
96
- }
97
- export {
98
- handleLogs
99
- };