diff --git a/README.md b/README.md index b074655..8106a22 100644 --- a/README.md +++ b/README.md @@ -540,13 +540,13 @@ mm describe-screen ### Lifecycle -| Command | Description | -| ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `mm launch [--context e2e\|prod] [--state default\|onboarding\|custom] [--extension-path ] [--goal ] [--force] [--flow-tags ]` | Auto-starts the daemon if needed, then launches a headed Chrome session with the configured extension. Use `--context` to set the environment context before launching. Use `--state` to control wallet initialization. Use `--extension-path` to override the extension directory. Use `--goal` and `--flow-tags` for knowledge tagging. Use `--force` to replace an existing session. | -| `mm cleanup [--shutdown]` | Stops the browser, tears down test services (fixture server, Anvil, mock server), and releases session resources. Add `--shutdown` to also terminate the daemon process. | -| `mm stop [--force]` | Stops the daemon process (symmetric to `mm serve`). Sends a best-effort cleanup before shutdown. Use `--force` to remove stale `.mm-server` state from crashed daemons. | -| `mm status` | Displays the daemon's current status: PID, port, uptime, allocated sub-ports, and whether a browser session is active. | -| `mm serve [--background]` | Manually starts the HTTP daemon without launching a browser session. Use `--background` to detach the process. Fails if a daemon is already running for this worktree. | +| Command | Description | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `mm launch [--context e2e\|prod] [--state default\|onboarding\|custom] [--extension-path ] [--goal ] [--force] [--flow-tags ] [--tags ]` | Auto-starts the daemon if needed, then launches a headed Chrome session with the configured extension. Use `--context` to set the environment context before launching. Use `--state` to control wallet initialization. Use `--extension-path` to override the extension directory. Use `--goal`, `--flow-tags`, and `--tags` for knowledge tagging. Use `--force` to replace an existing session. | +| `mm cleanup [--shutdown]` | Stops the browser, tears down test services (fixture server, Anvil, mock server), and releases session resources. Add `--shutdown` to also terminate the daemon process. | +| `mm stop [--force]` | Stops the daemon process (symmetric to `mm serve`). Sends a best-effort cleanup before shutdown. Use `--force` to remove stale `.mm-server` state from crashed daemons. | +| `mm status` | Displays the daemon's current status: PID, port, uptime, allocated sub-ports, and whether a browser session is active. | +| `mm serve [--background]` | Manually starts the HTTP daemon without launching a browser session. Use `--background` to detach the process. Fails if a daemon is already running for this worktree. | ### Interaction diff --git a/SKILL.md b/SKILL.md index c0855a9..3ad4078 100644 --- a/SKILL.md +++ b/SKILL.md @@ -117,19 +117,22 @@ The `run_steps` tool collects observations once after all steps complete. Contro Starts the daemon (if not running) and launches a headed Chrome session with the extension. ``` -mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path ] [--goal ] [--force] [--flow-tags ] +mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path ] [--goal ] [--force] [--flow-tags ] [--tags ] ``` -| Flag | Description | -| ------------------------- | --------------------------------------------------------------- | -| `--context e2e\|prod` | Set the environment context before launching | -| `--state default` | Pre-onboarded wallet with 25 ETH on local Anvil chain (default) | -| `--state onboarding` | Fresh wallet requiring manual onboarding setup | -| `--state custom` | Use a custom fixture for wallet state | -| `--extension-path ` | Override the extension build directory | -| `--goal ` | Tag the session with a goal for knowledge store | -| `--force` | Replace an existing active session | -| `--flow-tags ` | Comma-separated flow tags for cross-session knowledge | +| Flag | Description | +| ------------------------- | ------------------------------------------------------------------------------ | +| `--context e2e\|prod` | Set the environment context before launching | +| `--state default` | Pre-onboarded wallet with 25 ETH on local Anvil chain (default) | +| `--state onboarding` | Fresh wallet requiring manual onboarding setup | +| `--state custom` | Use a custom fixture for wallet state | +| `--extension-path ` | Override the extension build directory | +| `--goal ` | **Required for knowledge.** Describe what this session is doing | +| `--force` | Replace an existing active session | +| `--flow-tags ` | **Required for knowledge.** Comma-separated flow tags (see table below) | +| `--tags ` | Comma-separated free-form tags for ad-hoc filtering (e.g., `smoke,regression`) | + +**⚠ Always provide `--goal` and `--flow-tags` on every launch.** Without them, the knowledge store cannot index the session for cross-session learning, prior knowledge, or search. Sessions launched without tags are invisible to future sessions. Returns: `sessionId`, `extensionId`, `state` (current extension state). @@ -448,9 +451,13 @@ These contracts can be deployed to the local Anvil chain via `seed_contract` / ` | `simpleAccountFactory` | ERC-4337 account factory | | `verifyingPaymaster` | ERC-4337 paymaster | -## Flow Tags +## Session Tagging (REQUIRED) + +**Every `mm launch` must include `--goal` and `--flow-tags`.** This is what makes the knowledge store work — without tags, the session is invisible to search, prior knowledge, and cross-session learning. + +### Flow Tags -When launching, tag your session with flow tags for cross-session knowledge: +Pick one or more flow tags that describe what the session is doing: | Tag | Use for | | ----------------- | ------------------------------ | @@ -462,6 +469,16 @@ When launching, tag your session with flow tags for cross-session knowledge: | `settings` | Settings configuration | | `tx-confirmation` | Transaction confirmation flows | +### Free-Form Tags + +Use `--tags` for ad-hoc categorization not covered by flow tags: + +```bash +mm launch --goal "Regression test send USDC" --flow-tags send --tags regression,usdc +``` + +Tags enable filtering via `knowledge_sessions` and `knowledge_search`. + ## Daemon Model - Daemon runs per project, state tracked in `.mm-server` at the project root @@ -476,7 +493,7 @@ When launching, tag your session with flow tags for cross-session knowledge: ### Basic Interaction ```bash -mm launch --state default +mm launch --state default --goal "Test send ETH flow" --flow-tags send mm describe-screen # Response includes a11y nodes: [{ ref: "e1", role: "button", name: "Send" }, ...] mm click e1 @@ -490,7 +507,7 @@ mm cleanup --shutdown ### Transaction with Notification ```bash -mm launch --state default +mm launch --state default --goal "Test Uniswap swap via dApp" --flow-tags swap,connect mm navigate https://app.uniswap.org mm describe-screen # Interact with dApp... @@ -507,13 +524,13 @@ mm cleanup --shutdown # Set once — all subsequent mm commands target this project export MM_PROJECT=/path/to/metamask-extension -mm launch --state default +mm launch --state default --goal "Verify home screen" --flow-tags settings mm describe-screen mm click e1 mm cleanup --shutdown # Or use --project per command -mm --project ../metamask-extension launch +mm --project ../metamask-extension launch --goal "Quick check" --flow-tags send mm --project ../metamask-extension describe-screen ``` diff --git a/src/cli/mm.test.ts b/src/cli/mm.test.ts index f38111f..be6dfcd 100644 --- a/src/cli/mm.test.ts +++ b/src/cli/mm.test.ts @@ -433,6 +433,42 @@ describe('parseLaunchArgs', () => { ); }); + it('parses --tags as comma-separated array', () => { + expect(parseLaunchArgs(['--tags', 'smoke, regression'])).toStrictEqual({ + tags: ['smoke', 'regression'], + }); + }); + + it('exits for --tags without value', () => { + expect(() => parseLaunchArgs(['--tags'])).toThrowError('process.exit'); + expect(stderrSpy).toHaveBeenCalledWith( + 'Error: --tags requires a comma-separated value\n', + ); + }); + + it('exits for --tags with flag as value', () => { + expect(() => parseLaunchArgs(['--tags', '--force'])).toThrowError( + 'process.exit', + ); + }); + + it('parses --tags and --flow-tags together', () => { + expect( + parseLaunchArgs([ + '--flow-tags', + 'send', + '--tags', + 'smoke,e2e', + '--goal', + 'test send', + ]), + ).toStrictEqual({ + flowTags: ['send'], + tags: ['smoke', 'e2e'], + goal: 'test send', + }); + }); + it('parses --context value', () => { expect(parseLaunchArgs(['--context', 'prod'])).toStrictEqual({ context: 'prod', diff --git a/src/cli/mm.ts b/src/cli/mm.ts index 4b63b1e..49de836 100644 --- a/src/cli/mm.ts +++ b/src/cli/mm.ts @@ -1090,6 +1090,7 @@ export function parseLaunchArgs(args: string[]): Record { '--goal', '--force', '--flow-tags', + '--tags', ]); for (let i = 0; i < args.length; i++) { @@ -1135,6 +1136,15 @@ export function parseLaunchArgs(args: string[]): Record { process.exit(1); } result.flowTags = args[i].split(',').map((tag) => tag.trim()); + } else if (arg === '--tags') { + i += 1; + if (!args[i] || args[i].startsWith('--')) { + process.stderr.write( + 'Error: --tags requires a comma-separated value\n', + ); + process.exit(1); + } + result.tags = args[i].split(',').map((tag) => tag.trim()); } else if (arg.startsWith('--') && !knownFlags.has(arg)) { process.stderr.write(`Warning: unknown launch flag '${arg}'\n`); } @@ -1159,7 +1169,7 @@ Environment Variables: Falls back to the current git worktree root. Lifecycle: - mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path ] [--goal ] [--force] [--flow-tags ] + mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path ] [--goal ] [--force] [--flow-tags ] [--tags ] mm cleanup [--shutdown] mm status mm stop [--force]