@deeeed/metamask-harness 0.3.7 → 0.3.9
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 +39 -0
- package/adapters/extension/start-watch.sh +8 -1
- package/adapters/manifest.json +8 -0
- package/adapters/mobile/lib/tmux-viewer.sh +38 -0
- package/adapters/mobile/start-metro.sh +4 -18
- package/adapters/mobile/stop-metro.sh +66 -0
- package/adapters/mobile/yarn-setup.sh +14 -2
- package/adapters/shared/resolve-farmslot-ports.sh +21 -0
- package/docs/UX-PRINCIPLES.md +61 -0
- package/package.json +8 -3
- package/scripts/completions.sh +6 -3
- package/src/adapters/mobile/prepare.ts +42 -17
- package/src/adapters/mobile/runtime-decision.ts +103 -42
- package/src/cli.ts +77 -4
- package/src/commands/launch.ts +87 -11
- package/src/commands/shared.ts +62 -1
- package/src/doctor.ts +25 -13
- package/src/mm-harness-cli.ts +59 -6
package/src/mm-harness-cli.ts
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
// teach; genuinely-unknown commands fall to commander's default.
|
|
8
8
|
|
|
9
9
|
import { spawnSync } from 'node:child_process';
|
|
10
|
+
import fs from 'node:fs';
|
|
10
11
|
import path from 'node:path';
|
|
11
12
|
import { fileURLToPath } from 'node:url';
|
|
12
13
|
|
|
13
14
|
import { Command } from 'commander';
|
|
14
15
|
|
|
16
|
+
import { color } from './cli-color.ts';
|
|
15
17
|
import { handleUpdate, maybeNudge } from './commands/update.ts';
|
|
16
18
|
|
|
17
19
|
// …/src → its parent is the package root that holds scripts/.
|
|
@@ -57,6 +59,25 @@ Example:
|
|
|
57
59
|
mm-harness actions --adapter mobile
|
|
58
60
|
mm-harness actions --adapter extension --raw`,
|
|
59
61
|
},
|
|
62
|
+
{
|
|
63
|
+
name: 'stop',
|
|
64
|
+
summary: 'Stop the dev server this checkout owns (mobile: port-scoped Metro) and close its log window.',
|
|
65
|
+
example: 'mm-harness stop',
|
|
66
|
+
helpText: `mm-harness stop [flags]
|
|
67
|
+
|
|
68
|
+
Stop the Metro dev server this checkout owns and close its tmux log-tail window.
|
|
69
|
+
Port-scoped: only the listener on the checkout's resolved port is signalled, so
|
|
70
|
+
concurrent slots are untouched. Nothing running = success (idempotent).
|
|
71
|
+
Extension/core: teaching error (their dev servers are slot-managed).
|
|
72
|
+
|
|
73
|
+
--port <port> Metro port (default: the checkout's slot context)
|
|
74
|
+
--target <path> Checkout path (default: cwd)
|
|
75
|
+
--json Machine-readable output
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
mm-harness stop
|
|
79
|
+
mm-harness stop --port 8061`,
|
|
80
|
+
},
|
|
60
81
|
{
|
|
61
82
|
name: 'call',
|
|
62
83
|
summary: 'Run one action in isolation as a one-node recipe through the real engine path (fuzzy short names; --arg k=v; same trace/evidence as run).',
|
|
@@ -345,7 +366,7 @@ const HELP_GROUPS: HelpGroup[] = [
|
|
|
345
366
|
{
|
|
346
367
|
title: 'DAILY LOOP',
|
|
347
368
|
blurb: 'what a teammate runs many times a day (auto-ensures the overlay; --heal owns recovery)',
|
|
348
|
-
commands: ['launch', 'logs', 'debug', 'fixtures'],
|
|
369
|
+
commands: ['launch', 'stop', 'logs', 'debug', 'fixtures'],
|
|
349
370
|
},
|
|
350
371
|
{
|
|
351
372
|
title: 'DISCOVER',
|
|
@@ -375,19 +396,51 @@ function commandMeta(name: string): { summary: string; example: string; planned:
|
|
|
375
396
|
return { summary: '', example: '', planned: false };
|
|
376
397
|
}
|
|
377
398
|
|
|
399
|
+
// Slot context the orchestrator's prepare wrote into the checkout, when the
|
|
400
|
+
// help is run from inside one. Presence-gated: no context, no line.
|
|
401
|
+
function detectedSlotLine(out: (style: string, text: string) => string): string | null {
|
|
402
|
+
const ctxPath = path.join(
|
|
403
|
+
process.cwd(),
|
|
404
|
+
process.env.RECIPE_RUNTIME_DIR || 'temp/recipe/runtime',
|
|
405
|
+
'agentic-runtime.json',
|
|
406
|
+
);
|
|
407
|
+
try {
|
|
408
|
+
const ctx = JSON.parse(fs.readFileSync(ctxPath, 'utf8')) as Record<string, unknown>;
|
|
409
|
+
const parts: string[] = [];
|
|
410
|
+
if (ctx.slotId) parts.push(`slot ${out('ok', String(ctx.slotId))}`);
|
|
411
|
+
if (ctx.simulator) parts.push(`device ${out('ok', String(ctx.simulator))}`);
|
|
412
|
+
if (ctx.metroPort) parts.push(`metro :${out('ok', String(ctx.metroPort))}`);
|
|
413
|
+
if (ctx.gitBranch) parts.push(`branch ${out('info', String(ctx.gitBranch))}`);
|
|
414
|
+
if (parts.length === 0) return null;
|
|
415
|
+
return `${out('label', 'SLOT')} — this checkout is a prepared slot: ${parts.join(' · ')}`;
|
|
416
|
+
} catch {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
378
421
|
function groupedHelp(): string {
|
|
422
|
+
const out = (style: string, text: string) => color(style, text, { stream: process.stdout });
|
|
379
423
|
const lines: string[] = [];
|
|
380
|
-
lines.push('mm-harness — one front door for the MetaMask recipe loop: launch the app, prove behavior, manage the runtime overlay
|
|
424
|
+
lines.push(`${out('bold', 'mm-harness')} — one front door for the MetaMask recipe loop: launch the app, prove behavior, manage the runtime overlay.`);
|
|
381
425
|
lines.push('Run it from inside a MetaMask checkout; the platform (mobile | extension | core) is auto-detected.');
|
|
382
|
-
lines.push(
|
|
426
|
+
lines.push(`Grammar: ${out('cmd', 'mm-harness <command> [target] [flags]')} (target is a positional: ios | android; flags add agent depth; --json is the agent contract)`);
|
|
427
|
+
if (process.env.MM_HARNESS_BIN) {
|
|
428
|
+
lines.push('');
|
|
429
|
+
lines.push(`${out('warn', 'DEV OVERRIDE ACTIVE')} — this run is served by MM_HARNESS_BIN=${out('path', process.env.MM_HARNESS_BIN)} (unset it to return to the installed/global bin).`);
|
|
430
|
+
}
|
|
431
|
+
const slotLine = detectedSlotLine(out);
|
|
432
|
+
if (slotLine) {
|
|
433
|
+
lines.push('');
|
|
434
|
+
lines.push(slotLine);
|
|
435
|
+
}
|
|
383
436
|
for (const group of HELP_GROUPS) {
|
|
384
437
|
lines.push('');
|
|
385
|
-
lines.push(`${group.title} — ${group.blurb}:`);
|
|
438
|
+
lines.push(`${out('label', group.title)} — ${group.blurb}:`);
|
|
386
439
|
for (const name of group.commands) {
|
|
387
440
|
const meta = commandMeta(name);
|
|
388
441
|
const planned = meta.planned ? ' (planned)' : '';
|
|
389
|
-
lines.push(` ${name.padEnd(10)} ${meta.summary}${planned}`);
|
|
390
|
-
lines.push(` ${meta.example}`);
|
|
442
|
+
lines.push(` ${out('cmd', name.padEnd(10))} ${meta.summary}${planned}`);
|
|
443
|
+
lines.push(` ${out('comment', meta.example)}`);
|
|
391
444
|
}
|
|
392
445
|
}
|
|
393
446
|
lines.push('');
|