@muggleai/works 4.8.3 → 4.9.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.
Files changed (38) hide show
  1. package/README.md +2 -8
  2. package/dist/{chunk-44I5ROCB.js → chunk-4KQZLF56.js} +219 -7
  3. package/dist/{chunk-OMLNCNSZ.js → chunk-6N7OIBAS.js} +7 -2
  4. package/dist/cli.js +2 -2
  5. package/dist/index.js +2 -2
  6. package/dist/plugin/.claude-plugin/plugin.json +8 -1
  7. package/dist/plugin/.cursor-plugin/plugin.json +1 -1
  8. package/dist/plugin/agents/acceptance-tester.md +103 -0
  9. package/dist/plugin/scripts/ensure-electron-app.sh +78 -1
  10. package/dist/plugin/skills/muggle/SKILL.md +24 -8
  11. package/dist/plugin/skills/muggle-pr-visual-walkthrough/SKILL.md +17 -0
  12. package/dist/plugin/skills/muggle-preferences/SKILL.md +82 -0
  13. package/dist/plugin/skills/muggle-status/SKILL.md +21 -1
  14. package/dist/plugin/skills/muggle-test/SKILL.md +26 -0
  15. package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +50 -19
  16. package/dist/plugin/skills/muggle-test-import/SKILL.md +20 -0
  17. package/dist/plugin/skills/muggle-test-prepare/SKILL.md +276 -0
  18. package/dist/plugin/skills/muggle-test-regenerate-missing/SKILL.md +18 -0
  19. package/dist/release-manifest.json +4 -4
  20. package/dist/src-7GB7WIFT.js +1 -0
  21. package/package.json +6 -6
  22. package/plugin/.claude-plugin/plugin.json +8 -1
  23. package/plugin/.cursor-plugin/plugin.json +1 -1
  24. package/plugin/agents/acceptance-tester.md +103 -0
  25. package/plugin/scripts/ensure-electron-app.sh +78 -1
  26. package/plugin/skills/muggle/SKILL.md +24 -8
  27. package/plugin/skills/muggle-pr-visual-walkthrough/SKILL.md +17 -0
  28. package/plugin/skills/muggle-preferences/SKILL.md +82 -0
  29. package/plugin/skills/muggle-status/SKILL.md +21 -1
  30. package/plugin/skills/muggle-test/SKILL.md +26 -0
  31. package/plugin/skills/muggle-test-feature-local/SKILL.md +50 -19
  32. package/plugin/skills/muggle-test-import/SKILL.md +20 -0
  33. package/plugin/skills/muggle-test-prepare/SKILL.md +276 -0
  34. package/plugin/skills/muggle-test-regenerate-missing/SKILL.md +18 -0
  35. package/scripts/postinstall.mjs +88 -0
  36. package/dist/plugin/skills/optimize-descriptions/SKILL.md +0 -212
  37. package/dist/src-ZRUONWKV.js +0 -1
  38. package/plugin/skills/optimize-descriptions/SKILL.md +0 -212
@@ -17,6 +17,23 @@ This is the **canonical PR-walkthrough workflow** shared across every Muggle ent
17
17
 
18
18
  Rendering is always done by `muggle build-pr-section`, a battle-tested CLI that handles deterministic markdown layout, per-step screenshots, and automatic fit-vs-overflow (oversized content spills into a follow-up comment). Never hand-write the walkthrough markdown.
19
19
 
20
+ ## Preferences
21
+
22
+ User preferences are available in the session context (injected at session start). Look for the line starting with `Muggle Preferences` — it contains key=value pairs like `autoLogin=ask showElectronBrowser=always ...`.
23
+
24
+ If no preferences line is present, treat all preferences as `"ask"`.
25
+
26
+ When you reach a decision gated by a preference:
27
+ - **`always`** → proceed without asking the user
28
+ - **`never`** → skip without asking the user
29
+ - **`ask`** → ask the user, then offer: "Want me to remember this choice for future sessions?" If yes, call `muggle-local-preferences-set` with the key, their chosen value, and scope `global`.
30
+
31
+ This skill uses these preferences:
32
+
33
+ | Preference | Decision it gates |
34
+ |------------|------------------|
35
+ | `postPRVisualWalkthrough` | Post visual walkthrough to PR |
36
+
20
37
  ## Input contract: the `E2eReport` JSON
21
38
 
22
39
  Every caller must build an `E2eReport` JSON object and have it in conversation context before invoking this skill. The schema is defined in `src/cli/pr-section/types.ts` (`E2eReportSchema`) and enforced by the CLI with Zod — malformed input exits non-zero with a descriptive stderr message.
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: muggle-preferences
3
+ description: >-
4
+ View, set, or reset Muggle AI preferences that control testing behavior.
5
+ Use when user asks to see preferences, change a setting, configure Muggle
6
+ defaults, or manage muggle config. Triggers on: 'muggle preferences',
7
+ 'show muggle settings', 'change muggle preference', 'set autoLogin to
8
+ always', 'muggle config', 'reset muggle preferences', 'show my muggle
9
+ settings', 'configure muggle'.
10
+ ---
11
+
12
+ # Muggle Preferences
13
+
14
+ View, set, or reset the preference knobs that control Muggle AI behavior.
15
+
16
+ ## Operations
17
+
18
+ Parse the user's request to determine which operation to perform:
19
+
20
+ - **List** — user wants to see current values (default when no specific change requested)
21
+ - **Set** — user wants to change a specific preference
22
+ - **Reset** — user wants to restore a preference (or all preferences) to defaults
23
+
24
+ ## List
25
+
26
+ 1. Read preferences from session context. Look for the line starting with `Muggle Preferences` — it contains key=value pairs like `autoLogin=ask showElectronBrowser=always ...`.
27
+
28
+ If no preferences line is present, treat all preferences as `"ask"` (the default).
29
+
30
+ 2. Present all 12 preferences in a table:
31
+
32
+ ```
33
+ Muggle AI — Preferences
34
+
35
+ | Preference | Value | Description |
36
+ |--------------------------|--------|----------------------------------------------------------|
37
+ | autoLogin | ask | Reuse saved credentials without prompting |
38
+ | autoSelectProject | ask | Reuse last-used project for this repo |
39
+ | showElectronBrowser | ask | Show browser window during local tests |
40
+ | openTestResultsAfterRun | ask | Open results page on dashboard after local test |
41
+ | defaultExecutionMode | ask | Default to local or remote test execution |
42
+ | autoPublishLocalResults | ask | Upload local results to Muggle cloud |
43
+ | suggestRelatedUseCases | ask | Suggest related use cases after creating/running one |
44
+ | suggestRelatedTestCases | ask | Suggest related test cases after creating/running one |
45
+ | autoDetectChanges | ask | Scan local git changes and map to affected test cases |
46
+ | postPRVisualWalkthrough | ask | Post visual walkthrough with screenshots to PR |
47
+ | checkForUpdates | ask | Check for newer Muggle version at session start |
48
+ | verboseOutput | ask | Show detailed progress logs during execution |
49
+
50
+ Values: always (proceed without asking) · ask (prompt each time) · never (skip without asking)
51
+ Scope: global (~/.muggle-ai/) or project (.muggle-ai/ in repo root)
52
+ ```
53
+
54
+ ## Set
55
+
56
+ 1. Parse the requested key and value from the user's message.
57
+
58
+ 2. Validate the key is one of: `autoLogin`, `autoSelectProject`, `showElectronBrowser`, `openTestResultsAfterRun`, `defaultExecutionMode`, `autoPublishLocalResults`, `suggestRelatedUseCases`, `suggestRelatedTestCases`, `autoDetectChanges`, `postPRVisualWalkthrough`, `checkForUpdates`, `verboseOutput`.
59
+
60
+ If the key is ambiguous or not recognized, show the full list and ask the user to clarify.
61
+
62
+ 3. Validate the value is one of: `always`, `ask`, `never`.
63
+
64
+ 4. Determine scope:
65
+ - Default to `global`.
66
+ - If the user says "for this project", "project-level", or "just this repo", use `project` scope and pass `cwd` as the current working directory.
67
+
68
+ 5. Call `muggle-local-preferences-set` with:
69
+ - `key`: The preference key
70
+ - `value`: The chosen value
71
+ - `scope`: `"global"` or `"project"`
72
+ - `cwd`: Current working directory (required when scope is `"project"`)
73
+
74
+ 6. Confirm: `Set {key} to {value} ({scope}).`
75
+
76
+ ## Reset
77
+
78
+ 1. If the user asks to reset a **specific key**: call `muggle-local-preferences-set` with `value: "ask"` for that key.
79
+
80
+ 2. If the user asks to reset **all preferences**: call `muggle-local-preferences-set` for each of the 12 keys with `value: "ask"`.
81
+
82
+ 3. Confirm what was reset.
@@ -7,6 +7,23 @@ description: Check health of the Muggle AI installation. Use when user types mug
7
7
 
8
8
  Run a full health check and report results.
9
9
 
10
+ ## Preferences
11
+
12
+ User preferences are available in the session context (injected at session start). Look for the line starting with `Muggle Preferences` — it contains key=value pairs like `autoLogin=ask showElectronBrowser=always ...`.
13
+
14
+ If no preferences line is present, treat all preferences as `"ask"`.
15
+
16
+ When you reach a decision gated by a preference:
17
+ - **`always`** → proceed without asking the user
18
+ - **`never`** → skip without asking the user
19
+ - **`ask`** → ask the user, then offer: "Want me to remember this choice for future sessions?" If yes, call `muggle-local-preferences-set` with the key, their chosen value, and scope `global`.
20
+
21
+ This skill uses these preferences:
22
+
23
+ | Preference | Decision it gates |
24
+ |------------|------------------|
25
+ | `checkForUpdates` | Check for newer Muggle version |
26
+
10
27
  ## Checks
11
28
 
12
29
  1. **Electron app** — read `~/.muggle-ai/electron-app/` to find the installed version directory. Read `.install-metadata.json` to get version and checksum. Verify the binary exists at the expected path. On macOS, check code signing with `spctl --assess --verbose`.
@@ -15,6 +32,8 @@ Run a full health check and report results.
15
32
 
16
33
  3. **Authentication** — call `muggle-remote-auth-status`. Report whether credentials are valid and when they expire.
17
34
 
35
+ 4. **CLI version** — capture installed (`muggle --version`) and latest (`npm view @muggleai/works version`). Compare with `sort -V`; flag as out-of-date only when latest is strictly greater.
36
+
18
37
  ## Output
19
38
 
20
39
  ```
@@ -23,8 +42,9 @@ Muggle AI — Status
23
42
  Electron app [pass/fail] version, binary status
24
43
  MCP server [pass/fail] responsive, auth state
25
44
  Authentication [pass/fail] user, expiry
45
+ CLI version [pass/warn] installed → latest
26
46
 
27
47
  [All systems operational / Issues found — run /muggle:muggle-repair to fix.]
28
48
  ```
29
49
 
30
- Use pass/fail indicators for each check. If any check fails, tell the user to run `/muggle:muggle-repair`.
50
+ Use pass/fail indicators for each check. If any check fails, tell the user to run `/muggle:muggle-repair`. If the CLI version check warns (installed < latest), tell the user to run `/muggle:muggle-upgrade`.
@@ -32,6 +32,28 @@ Every test case verifies exactly **one** user-observable behavior. Never bundle
32
32
 
33
33
  **Never skip the generate→review cycle.** Even when you are 100% confident about the right shape, always present the generated test cases to the user before calling `muggle-remote-test-case-create`. "I'll skip the generate→review cycle and create directly" is a sign you're about to get it wrong.
34
34
 
35
+ ## Preferences
36
+
37
+ User preferences are available in the session context (injected at session start). Look for the line starting with `Muggle Preferences` — it contains key=value pairs like `autoLogin=ask showElectronBrowser=always ...`.
38
+
39
+ If no preferences line is present, treat all preferences as `"ask"`.
40
+
41
+ When you reach a decision gated by a preference:
42
+ - **`always`** → proceed without asking the user
43
+ - **`never`** → skip without asking the user
44
+ - **`ask`** → ask the user, then offer: "Want me to remember this choice for future sessions?" If yes, call `muggle-local-preferences-set` with the key, their chosen value, and scope `global`.
45
+
46
+ This skill uses these preferences:
47
+
48
+ | Preference | Decision it gates |
49
+ |------------|------------------|
50
+ | `autoLogin` | Reuse saved credentials when auth is required |
51
+ | `autoSelectProject` | Reuse last-used Muggle project for this repo |
52
+ | `autoDetectChanges` | Scan local git changes and map to affected test cases |
53
+ | `defaultExecutionMode` | Default to local or remote test execution |
54
+ | `autoPublishLocalResults` | Upload local results to Muggle cloud after run |
55
+ | `postPRVisualWalkthrough` | Post visual walkthrough to PR after results are available |
56
+
35
57
  ## Step 1: Confirm Scope of Work (Always First)
36
58
 
37
59
  Parse the user's query and explicitly confirm their expectation. There are exactly two modes:
@@ -418,3 +440,7 @@ This skill always uses **Mode A** (post to an existing PR); `muggle-do` is the o
418
440
  - **Always publish before opening browser** — the dashboard needs the published data to show results
419
441
  - **Delegate PR posting to `muggle-pr-visual-walkthrough`** — never inline the walkthrough markdown or call `gh pr comment` directly from this skill; ask the user and hand off
420
442
  - **Can be invoked at any state** — if the user already has a project or use cases set up, skip to the relevant step rather than re-doing everything
443
+
444
+ ## Agent Dispatch
445
+
446
+ When used in a multi-agent team (e.g., muggle-ai-teams), this skill is available through the **acceptance-tester** agent at `plugin/agents/acceptance-tester.md`. Orchestrators can dispatch it via `Agent()` instead of invoking this skill directly. The agent wraps this skill and four others (muggle-test-import, muggle-preferences, muggle-repair, muggle-status) and returns structured test results with blocking issues and suggested fixes for coding agents to act on.
@@ -22,6 +22,26 @@ The local URL only changes where the browser opens; it does not change the remot
22
22
  - **Selections** (project, use case, test case, script): Use `AskQuestion` with labeled options the user can click.
23
23
  - **Free-text inputs** (URLs, descriptions): Only use plain text prompts when there is no finite set of options. Even then, offer a detected/default value when possible.
24
24
 
25
+ ## Preferences
26
+
27
+ User preferences are available in the session context (injected at session start). Look for the line starting with `Muggle Preferences` — it contains key=value pairs like `autoLogin=ask showElectronBrowser=always ...`.
28
+
29
+ If no preferences line is present, treat all preferences as `"ask"`.
30
+
31
+ When you reach a decision gated by a preference:
32
+ - **`always`** → proceed without asking the user
33
+ - **`never`** → skip without asking the user
34
+ - **`ask`** → ask the user, then offer: "Want me to remember this choice for future sessions?" If yes, call `muggle-local-preferences-set` with the key, their chosen value, and scope `global`.
35
+
36
+ This skill uses these preferences:
37
+
38
+ | Preference | Decision it gates |
39
+ |------------|------------------|
40
+ | `autoLogin` | Reuse saved credentials when auth is required |
41
+ | `autoSelectProject` | Reuse last-used Muggle project for this repo |
42
+ | `showElectronBrowser` | Show Electron browser window during local E2E tests |
43
+ | `openTestResultsAfterRun` | Open results page on Muggle dashboard after run |
44
+
25
45
  ## Workflow
26
46
 
27
47
  ### 1. Auth
@@ -65,9 +85,20 @@ Prompt for projects: "Pick the project to group this test into:"
65
85
  2. `muggle-remote-use-case-create-from-prompts` with `projectId` and `instructions: ["<the user's natural-language instruction>"]` — persist. Use the created use case id and continue to test-case selection.
66
86
  - **Test case — Create new test case** (requires a chosen `useCaseId`): User provides an instruction describing what to test.
67
87
  1. `muggle-remote-test-case-generate-from-prompt` with `projectId`, `useCaseId`, `instruction` — **preview only** (server test-case prompt preview); show the returned draft(s); get confirmation via `AskQuestion`.
68
- 2. Persist the accepted draft with `muggle-remote-test-case-create`, mapping preview fields into the required properties (`title`, `description`, `goal`, `expectedResult`, `url`, etc.). Then continue from **section 4** with that `testCaseId`.
88
+ 2. Persist the accepted draft with `muggle-remote-test-case-create`, mapping preview fields into the required properties (`title`, `description`, `goal`, `expectedResult`, `url`, etc.). Then continue from **section 5** with that `testCaseId`.
89
+
90
+ ### 3. Ensure Local Services Are Ready
91
+
92
+ Before detecting the local URL, verify that the services the user needs are actually running. Use the `muggle:muggle-test-prepare` integration contract:
93
+
94
+ 1. Check if `/tmp/muggle-test-prepare.json` exists.
95
+ 2. If it exists, verify tracked PIDs are alive with `kill -0`.
96
+ 3. If all live → services are ready, proceed to Step 4 (Local URL).
97
+ 4. If the file is missing or has stale PIDs → invoke the `muggle:muggle-test-prepare` skill via the `Skill` tool to get services started. Once it completes, proceed to Step 4.
98
+
99
+ This step is especially important when the user's app depends on sibling services (a backend API, an auth service, etc.) that may not be running yet. The prepare skill handles discovery, startup, and cleanup so this skill doesn't have to.
69
100
 
70
- ### 3. Local URL
101
+ ### 4. Local URL
71
102
 
72
103
  Try to auto-detect the dev server URL by checking running terminals or common ports (e.g., `lsof -iTCP -sTCP:LISTEN -nP | grep -E ':(3000|3001|4200|5173|8080)'`). If a likely URL is found, present it as a clickable default via `AskQuestion`:
73
104
  - Option 1: "http://localhost:3000" (or whatever was detected)
@@ -77,14 +108,14 @@ If nothing detected, ask as free text: "Your local app should be running. What's
77
108
 
78
109
  Remind them: local URL is only the execution target, not tied to cloud project config.
79
110
 
80
- ### 4. Existing scripts vs new generation
111
+ ### 5. Existing scripts vs new generation
81
112
 
82
113
  `muggle-remote-test-script-list` with `testCaseId`.
83
114
 
84
115
  - **If any replayable/succeeded scripts exist:** use `AskQuestion` to present them as clickable options. Show: name, created/updated, step count per option. Include **"Generate new script"** as the last option.
85
116
  - **If none:** go straight to generation (no need to ask replay vs generate).
86
117
 
87
- ### 5. Load data for the chosen path
118
+ ### 6. Load data for the chosen path
88
119
 
89
120
  **Determine `freshSession`**
90
121
 
@@ -122,39 +153,39 @@ The MCP client often uses a **default wait of 300000 ms (5 minutes)** for `muggl
122
153
  - **`Electron execution timed out after 300000ms`:** Orchestration wait too short — see **`timeoutMs`** above.
123
154
  - **Exit code 26** (and messages like **LLM failed to generate / replay action script**): Often corresponds to a completed exploration whose **outcome was goal not achievable** (`goal_not_achievable`, summary with `halt`) — e.g. verifying "view script after a successful run" when **no run or script exists yet** in the UI. Use `muggle-local-run-result-get` and read the **summary / structured summary**; do not assume an Electron crash. **Fix:** choose a **project that already has** completed runs and scripts, or **change the test case** so preconditions match what localhost can satisfy (e.g. include steps to create and run a test first, or assert only empty-state UI when no runs exist).
124
155
 
125
- ### 6. Execute (no approval prompt)
156
+ ### 7. Execute (no approval prompt)
126
157
 
127
158
  Call `muggle-local-execute-test-generation` or `muggle-local-execute-replay` directly. **Do not** ask the user to re-approve the Electron launch — the user choosing this skill in the first place is the approval. The browser defaults to visible; only pass `showUi: false` if the user explicitly asked for headless.
128
159
 
129
- ### 7. After successful generation only
160
+ ### 8. After successful generation only
130
161
 
131
162
  - `muggle-local-publish-test-script`
132
163
  - Open returned `viewUrl` for the user (`open "<viewUrl>"` on macOS or OS equivalent).
133
164
 
134
- ### 8. Report
165
+ ### 9. Report
135
166
 
136
167
  - `muggle-local-run-result-get` with the run id from execute.
137
168
  - Include: status, duration, pass/fail summary, per-step summary, artifact/screenshot paths, errors if failed, and script view URL when publishing ran.
138
169
 
139
- ### 9. Offer to post a visual walkthrough to the PR
170
+ ### 10. Offer to post a visual walkthrough to the PR
140
171
 
141
- After reporting results, gather the required input and hand off to the shared **`muggle-pr-visual-walkthrough`** skill, which renders the walkthrough via `muggle build-pr-section` and posts it to the current branch's open PR.
172
+ After reporting results, gather the required input and hand off to the shared **`muggle:muggle-pr-visual-walkthrough`** skill, which renders the walkthrough via `muggle build-pr-section` and posts it to the current branch's open PR.
142
173
 
143
- #### 9a: Gather per-step screenshots
174
+ #### 10a: Gather per-step screenshots
144
175
 
145
- The shared skill takes an **`E2eReport` JSON** that includes per-step screenshot URLs. After step 7 has called `muggle-local-publish-test-script` and you have the `testScriptId`:
176
+ The shared skill takes an **`E2eReport` JSON** that includes per-step screenshot URLs. After step 8 has called `muggle-local-publish-test-script` and you have the `testScriptId`:
146
177
 
147
178
  1. Call `muggle-remote-test-script-get` with the `testScriptId`.
148
179
  2. Extract per step: `steps[].operation.action` and `steps[].operation.screenshotUrl`.
149
180
  3. Build the `steps` array: `[{ stepIndex: 0, action: "...", screenshotUrl: "..." }, ...]`.
150
- 4. If the run failed, capture `failureStepIndex`, `error`, and the local `artifactsDir` from the run result in step 8.
181
+ 4. If the run failed, capture `failureStepIndex`, `error`, and the local `artifactsDir` from the run result in step 9.
151
182
  5. Populate `description` (test case title/description) and `useCaseName` (parent use case title) on the report entry — optional but strongly recommended; they drive the grouped overview and the per-test collapsible headers. Prefer values already in your conversation context from earlier steps (e.g. the test case you just created or selected, or the use case you confirmed); only call `muggle-remote-test-case-get` / `muggle-remote-use-case-get` for anything you don't already have.
152
183
 
153
184
  Assemble the `E2eReport`:
154
185
 
155
186
  ```json
156
187
  {
157
- "projectId": "<projectId from step 2>",
188
+ "projectId": "<projectId from step 2 (Targets)>",
158
189
  "tests": [
159
190
  {
160
191
  "name": "<test case title>",
@@ -171,9 +202,9 @@ Assemble the `E2eReport`:
171
202
  }
172
203
  ```
173
204
 
174
- See the `muggle-pr-visual-walkthrough` skill for the full schema including the failed-test shape.
205
+ See the `muggle:muggle-pr-visual-walkthrough` skill for the full schema including the failed-test shape.
175
206
 
176
- #### 9b: Ask the user
207
+ #### 10b: Ask the user
177
208
 
178
209
  Use `AskQuestion`:
179
210
 
@@ -182,11 +213,11 @@ Use `AskQuestion`:
182
213
  - Option 1: "Yes, post to PR"
183
214
  - Option 2: "Skip"
184
215
 
185
- #### 9c: Invoke the shared skill in Mode A
216
+ #### 10c: Invoke the shared skill in Mode A
186
217
 
187
- If the user chooses "Yes, post to PR", invoke the `muggle-pr-visual-walkthrough` skill via the `Skill` tool. With the `E2eReport` in context, the skill renders the markdown block via the CLI, finds the PR via `gh pr view`, posts `body` as a comment, posts the overflow `comment` only if the CLI emitted one, and confirms the PR URL to the user.
218
+ If the user chooses "Yes, post to PR", invoke the `muggle:muggle-pr-visual-walkthrough` skill via the `Skill` tool. With the `E2eReport` in context, the skill renders the markdown block via the CLI, finds the PR via `gh pr view`, posts `body` as a comment, posts the overflow `comment` only if the CLI emitted one, and confirms the PR URL to the user.
188
219
 
189
- Always use **Mode A** (post to existing PR) from this skill. Never hand-write the walkthrough markdown or call `gh pr comment` directly — delegate to `muggle-pr-visual-walkthrough`.
220
+ Always use **Mode A** (post to existing PR) from this skill. Never hand-write the walkthrough markdown or call `gh pr comment` directly — delegate to `muggle:muggle-pr-visual-walkthrough`.
190
221
 
191
222
  ## Non-negotiables
192
223
 
@@ -197,4 +228,4 @@ Always use **Mode A** (post to existing PR) from this skill. Never hand-write th
197
228
  - Replay: never hand-built or simplified `actionScript` — only from `muggle-remote-action-script-get`.
198
229
  - Use `AskQuestion` for every selection — project, use case, test case, script. Never ask the user to type a number.
199
230
  - Project, use case, and test case selection lists must always include "Create new ...". Include "Show full list" whenever the API returned at least one row for that step; omit "Show full list" when the list is empty (offer "Create new ..." only). For creates, use preview tools (`muggle-remote-use-case-prompt-preview`, `muggle-remote-test-case-generate-from-prompt`) before persisting.
200
- - PR posting is always optional and always delegated to the `muggle-pr-visual-walkthrough` skill — never inline the walkthrough markdown or call `gh pr comment` directly from this skill.
231
+ - PR posting is always optional and always delegated to the `muggle:muggle-pr-visual-walkthrough` skill — never inline the walkthrough markdown or call `gh pr comment` directly from this skill.
@@ -18,6 +18,26 @@ This skill migrates existing test artifacts into Muggle Test. It reads your sour
18
18
  structures them into use cases and test cases, gets your approval, then creates everything
19
19
  in a Muggle project via the API.
20
20
 
21
+ ## Preferences
22
+
23
+ User preferences are available in the session context (injected at session start). Look for the line starting with `Muggle Preferences` — it contains key=value pairs like `autoLogin=ask showElectronBrowser=always ...`.
24
+
25
+ If no preferences line is present, treat all preferences as `"ask"`.
26
+
27
+ When you reach a decision gated by a preference:
28
+ - **`always`** → proceed without asking the user
29
+ - **`never`** → skip without asking the user
30
+ - **`ask`** → ask the user, then offer: "Want me to remember this choice for future sessions?" If yes, call `muggle-local-preferences-set` with the key, their chosen value, and scope `global`.
31
+
32
+ This skill uses these preferences:
33
+
34
+ | Preference | Decision it gates |
35
+ |------------|------------------|
36
+ | `autoLogin` | Reuse saved credentials when auth is required |
37
+ | `autoSelectProject` | Reuse last-used Muggle project for this repo |
38
+ | `suggestRelatedUseCases` | Suggest related use cases after import |
39
+ | `suggestRelatedTestCases` | Suggest related test cases after import |
40
+
21
41
  ## Concepts
22
42
 
23
43
  - **Use case**: A high-level feature or user workflow (e.g., "User Registration", "Checkout Flow")
@@ -0,0 +1,276 @@
1
+ ---
2
+ name: muggle-test-prepare
3
+ description: "Make sure dev servers and sibling services are ready on the user's machine before running E2E acceptance tests. Checks which services need to be running, discovers sibling directories by folder name, verifies what's already listening, and offers to start anything that's missing — with the user's approval at every step. Use this skill whenever the user needs to prepare their local environment for E2E testing, verify their services are up, get their local dev stack ready, or when other muggle skills detect that required services are not listening on common ports. Triggers on: 'prepare for testing', 'make sure my services are running', 'check my local env', 'get ready for tests', 'are my services up', 'prepare local environment', 'spin up services', 'set up for E2E', 'verify my setup'. Also use when muggle-test, muggle-do, or muggle-test-feature-local need services running."
4
+ ---
5
+
6
+ # Muggle Test Prepare
7
+
8
+ Make sure the local services a user needs for E2E acceptance testing are up and ready. Check what's already running, discover sibling service directories by folder name, and offer to start anything that's missing — always with the user in control.
9
+
10
+ Some users start their own services (tmux scripts, docker-compose, a terminal per service). Others want help launching them. This skill handles both: it verifies readiness first, and only offers to start things when something is missing.
11
+
12
+ ## Privacy Boundary
13
+
14
+ This skill touches the user's local machine — processes, ports, directories outside the current repo. Every action is explicit and confirmed.
15
+
16
+ - **Folder names are public.** You may list directory names in a parent folder to discover sibling services.
17
+ - **File contents are private until confirmed.** Never read files inside a directory the user hasn't explicitly identified as a service to start. Once confirmed, you may inspect only top-level project indicator files (`package.json`, `Makefile`, `Cargo.toml`, `go.mod`, `pyproject.toml`, `docker-compose.yml`) to determine the start command.
18
+ - **Never traverse upward more than one level** from the current working directory to list folders.
19
+
20
+ ## PID Tracking
21
+
22
+ All launched processes are tracked in `/tmp/muggle-test-prepare.json`:
23
+
24
+ ```json
25
+ {
26
+ "session_started": "2025-01-15T10:30:00Z",
27
+ "testing_scope": "frontend",
28
+ "excluded_services": [
29
+ {"name": "payment-gateway", "reason": "Needs production certificates"}
30
+ ],
31
+ "services": [
32
+ {
33
+ "name": "backend-api",
34
+ "dir": "/Users/user/Github/backend-api",
35
+ "command": "npm run dev",
36
+ "pid": 12345,
37
+ "port": 3001,
38
+ "log": "/tmp/muggle-prepare-backend-api.log"
39
+ }
40
+ ]
41
+ }
42
+ ```
43
+
44
+ The `testing_scope` field records what the user is testing (from Step 1). The `excluded_services` field records services the user said can't run locally (from Step 2), so other skills understand what's intentionally absent vs. forgotten.
45
+
46
+ **On every invocation**, check this file first. If it exists with live PIDs (verify with `kill -0`), present the running services and ask:
47
+
48
+ Use `AskQuestion`:
49
+ - Option 1: "Keep them running — skip to testing"
50
+ - Option 2: "Tear down and start fresh"
51
+ - Option 3: "Add more services to the running set"
52
+
53
+ Prune any dead PIDs silently (the process crashed on its own — no point asking about it).
54
+
55
+ ## Workflow
56
+
57
+ ### Step 1: What Are You Testing?
58
+
59
+ Before discovering services, understand the shape of the testing so you can scope correctly. Use `AskQuestion`:
60
+
61
+ > "What are you testing locally?"
62
+
63
+ - Option 1: "A frontend feature — I need the UI and its backend dependencies running"
64
+ - Option 2: "A backend API — I just need the API server running"
65
+ - Option 3: "The full stack — everything needs to be up"
66
+
67
+ This scopes the rest of the workflow. If the user is testing a backend API, they probably don't need a frontend dev server. If they're testing a frontend feature, they need the frontend plus whatever backends it talks to. Keep this answer in mind when presenting service candidates in Step 3 — pre-check the ones that match and leave the rest unchecked.
68
+
69
+ ### Step 2: Viability Check
70
+
71
+ Some services can't run on a developer's machine by design — they need production secrets, HSMs, specific certificates, or cloud-only infrastructure. Don't waste time trying to discover or start them.
72
+
73
+ **If the user already volunteered this information** in their initial message (e.g., "the payment-gateway can't run locally"), acknowledge it and skip the question — don't re-ask what they already answered.
74
+
75
+ Otherwise, use `AskQuestion`:
76
+
77
+ > "Are there any services in your stack that **can't** run locally? (e.g., needs production secrets, specific certificates, or cloud-only infra)"
78
+
79
+ - Option 1: "All my services can run locally"
80
+ - Option 2: "Some can't — I'll tell you which"
81
+
82
+ If the user picks option 2, collect the names. Acknowledge them and exclude from discovery.
83
+
84
+ If an excluded service is a hard dependency for the app under test, **suggest testing in a preview/staging environment instead** — the user can merge first and use `/muggle-test` in remote mode, where everything is already up and running. Frame it as an alternative, not a dead end:
85
+
86
+ > "Since **payment-gateway** can't run locally, you might get better coverage by merging and running `/muggle-test` against your preview environment — everything's wired up there. Want to continue with a partial local setup, or switch to remote testing?"
87
+
88
+ - Option 1: "Continue locally — I'll work around the missing service"
89
+ - Option 2: "Switch to remote — I'll merge and test on preview"
90
+
91
+ If the user chooses remote, hand off to `/muggle-test` in remote mode and exit this skill.
92
+
93
+ ### Step 3: Identify Required Services & How to Start Them
94
+
95
+ Figure out which services need to be running. Start by listing folder names in the **parent directory** of the current working directory — these are the most likely candidates.
96
+
97
+ ```bash
98
+ ls -d "$(dirname "$PWD")"/*/ | xargs -I{} basename {}
99
+ ```
100
+
101
+ Present folder names only (not contents) as candidates. Use `AskQuestion` with `multiSelect: true`:
102
+
103
+ > "Which of these need to be running for your tests?"
104
+
105
+ List each folder name as an option. Pre-check the ones that match the testing scope from Step 1 (e.g., if testing a frontend feature, pre-check the frontend and likely backends). Always include these fixed tail options:
106
+ - "Just the current project (no other services needed)"
107
+ - "None of these — I'll tell you what I need"
108
+
109
+ If the user provides manual paths, verify they exist before continuing. If a path doesn't exist, report it and ask for correction.
110
+
111
+ **Include the current working directory as a candidate** — the user might be editing the backend but also need the frontend (a sibling) started, or vice versa.
112
+
113
+ **Immediately after the user selects services**, ask how they want to handle startup. This avoids making someone who prefers their own scripts wait through command detection before they get to say "I'll handle it."
114
+
115
+ Use `AskQuestion`:
116
+
117
+ > "How do you want to handle these?"
118
+
119
+ - Option 1: "Check what's running, start what's missing for me"
120
+ - Option 2: "I'll start them myself — just verify they're up when I'm done"
121
+
122
+ If the user picks **option 2**: skip Steps 4-6. Wait for them to confirm they're ready, then go straight to Step 4 (Check What's Already Running) to verify everything is listening, and report readiness (Step 7).
123
+
124
+ If the user picks **option 1**: proceed through Steps 4-7 as normal.
125
+
126
+ ### Step 4: Check What's Already Running
127
+
128
+ Before offering to start anything, check what's already listening on common dev ports:
129
+
130
+ ```bash
131
+ lsof -iTCP -sTCP:LISTEN -nP 2>/dev/null | grep -E ':(3000|3001|3002|4200|5173|5174|8080|8081|8000|8888|4000|9000)'
132
+ ```
133
+
134
+ Cross-reference against the selected service directories. If a selected service appears to already be running (match by port or by the process's working directory), report it as ready:
135
+
136
+ > "**backend-api** is already listening on port 3001 (PID 54321) — looks good."
137
+
138
+ If **all** required services are already running, report readiness and skip straight to Step 7. No need to go through Steps 5-6.
139
+
140
+ If some are running and some aren't, acknowledge the running ones and continue to Step 5 only for the missing services. Use `AskQuestion` for any already-running service the user might want restarted:
141
+ - Option 1: "It's fine, keep it"
142
+ - Option 2: "Restart it"
143
+
144
+ For services that are already running and the user wants to keep, add them to the PID tracking file so cleanup can find them later, but mark them as `external: true` so cleanup knows not to kill them (the user started them independently).
145
+
146
+ ### Step 5: Determine Start Commands
147
+
148
+ For each required service that isn't already running, figure out how to start it. Propose the command so there's a shared understanding.
149
+
150
+ Read **only** the indicator file that exists — don't read additional files.
151
+
152
+ **Detection order:**
153
+
154
+ | Indicator | Stack | Default command | What to check |
155
+ |:----------|:------|:----------------|:--------------|
156
+ | `package.json` | Node.js | `npm run dev` | Read `scripts` field: prefer `dev` > `start` > `serve` |
157
+ | `Makefile` | Various | `make dev` | Just check existence; propose `make dev` or `make run` |
158
+ | `Cargo.toml` | Rust | `cargo run` | Just check existence |
159
+ | `go.mod` | Go | `go run .` | Just check existence |
160
+ | `pyproject.toml` | Python | Check for framework | Read `[project.scripts]` or `[tool.poetry.scripts]` if present |
161
+ | `requirements.txt` | Python | `python app.py` | Just check existence |
162
+ | `docker-compose.yml` | Docker | `docker compose up` | Just check existence |
163
+
164
+ If no indicator file is found, tell the user and ask them to provide the start command manually.
165
+
166
+ **Present all proposed commands in a single summary:**
167
+
168
+ ```
169
+ Service Directory Command
170
+ ────────────────────────────────────────────────────────────────
171
+ backend-api ~/Github/backend-api npm run dev
172
+ auth-service ~/Github/auth-service go run .
173
+ frontend ~/Github/frontend npm run dev
174
+ ────────────────────────────────────────────────────────────────
175
+ ```
176
+
177
+ Use `AskQuestion`:
178
+ - Option 1: "Looks good, start them"
179
+ - Option 2: "I need to edit some commands"
180
+
181
+ If the user needs edits, collect corrections and re-present.
182
+
183
+ ### Step 6: Start Services
184
+
185
+ For each service, launch in the background:
186
+
187
+ ```bash
188
+ cd "<service-dir>" && nohup <command> > /tmp/muggle-prepare-<service-name>.log 2>&1 &
189
+ echo $!
190
+ ```
191
+
192
+ Capture the PID. Write all service entries to `/tmp/muggle-test-prepare.json`.
193
+
194
+ **Startup verification** — after a short pause (~3-5 seconds per service), check:
195
+
196
+ 1. PID is alive: `kill -0 <pid> 2>/dev/null`
197
+ 2. Port is listening (if known): `lsof -iTCP:<port> -sTCP:LISTEN -nP 2>/dev/null`
198
+
199
+ If a service's PID dies immediately, read the last 20 lines of its log and show the user:
200
+
201
+ > "**backend-api** exited right after starting. Here's the tail of its log:"
202
+
203
+ Then ask how to proceed:
204
+ - Option 1: "Skip it and continue with the others"
205
+ - Option 2: "Let me fix it — I'll re-invoke later"
206
+
207
+ **Port discovery** — if the port isn't known upfront, after the service starts, re-scan listening ports and try to identify which new port appeared. Record it in the tracking file if found. If not found within ~10 seconds, note the port as unknown — the service may take longer to boot.
208
+
209
+ ### Step 7: Report Readiness
210
+
211
+ Whether you started the services or the user did, confirm that everything is listening:
212
+
213
+ ```
214
+ Service PID Port Status
215
+ ──────────────────────────────────────────────
216
+ backend-api 12345 3001 Running
217
+ auth-service 12346 8080 Running
218
+ frontend 12347 3000 Running
219
+ ──────────────────────────────────────────────
220
+ All 3 services verified. Ready for E2E testing.
221
+ ```
222
+
223
+ If you launched the services, also show:
224
+ ```
225
+ Logs: /tmp/muggle-prepare-*.log
226
+ Cleanup: say "stop services" or re-invoke this skill.
227
+ ```
228
+
229
+ ## Cleanup
230
+
231
+ Cleanup is triggered when:
232
+ - The user says "stop services", "tear down", "clean up", or "I'm done testing"
233
+ - Another skill signals that a test run is complete
234
+ - This skill is re-invoked and the user chooses "tear down and start fresh"
235
+
236
+ **Cleanup steps:**
237
+
238
+ 1. Read `/tmp/muggle-test-prepare.json`
239
+ 2. Skip any services marked `external: true` (the user started them independently)
240
+ 3. For each managed service, send `SIGTERM`: `kill <pid>`
241
+ 4. Wait ~2 seconds, verify with `kill -0`
242
+ 5. If still alive, `kill -9 <pid>`
243
+ 6. Remove log files: `rm -f /tmp/muggle-prepare-*.log`
244
+ 7. Remove the tracking file: `rm -f /tmp/muggle-test-prepare.json`
245
+
246
+ Report:
247
+
248
+ ```
249
+ Stopped 3 services:
250
+ backend-api (PID 12345)
251
+ auth-service (PID 12346)
252
+ frontend (PID 12347)
253
+ ```
254
+
255
+ ## Integration Contract (for other skills)
256
+
257
+ When `muggle-test`, `muggle-do`, or `muggle-test-feature-local` want to check if services are ready:
258
+
259
+ 1. Check if `/tmp/muggle-test-prepare.json` exists
260
+ 2. Verify PIDs are alive with `kill -0`
261
+ 3. If all live → services are ready, proceed to test execution
262
+ 4. If missing or stale → invoke `muggle-test-prepare`
263
+
264
+ After a test run completes, the calling skill can invoke cleanup by re-invoking this skill with cleanup intent, or leave services running for the next run (the user chose lifecycle management, not clean-state resets).
265
+
266
+ ## Guardrails
267
+
268
+ - **Verify first, offer to start second** — always check what's already running before proposing to start anything. If everything is up, just confirm readiness and move on.
269
+ - **The user may prefer to start services themselves** — always offer that option. Some developers have their own startup scripts, tmux layouts, or docker-compose setups they'd rather use.
270
+ - **Never start a process the user didn't approve** — every command is presented and confirmed before execution.
271
+ - **Never read file contents outside confirmed directories** — folder names are discoverable; file contents require explicit user selection.
272
+ - **Never leave orphan processes untracked** — every background PID goes into the tracking file.
273
+ - **Never kill a process the user started independently** — services marked `external: true` survive cleanup.
274
+ - **Never assume start commands** — always verify by checking project indicator files; always confirm with the user.
275
+ - **Bail early on non-viable services** — don't attempt to start something the user said can't run locally.
276
+ - **Idempotent** — if services are already tracked and alive, offer to keep them rather than double-starting.