@muggleai/works 5.16.0 → 5.17.0-staging.113
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/README.md +3 -0
- package/dist/{chunk-FK7XVMVA.js → chunk-6ILUPFM5.js} +188 -4
- package/dist/{chunk-VQZLKLAY.js → chunk-EKSYEVM2.js} +279 -2
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/plugin/config/onboarding-limits.json +3 -0
- package/dist/plugin/config/preference-defaults.json +25 -0
- package/dist/plugin/scripts/ensure-electron-app.sh +36 -21
- package/dist/plugin/skills/muggle/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-preferences/SKILL.md +3 -2
- package/dist/plugin/skills/muggle-preferences/ops/configure.md +4 -3
- package/dist/plugin/skills/muggle-preferences/ops/list.md +2 -1
- package/dist/plugin/skills/muggle-preferences/ops/onboard.md +54 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/README.md +7 -5
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +1 -1
- package/dist/plugin/skills/muggle-test-prepare/steps/check-running.md +1 -1
- package/dist/plugin/skills/muggle-test-prepare/steps/reuse-plan.md +1 -1
- package/dist/release-manifest.json +3 -3
- package/dist/src-52J7RTUV.js +1 -0
- package/package.json +3 -2
- package/plugin/config/onboarding-limits.json +3 -0
- package/plugin/config/preference-defaults.json +25 -0
- package/plugin/scripts/ensure-electron-app.sh +36 -21
- package/plugin/skills/muggle/SKILL.md +1 -1
- package/plugin/skills/muggle-preferences/SKILL.md +3 -2
- package/plugin/skills/muggle-preferences/ops/configure.md +4 -3
- package/plugin/skills/muggle-preferences/ops/list.md +2 -1
- package/plugin/skills/muggle-preferences/ops/onboard.md +54 -0
- package/plugin/skills/muggle-preferences/preference-gates/README.md +7 -5
- package/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +1 -1
- package/plugin/skills/muggle-test-prepare/steps/check-running.md +1 -1
- package/plugin/skills/muggle-test-prepare/steps/reuse-plan.md +1 -1
- package/scripts/onboarding-backfill.mjs +49 -0
- package/scripts/postinstall.mjs +12 -0
- package/dist/src-EHF3T2T2.js +0 -1
|
@@ -114,14 +114,22 @@ version_check || true
|
|
|
114
114
|
# <cwd>/.muggle-ai/preferences.json is left on disk but no longer read, so the
|
|
115
115
|
# keys it can no longer apply are named once — the stamp file suppresses the
|
|
116
116
|
# repeat until that key set changes.
|
|
117
|
-
prefs_global_file="${HOME}/.muggle-ai/preferences.json"
|
|
118
117
|
prefs_line=""
|
|
119
118
|
prefs_file_note=""
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
# Defaults ship as data next to this hook so the context line and the MCP tools
|
|
121
|
+
# resolve a preference the same way. Hardcoding them here drifted once already.
|
|
122
|
+
prefs_hook_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
123
|
+
prefs_defaults_file="${prefs_hook_dir}/../config/preference-defaults.json"
|
|
124
|
+
prefs_limits_file="${prefs_hook_dir}/../config/onboarding-limits.json"
|
|
125
|
+
|
|
126
|
+
onboarding_directive='Muggle Test first-run setup has not been run on this machine. Before acting on the user request, acknowledge what they asked for, then offer them the one-time setup walkthrough (the `onboard` operation of the muggle-preferences skill) which explains how Muggle Test works and saves their preferences. Accepting the recommended defaults takes one keystroke. If they decline, record the skip and carry on with their request using defaults.'
|
|
127
|
+
|
|
128
|
+
# A missing preferences file is not a special case: the resolver below falls back to
|
|
129
|
+
# the shipped defaults, which is exactly what the code will use until setup seeds them.
|
|
130
|
+
# Extract preferences object keys and values into a compact one-liner.
|
|
131
|
+
# Uses node for reliable JSON parsing (already required for muggle).
|
|
132
|
+
prefs_line=$(MUGGLE_PREFERENCE_DEFAULTS_FILE="$prefs_defaults_file" MUGGLE_ONBOARDING_LIMITS_FILE="$prefs_limits_file" MUGGLE_ONBOARDING_DIRECTIVE="$onboarding_directive" node -e "
|
|
125
133
|
const fs = require('fs');
|
|
126
134
|
const os = require('os');
|
|
127
135
|
const path = require('path');
|
|
@@ -129,21 +137,31 @@ if [ -f "$prefs_global_file" ]; then
|
|
|
129
137
|
// Resolved through node, not the shell's \$HOME: under Git Bash the shell
|
|
130
138
|
// reports a POSIX path that Windows node cannot open.
|
|
131
139
|
const globalFile = path.join(os.homedir(), '.muggle-ai', 'preferences.json');
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
suggestRelatedUseCases:'ask', suggestRelatedTestCases:'ask', autoDetectChanges:'ask',
|
|
138
|
-
postPRVisualWalkthrough:'ask', autoCreatePR:'ask',
|
|
139
|
-
checkForUpdates:'ask', verboseOutput:'ask',
|
|
140
|
-
autoUseWorktree:'ask', autoRebase:'ask', autoCleanup:'ask',
|
|
141
|
-
autoE2ETest:'always', autoRouteBuildToMuggleDo:'ask'
|
|
142
|
-
};
|
|
140
|
+
let file = {};
|
|
141
|
+
try { file = JSON.parse(fs.readFileSync(globalFile, 'utf-8')); } catch {}
|
|
142
|
+
const g = file.preferences || {};
|
|
143
|
+
let defaults = {};
|
|
144
|
+
try { defaults = JSON.parse(fs.readFileSync(process.env.MUGGLE_PREFERENCE_DEFAULTS_FILE, 'utf-8')); } catch {}
|
|
143
145
|
const resolved = { ...defaults, ...g };
|
|
144
146
|
const line = Object.entries(resolved).map(([k,v]) => k+'='+v).join(' ');
|
|
145
147
|
const blocks = ['Muggle Test Preferences (~/.muggle-ai/preferences.json):\\\\n' + line];
|
|
146
148
|
|
|
149
|
+
const onboardedAt = file.onboardingCompletedAt;
|
|
150
|
+
if (typeof onboardedAt !== 'string' || onboardedAt.length === 0) {
|
|
151
|
+
// The offer is capped here rather than only in the skip path: a user who never
|
|
152
|
+
// engages would otherwise be re-asked every session forever.
|
|
153
|
+
let maxOffers = 0;
|
|
154
|
+
try { maxOffers = JSON.parse(fs.readFileSync(process.env.MUGGLE_ONBOARDING_LIMITS_FILE, 'utf-8')).maxOffers; } catch {}
|
|
155
|
+
const offersDir = path.join(os.homedir(), '.cache', 'muggle');
|
|
156
|
+
const offersFile = path.join(offersDir, 'onboarding-offers');
|
|
157
|
+
let offers = 0;
|
|
158
|
+
try { offers = parseInt(fs.readFileSync(offersFile, 'utf-8'), 10) || 0; } catch {}
|
|
159
|
+
if (maxOffers > 0 && offers < maxOffers) {
|
|
160
|
+
try { fs.mkdirSync(offersDir, { recursive: true }); fs.writeFileSync(offersFile, String(offers + 1)); } catch {}
|
|
161
|
+
blocks.push(process.env.MUGGLE_ONBOARDING_DIRECTIVE);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
147
165
|
const cwd = process.env.CLAUDE_CWD || process.env.CURSOR_CWD || process.cwd();
|
|
148
166
|
const pPath = path.join(cwd, '.muggle-ai', 'preferences.json');
|
|
149
167
|
let p = {};
|
|
@@ -166,11 +184,8 @@ if [ -f "$prefs_global_file" ]; then
|
|
|
166
184
|
console.log(blocks.join('\\\\n\\\\n'));
|
|
167
185
|
} catch { console.log(''); }
|
|
168
186
|
" 2>/dev/null || true)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
fi
|
|
172
|
-
else
|
|
173
|
-
prefs_file_note="\\n\\nMuggle Test Preferences: not configured. Run \\\`muggle setup\\\` or tell the agent to set preferences."
|
|
187
|
+
if [ -n "$prefs_line" ]; then
|
|
188
|
+
prefs_file_note="\\n\\n${prefs_line}"
|
|
174
189
|
fi
|
|
175
190
|
|
|
176
191
|
# --- Last-used cache injection ---
|
|
@@ -12,7 +12,7 @@ Use this as the top-level Muggle Test command router.
|
|
|
12
12
|
|
|
13
13
|
## Preferences
|
|
14
14
|
|
|
15
|
-
User preferences are injected by the SessionStart hook into a `Muggle Test Preferences` line in session context (key=value pairs). Resolution: defaults → `~/.muggle-ai/preferences.json`. Preferences are user-level and apply to every repo.
|
|
15
|
+
User preferences are injected by the SessionStart hook into a `Muggle Test Preferences` line in session context (key=value pairs). Resolution: shipped defaults → `~/.muggle-ai/preferences.json`. Preferences are user-level and apply to every repo. The line carries every key already resolved, so a key is never absent.
|
|
16
16
|
|
|
17
17
|
This router skill itself does not gate any decision on a preference — it just routes user intent to a downstream skill. Each downstream skill consults its own preferences. For example, `checkForUpdates` is consulted by `muggle-status` (Check 4), not here.
|
|
18
18
|
|
|
@@ -23,10 +23,11 @@ Pick the operation, then read its op file for the procedure.
|
|
|
23
23
|
| "show preferences" / no args | `ops/list.md` |
|
|
24
24
|
| "configure muggle" / "muggle setup" / change without naming a key | `ops/configure.md` |
|
|
25
25
|
| "reset preferences" | `ops/reset.md` |
|
|
26
|
+
| Session context says first-run setup has not been run | `ops/onboard.md` |
|
|
26
27
|
|
|
27
28
|
## Shared context (all ops)
|
|
28
29
|
|
|
29
|
-
- **Current values**: session-context line `Muggle Test Preferences key=value
|
|
30
|
+
- **Current values**: session-context line `Muggle Test Preferences key=value …`, already resolved against the shipped defaults in `${CLAUDE_PLUGIN_ROOT}/config/preference-defaults.json`.
|
|
30
31
|
- **Per-key files**: `preference-gates/<key>.md`. Key list = `ls preference-gates/*.md` minus `README.md`.
|
|
31
|
-
- **Allowed values**: `always`/`never`/`ask` (
|
|
32
|
+
- **Allowed values**: `always`/`never`/`ask`, except `defaultExecutionMode` (`local`/`remote`/`ask`), `autoE2ETest` (`always`/`ask`), and `watcherLifetime` (`1d`/`7d`/`never`).
|
|
32
33
|
- **Scope**: preferences are user-level. Every write lands in `~/.muggle-ai/preferences.json` and applies to every repo. If the user asks for a per-project setting, say it isn't supported and confirm before setting it everywhere.
|
|
@@ -26,13 +26,14 @@ you can tell me which (if any) should instead be set to `never`.
|
|
|
26
26
|
For each option: label = key name, description = first paragraph of `preference-gates/<key>.md`. Multi-select question text = `Which of these should auto-proceed (set to "always")?`; selected = `always`.
|
|
27
27
|
|
|
28
28
|
- `multiSelect: true`, `header: "Auth & session"` — `autoLogin`, `autoSelectProject`, `checkForUpdates`, `verboseOutput`
|
|
29
|
-
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`
|
|
29
|
+
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`, `reusePreparePlan`
|
|
30
30
|
- `multiSelect: true`, `header: "Test run"` — `showElectronBrowser`, `openTestResultsAfterRun`
|
|
31
31
|
- `multiSelect: true`, `header: "Suggestions"` — `suggestRelatedUseCases`, `suggestRelatedTestCases`
|
|
32
|
-
- `multiSelect: true`, `header: "PR"` — `postPRVisualWalkthrough`, `autoCreatePR`, `autoWatchPR`
|
|
33
|
-
- `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`
|
|
32
|
+
- `multiSelect: true`, `header: "PR"` — `postPRVisualWalkthrough`, `autoCreatePR`, `autoWatchPR`, `autoRouteBuildToMuggleDo`
|
|
33
|
+
- `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`, `autoResolveConflicts`
|
|
34
34
|
- `multiSelect: false`, `header: "E2E acceptance"` — `autoE2ETest`. Options: `Always run Stage 6 at the end` (`always` — default), `Ask each cycle` (`ask`). No `never` option.
|
|
35
35
|
- `multiSelect: false`, `header: "Default mode"` — `defaultExecutionMode`. Options: `Local — run on my computer` (`local`), `Remote — run in the Muggle Test cloud` (`remote`), `Ask each time` (don't change).
|
|
36
|
+
- `multiSelect: false`, `header: "PR watcher"` — `watcherLifetime`. Options: `Retire after 1 day` (`1d`), `Retire after 7 days` (`7d` — default), `Never retire` (`never`).
|
|
36
37
|
|
|
37
38
|
`AskUserQuestion` accepts up to 4 questions per call — split across calls.
|
|
38
39
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
2. Render `Preference | Value | Description` table titled `Muggle AI — Preferences`. Values from session context.
|
|
5
5
|
3. Footer:
|
|
6
6
|
```
|
|
7
|
-
Values: always · ask · never
|
|
7
|
+
Values: always · ask · never — except defaultExecutionMode (local/remote/ask),
|
|
8
|
+
autoE2ETest (always/ask), watcherLifetime (1d/7d/never)
|
|
8
9
|
Stored: ~/.muggle-ai/preferences.json — applies to every repo
|
|
9
10
|
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Onboard (first-run walkthrough)
|
|
2
|
+
|
|
3
|
+
Runs once per machine, when session context says Muggle Test first-run setup has not been run. Explains what Muggle Test is, then saves the user's preferences.
|
|
4
|
+
|
|
5
|
+
The CLI owns the questions and every mapping from an answer onto a preference value. Render what `muggle init --json` returns — never hardcode keys, labels, or defaults here, and never write `preferences.json` directly.
|
|
6
|
+
|
|
7
|
+
## Step 1 — answer the user first
|
|
8
|
+
|
|
9
|
+
If the user asked for something, acknowledge it before offering setup. Setup is an offer, not a gate. Never make them wait for it.
|
|
10
|
+
|
|
11
|
+
## Step 2 — load the walkthrough
|
|
12
|
+
|
|
13
|
+
Run `muggle init --json`. It returns:
|
|
14
|
+
|
|
15
|
+
- `primerHeadline`, `primerBullets` — what to show before asking anything
|
|
16
|
+
- `blanketOptions` — the dispositions, each with `choice`, `label`, `description`
|
|
17
|
+
- `groups` — per-group questions; `kind` is `toggle` or `choice`
|
|
18
|
+
|
|
19
|
+
## Step 3 — show the primer, then the blanket choice
|
|
20
|
+
|
|
21
|
+
Print `primerHeadline` and `primerBullets` verbatim. Then one `AskUserQuestion` whose options are `blanketOptions` in order, using each `label` and `description`. The first option is pre-selected.
|
|
22
|
+
|
|
23
|
+
Record the picked `choice` value.
|
|
24
|
+
|
|
25
|
+
## Step 4 — per-group questions
|
|
26
|
+
|
|
27
|
+
Only when the user picked `customize`. Otherwise skip to step 5.
|
|
28
|
+
|
|
29
|
+
For each entry in `groups`, in order:
|
|
30
|
+
|
|
31
|
+
- `kind: "toggle"` — one `multiSelect: true` question. `header` = the group's `header`, question text = its `prompt`, one option per entry using `key` as the label and `description` as the description. Pre-select every entry whose `isSelectedByDefault` is true. Collect the selected `key`s.
|
|
32
|
+
- `kind: "choice"` — one `multiSelect: false` question. `header` = the group's `header`, question text = its `prompt`, one option per entry in `options` using `label`. Pre-select the option whose `isDefault` is true. Record `key` → the picked option's `value`.
|
|
33
|
+
|
|
34
|
+
`AskUserQuestion` takes at most 4 questions per call, so split the groups across calls.
|
|
35
|
+
|
|
36
|
+
## Step 5 — apply
|
|
37
|
+
|
|
38
|
+
Write the answers to `~/.muggle-ai/temp/onboarding-answers.json`:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"blanket": "customize",
|
|
43
|
+
"selectedToggleKeys": ["autoLogin", "autoSelectProject"],
|
|
44
|
+
"choices": { "autoE2ETest": "always", "defaultExecutionMode": "local", "watcherLifetime": "7d" }
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`blanket` is the value from step 3. Include `selectedToggleKeys` and `choices` only when it is `customize`.
|
|
49
|
+
|
|
50
|
+
Run `muggle init --apply ~/.muggle-ai/temp/onboarding-answers.json`, then delete the file.
|
|
51
|
+
|
|
52
|
+
## Step 6 — confirm
|
|
53
|
+
|
|
54
|
+
Print what the CLI reported. On `skip`, say it will be offered again next session and move on — a declined offer retires itself after the third time.
|
|
@@ -4,21 +4,23 @@ One file per key in this directory — `ls preference-gates/*.md` is the
|
|
|
4
4
|
authoritative key list. Skills load this contract + only the gates they
|
|
5
5
|
actually fire.
|
|
6
6
|
|
|
7
|
-
Default allowed values: `always` / `never` / `ask`. Per-key overrides
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Default allowed values: `always` / `never` / `ask`. Per-key overrides are noted
|
|
8
|
+
in their own file: `defaultExecutionMode` (`local` / `remote` / `ask`),
|
|
9
|
+
`autoE2ETest` (`always` / `ask`), and `watcherLifetime` (`1d` / `7d` / `never`).
|
|
10
10
|
|
|
11
11
|
## Resolution
|
|
12
12
|
|
|
13
13
|
`SessionStart` injects a `Muggle Test Preferences` line (`key=value` pairs) from
|
|
14
14
|
`~/.muggle-ai/preferences.json`. Preferences are user-level — there is no
|
|
15
|
-
per-project layer.
|
|
15
|
+
per-project layer. The line carries every key, already resolved against the
|
|
16
|
+
shipped defaults in `${CLAUDE_PLUGIN_ROOT}/config/preference-defaults.json`, so a
|
|
17
|
+
key is never absent.
|
|
16
18
|
|
|
17
19
|
## Gate behavior
|
|
18
20
|
|
|
19
21
|
- `always` → take the pro-action, then **always** print the silent footer.
|
|
20
22
|
- `never` → take the skip-action, then **always** print the silent footer.
|
|
21
|
-
- `ask`
|
|
23
|
+
- `ask` → run Picker 1 (per-key file) → Picker 2 (below).
|
|
22
24
|
|
|
23
25
|
`defaultExecutionMode` uses `local`/`remote` instead of `always`/`never`.
|
|
24
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `autoResolveConflicts`
|
|
2
2
|
|
|
3
|
-
When a rebase onto `origin/{default}` hits conflicts, `always` resolves them autonomously behind a verify-or-rollback gate and `never` aborts the rebase and escalates. Take the effective value from the configured preference per [`../README.md`](../README.md#resolution) (the injected `Muggle Test Preferences` line) — don't assume a default;
|
|
3
|
+
When a rebase onto `origin/{default}` hits conflicts, `always` resolves them autonomously behind a verify-or-rollback gate and `never` aborts the rebase and escalates. Take the effective value from the configured preference per [`../README.md`](../README.md#resolution) (the injected `Muggle Test Preferences` line) — don't assume a default; the line carries every key already resolved.
|
|
4
4
|
|
|
5
5
|
**Picker 1** — header `Resolve rebase conflicts?`, question `"Rebase onto origin/{default} hit conflicts in {conflicted} file(s) — resolve them autonomously?"`
|
|
6
6
|
- `Resolve autonomously` — `Resolve the conflicts, then re-verify (build + unit + E2E) before any push; roll back and escalate if verification fails.` → `always`
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
The dev-server URL the tests will hit is a **recorded value, not a guess** — resolve it before probing anything.
|
|
6
6
|
|
|
7
7
|
1. Read the cached host with `muggle-local-last-host-get`. It reads the entry keyed on `<cwd>` in `~/.muggle-ai/last-host.json`; a worktree usually has **no cache of its own**, so when the worktree returns nothing, pass the **main** working-tree root as `cwd` — `git rev-parse --git-common-dir`, then its parent directory.
|
|
8
|
-
2. Apply the [`autoSelectLocalHost`](../../muggle-preferences/preference-gates/autoSelectLocalHost.md) gate (read its value from the `Muggle Test Preferences` session-context line
|
|
8
|
+
2. Apply the [`autoSelectLocalHost`](../../muggle-preferences/preference-gates/autoSelectLocalHost.md) gate (read its value from the `Muggle Test Preferences` session-context line, which carries every key already resolved):
|
|
9
9
|
- `always` **and** a cache exists → use it silently: `Using saved local URL {lastHost}`.
|
|
10
10
|
- otherwise (`ask` / `never`, or no cache) → **confirm before using any host.** Run the gate's Picker 1 with `{lastHost}` (cached URL, omitted when absent) and `{suggestedHost}` (a port you actually detect listening). Never auto-pick, and never fall back to a framework default like `:3000`; if nothing is cached or detected, ask the user to type the URL.
|
|
11
11
|
|
|
@@ -17,7 +17,7 @@ Load the prose companion per [e2e-instructions](./e2e-instructions.md) — `~/.m
|
|
|
17
17
|
|
|
18
18
|
## Gate `reusePreparePlan`
|
|
19
19
|
|
|
20
|
-
Per [`muggle-preferences/preference-gates/README.md`](../../muggle-preferences/preference-gates/README.md). Read the current value from the `Muggle Test Preferences` session-context line
|
|
20
|
+
Per [`muggle-preferences/preference-gates/README.md`](../../muggle-preferences/preference-gates/README.md). Read the current value from the `Muggle Test Preferences` session-context line, which carries every key already resolved.
|
|
21
21
|
|
|
22
22
|
- `always` → silently take the **reuse path** (below). Print the silent footer (substitute `{services}` with the comma-separated names from the loaded plan).
|
|
23
23
|
- `never` → take the **rediscover path**: exit this step; continue at [rebase-check](./rebase-check.md).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"release": "5.13.1",
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-09-
|
|
3
|
+
"buildId": "run-113-1",
|
|
4
|
+
"commitSha": "7ee3a19d04e8507a86d41d123b9daa7d2bf1a572",
|
|
5
|
+
"buildTime": "2026-09-15T05:23:37Z",
|
|
6
6
|
"serviceName": "muggle-ai-works-mcp"
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DEFAULT_PREFERENCES, ElectronAppReleaseStream, ONBOARDING_BLANKET_OPTIONS, ONBOARDING_CHOICE_GROUPS, ONBOARDING_MAX_OFFERS, ONBOARDING_PRIMER_BULLETS, ONBOARDING_PRIMER_HEADLINE, ONBOARDING_TOGGLE_GROUPS, ONBOARDING_TOGGLE_PROMPT, ONBOARDING_UNSELECTED_TOGGLE_VALUE, OnboardingBlanketChoice, OnboardingGroupKind, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, ProjectPreferencesReconcileOutcome, RuntimeTarget, WATCHER_LIFETIME_SECONDS, WATCHER_LIFETIME_UNBOUNDED_SECONDS, applyOnboardingAnswers, assertDeviceCodeClientProvisioned, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, buildOnboardingPlan, calculateFileChecksum, completeOnboarding, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports as e2e, formatPreferencesOneLiner, getActiveElectronAppReleaseStream, getActiveRuntimeTarget, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppReleaseTagPrefix, getElectronAppSignedFromVersion, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getOnboardingToggleKeys, getPlatformKey, getQaTools, getReleaseSignerIdentityUri, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports as localQa, markOnboardingCompleted, mcp_exports as mcp, needsOnboarding, openBrowserUrl, performLogin, performLogout, pollDeviceCode, e2e_exports as qa, readPreferencesMetadata, reconcileProjectPreferences, recordOnboardingSkip, resetConfig, resetLogger, resetPreference, resolveActiveProfile, resolveActiveReleaseStream, resolveActiveReleaseTagPrefix, resolveBlanketPreferences, resolveElectronAppPathOrNull, resolveOnboardingAnswers, resolvePreferences, resolveRuntimeTarget, resolveTogglePreferences, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences, writePreferencesWithMetadata } from './chunk-EKSYEVM2.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muggleai/works",
|
|
3
3
|
"mcpName": "io.github.multiplex-ai/muggle",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.17.0-staging.113",
|
|
5
5
|
"description": "Ship quality products with AI-powered E2E acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"plugin",
|
|
14
14
|
"bin/muggle.js",
|
|
15
15
|
"scripts/postinstall.mjs",
|
|
16
|
+
"scripts/onboarding-backfill.mjs",
|
|
16
17
|
"scripts/release-integrity",
|
|
17
18
|
"config/runtime-targets.json"
|
|
18
19
|
],
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"muggleConfig": {
|
|
54
55
|
"electronAppVersion": "1.10.3",
|
|
55
56
|
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
|
|
56
|
-
"runtimeTargetDefault": "
|
|
57
|
+
"runtimeTargetDefault": "staging",
|
|
57
58
|
"checksumsByStream": {
|
|
58
59
|
"production": {
|
|
59
60
|
"win32-x64": "58e2238b1609ceff65b836b4b724b1c4c341d737a15debaa8a71af21b70bc436",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"autoLogin": "always",
|
|
3
|
+
"autoSelectProject": "always",
|
|
4
|
+
"autoSelectLocalHost": "always",
|
|
5
|
+
"showElectronBrowser": "always",
|
|
6
|
+
"openTestResultsAfterRun": "always",
|
|
7
|
+
"defaultExecutionMode": "local",
|
|
8
|
+
"suggestRelatedUseCases": "always",
|
|
9
|
+
"suggestRelatedTestCases": "always",
|
|
10
|
+
"autoDetectChanges": "always",
|
|
11
|
+
"postPRVisualWalkthrough": "always",
|
|
12
|
+
"autoCreatePR": "always",
|
|
13
|
+
"checkForUpdates": "always",
|
|
14
|
+
"verboseOutput": "never",
|
|
15
|
+
"autoUseWorktree": "always",
|
|
16
|
+
"autoRebase": "always",
|
|
17
|
+
"autoCleanup": "always",
|
|
18
|
+
"autoE2ETest": "always",
|
|
19
|
+
"autoResolveConflicts": "always",
|
|
20
|
+
"autoReuseValidationContext": "always",
|
|
21
|
+
"autoRouteBuildToMuggleDo": "always",
|
|
22
|
+
"autoWatchPR": "always",
|
|
23
|
+
"reusePreparePlan": "always",
|
|
24
|
+
"watcherLifetime": "7d"
|
|
25
|
+
}
|
|
@@ -114,14 +114,22 @@ version_check || true
|
|
|
114
114
|
# <cwd>/.muggle-ai/preferences.json is left on disk but no longer read, so the
|
|
115
115
|
# keys it can no longer apply are named once — the stamp file suppresses the
|
|
116
116
|
# repeat until that key set changes.
|
|
117
|
-
prefs_global_file="${HOME}/.muggle-ai/preferences.json"
|
|
118
117
|
prefs_line=""
|
|
119
118
|
prefs_file_note=""
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
# Defaults ship as data next to this hook so the context line and the MCP tools
|
|
121
|
+
# resolve a preference the same way. Hardcoding them here drifted once already.
|
|
122
|
+
prefs_hook_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
123
|
+
prefs_defaults_file="${prefs_hook_dir}/../config/preference-defaults.json"
|
|
124
|
+
prefs_limits_file="${prefs_hook_dir}/../config/onboarding-limits.json"
|
|
125
|
+
|
|
126
|
+
onboarding_directive='Muggle Test first-run setup has not been run on this machine. Before acting on the user request, acknowledge what they asked for, then offer them the one-time setup walkthrough (the `onboard` operation of the muggle-preferences skill) which explains how Muggle Test works and saves their preferences. Accepting the recommended defaults takes one keystroke. If they decline, record the skip and carry on with their request using defaults.'
|
|
127
|
+
|
|
128
|
+
# A missing preferences file is not a special case: the resolver below falls back to
|
|
129
|
+
# the shipped defaults, which is exactly what the code will use until setup seeds them.
|
|
130
|
+
# Extract preferences object keys and values into a compact one-liner.
|
|
131
|
+
# Uses node for reliable JSON parsing (already required for muggle).
|
|
132
|
+
prefs_line=$(MUGGLE_PREFERENCE_DEFAULTS_FILE="$prefs_defaults_file" MUGGLE_ONBOARDING_LIMITS_FILE="$prefs_limits_file" MUGGLE_ONBOARDING_DIRECTIVE="$onboarding_directive" node -e "
|
|
125
133
|
const fs = require('fs');
|
|
126
134
|
const os = require('os');
|
|
127
135
|
const path = require('path');
|
|
@@ -129,21 +137,31 @@ if [ -f "$prefs_global_file" ]; then
|
|
|
129
137
|
// Resolved through node, not the shell's \$HOME: under Git Bash the shell
|
|
130
138
|
// reports a POSIX path that Windows node cannot open.
|
|
131
139
|
const globalFile = path.join(os.homedir(), '.muggle-ai', 'preferences.json');
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
suggestRelatedUseCases:'ask', suggestRelatedTestCases:'ask', autoDetectChanges:'ask',
|
|
138
|
-
postPRVisualWalkthrough:'ask', autoCreatePR:'ask',
|
|
139
|
-
checkForUpdates:'ask', verboseOutput:'ask',
|
|
140
|
-
autoUseWorktree:'ask', autoRebase:'ask', autoCleanup:'ask',
|
|
141
|
-
autoE2ETest:'always', autoRouteBuildToMuggleDo:'ask'
|
|
142
|
-
};
|
|
140
|
+
let file = {};
|
|
141
|
+
try { file = JSON.parse(fs.readFileSync(globalFile, 'utf-8')); } catch {}
|
|
142
|
+
const g = file.preferences || {};
|
|
143
|
+
let defaults = {};
|
|
144
|
+
try { defaults = JSON.parse(fs.readFileSync(process.env.MUGGLE_PREFERENCE_DEFAULTS_FILE, 'utf-8')); } catch {}
|
|
143
145
|
const resolved = { ...defaults, ...g };
|
|
144
146
|
const line = Object.entries(resolved).map(([k,v]) => k+'='+v).join(' ');
|
|
145
147
|
const blocks = ['Muggle Test Preferences (~/.muggle-ai/preferences.json):\\\\n' + line];
|
|
146
148
|
|
|
149
|
+
const onboardedAt = file.onboardingCompletedAt;
|
|
150
|
+
if (typeof onboardedAt !== 'string' || onboardedAt.length === 0) {
|
|
151
|
+
// The offer is capped here rather than only in the skip path: a user who never
|
|
152
|
+
// engages would otherwise be re-asked every session forever.
|
|
153
|
+
let maxOffers = 0;
|
|
154
|
+
try { maxOffers = JSON.parse(fs.readFileSync(process.env.MUGGLE_ONBOARDING_LIMITS_FILE, 'utf-8')).maxOffers; } catch {}
|
|
155
|
+
const offersDir = path.join(os.homedir(), '.cache', 'muggle');
|
|
156
|
+
const offersFile = path.join(offersDir, 'onboarding-offers');
|
|
157
|
+
let offers = 0;
|
|
158
|
+
try { offers = parseInt(fs.readFileSync(offersFile, 'utf-8'), 10) || 0; } catch {}
|
|
159
|
+
if (maxOffers > 0 && offers < maxOffers) {
|
|
160
|
+
try { fs.mkdirSync(offersDir, { recursive: true }); fs.writeFileSync(offersFile, String(offers + 1)); } catch {}
|
|
161
|
+
blocks.push(process.env.MUGGLE_ONBOARDING_DIRECTIVE);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
147
165
|
const cwd = process.env.CLAUDE_CWD || process.env.CURSOR_CWD || process.cwd();
|
|
148
166
|
const pPath = path.join(cwd, '.muggle-ai', 'preferences.json');
|
|
149
167
|
let p = {};
|
|
@@ -166,11 +184,8 @@ if [ -f "$prefs_global_file" ]; then
|
|
|
166
184
|
console.log(blocks.join('\\\\n\\\\n'));
|
|
167
185
|
} catch { console.log(''); }
|
|
168
186
|
" 2>/dev/null || true)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
fi
|
|
172
|
-
else
|
|
173
|
-
prefs_file_note="\\n\\nMuggle Test Preferences: not configured. Run \\\`muggle setup\\\` or tell the agent to set preferences."
|
|
187
|
+
if [ -n "$prefs_line" ]; then
|
|
188
|
+
prefs_file_note="\\n\\n${prefs_line}"
|
|
174
189
|
fi
|
|
175
190
|
|
|
176
191
|
# --- Last-used cache injection ---
|
|
@@ -12,7 +12,7 @@ Use this as the top-level Muggle Test command router.
|
|
|
12
12
|
|
|
13
13
|
## Preferences
|
|
14
14
|
|
|
15
|
-
User preferences are injected by the SessionStart hook into a `Muggle Test Preferences` line in session context (key=value pairs). Resolution: defaults → `~/.muggle-ai/preferences.json`. Preferences are user-level and apply to every repo.
|
|
15
|
+
User preferences are injected by the SessionStart hook into a `Muggle Test Preferences` line in session context (key=value pairs). Resolution: shipped defaults → `~/.muggle-ai/preferences.json`. Preferences are user-level and apply to every repo. The line carries every key already resolved, so a key is never absent.
|
|
16
16
|
|
|
17
17
|
This router skill itself does not gate any decision on a preference — it just routes user intent to a downstream skill. Each downstream skill consults its own preferences. For example, `checkForUpdates` is consulted by `muggle-status` (Check 4), not here.
|
|
18
18
|
|
|
@@ -23,10 +23,11 @@ Pick the operation, then read its op file for the procedure.
|
|
|
23
23
|
| "show preferences" / no args | `ops/list.md` |
|
|
24
24
|
| "configure muggle" / "muggle setup" / change without naming a key | `ops/configure.md` |
|
|
25
25
|
| "reset preferences" | `ops/reset.md` |
|
|
26
|
+
| Session context says first-run setup has not been run | `ops/onboard.md` |
|
|
26
27
|
|
|
27
28
|
## Shared context (all ops)
|
|
28
29
|
|
|
29
|
-
- **Current values**: session-context line `Muggle Test Preferences key=value
|
|
30
|
+
- **Current values**: session-context line `Muggle Test Preferences key=value …`, already resolved against the shipped defaults in `${CLAUDE_PLUGIN_ROOT}/config/preference-defaults.json`.
|
|
30
31
|
- **Per-key files**: `preference-gates/<key>.md`. Key list = `ls preference-gates/*.md` minus `README.md`.
|
|
31
|
-
- **Allowed values**: `always`/`never`/`ask` (
|
|
32
|
+
- **Allowed values**: `always`/`never`/`ask`, except `defaultExecutionMode` (`local`/`remote`/`ask`), `autoE2ETest` (`always`/`ask`), and `watcherLifetime` (`1d`/`7d`/`never`).
|
|
32
33
|
- **Scope**: preferences are user-level. Every write lands in `~/.muggle-ai/preferences.json` and applies to every repo. If the user asks for a per-project setting, say it isn't supported and confirm before setting it everywhere.
|
|
@@ -26,13 +26,14 @@ you can tell me which (if any) should instead be set to `never`.
|
|
|
26
26
|
For each option: label = key name, description = first paragraph of `preference-gates/<key>.md`. Multi-select question text = `Which of these should auto-proceed (set to "always")?`; selected = `always`.
|
|
27
27
|
|
|
28
28
|
- `multiSelect: true`, `header: "Auth & session"` — `autoLogin`, `autoSelectProject`, `checkForUpdates`, `verboseOutput`
|
|
29
|
-
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`
|
|
29
|
+
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`, `reusePreparePlan`
|
|
30
30
|
- `multiSelect: true`, `header: "Test run"` — `showElectronBrowser`, `openTestResultsAfterRun`
|
|
31
31
|
- `multiSelect: true`, `header: "Suggestions"` — `suggestRelatedUseCases`, `suggestRelatedTestCases`
|
|
32
|
-
- `multiSelect: true`, `header: "PR"` — `postPRVisualWalkthrough`, `autoCreatePR`, `autoWatchPR`
|
|
33
|
-
- `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`
|
|
32
|
+
- `multiSelect: true`, `header: "PR"` — `postPRVisualWalkthrough`, `autoCreatePR`, `autoWatchPR`, `autoRouteBuildToMuggleDo`
|
|
33
|
+
- `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`, `autoResolveConflicts`
|
|
34
34
|
- `multiSelect: false`, `header: "E2E acceptance"` — `autoE2ETest`. Options: `Always run Stage 6 at the end` (`always` — default), `Ask each cycle` (`ask`). No `never` option.
|
|
35
35
|
- `multiSelect: false`, `header: "Default mode"` — `defaultExecutionMode`. Options: `Local — run on my computer` (`local`), `Remote — run in the Muggle Test cloud` (`remote`), `Ask each time` (don't change).
|
|
36
|
+
- `multiSelect: false`, `header: "PR watcher"` — `watcherLifetime`. Options: `Retire after 1 day` (`1d`), `Retire after 7 days` (`7d` — default), `Never retire` (`never`).
|
|
36
37
|
|
|
37
38
|
`AskUserQuestion` accepts up to 4 questions per call — split across calls.
|
|
38
39
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
2. Render `Preference | Value | Description` table titled `Muggle AI — Preferences`. Values from session context.
|
|
5
5
|
3. Footer:
|
|
6
6
|
```
|
|
7
|
-
Values: always · ask · never
|
|
7
|
+
Values: always · ask · never — except defaultExecutionMode (local/remote/ask),
|
|
8
|
+
autoE2ETest (always/ask), watcherLifetime (1d/7d/never)
|
|
8
9
|
Stored: ~/.muggle-ai/preferences.json — applies to every repo
|
|
9
10
|
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Onboard (first-run walkthrough)
|
|
2
|
+
|
|
3
|
+
Runs once per machine, when session context says Muggle Test first-run setup has not been run. Explains what Muggle Test is, then saves the user's preferences.
|
|
4
|
+
|
|
5
|
+
The CLI owns the questions and every mapping from an answer onto a preference value. Render what `muggle init --json` returns — never hardcode keys, labels, or defaults here, and never write `preferences.json` directly.
|
|
6
|
+
|
|
7
|
+
## Step 1 — answer the user first
|
|
8
|
+
|
|
9
|
+
If the user asked for something, acknowledge it before offering setup. Setup is an offer, not a gate. Never make them wait for it.
|
|
10
|
+
|
|
11
|
+
## Step 2 — load the walkthrough
|
|
12
|
+
|
|
13
|
+
Run `muggle init --json`. It returns:
|
|
14
|
+
|
|
15
|
+
- `primerHeadline`, `primerBullets` — what to show before asking anything
|
|
16
|
+
- `blanketOptions` — the dispositions, each with `choice`, `label`, `description`
|
|
17
|
+
- `groups` — per-group questions; `kind` is `toggle` or `choice`
|
|
18
|
+
|
|
19
|
+
## Step 3 — show the primer, then the blanket choice
|
|
20
|
+
|
|
21
|
+
Print `primerHeadline` and `primerBullets` verbatim. Then one `AskUserQuestion` whose options are `blanketOptions` in order, using each `label` and `description`. The first option is pre-selected.
|
|
22
|
+
|
|
23
|
+
Record the picked `choice` value.
|
|
24
|
+
|
|
25
|
+
## Step 4 — per-group questions
|
|
26
|
+
|
|
27
|
+
Only when the user picked `customize`. Otherwise skip to step 5.
|
|
28
|
+
|
|
29
|
+
For each entry in `groups`, in order:
|
|
30
|
+
|
|
31
|
+
- `kind: "toggle"` — one `multiSelect: true` question. `header` = the group's `header`, question text = its `prompt`, one option per entry using `key` as the label and `description` as the description. Pre-select every entry whose `isSelectedByDefault` is true. Collect the selected `key`s.
|
|
32
|
+
- `kind: "choice"` — one `multiSelect: false` question. `header` = the group's `header`, question text = its `prompt`, one option per entry in `options` using `label`. Pre-select the option whose `isDefault` is true. Record `key` → the picked option's `value`.
|
|
33
|
+
|
|
34
|
+
`AskUserQuestion` takes at most 4 questions per call, so split the groups across calls.
|
|
35
|
+
|
|
36
|
+
## Step 5 — apply
|
|
37
|
+
|
|
38
|
+
Write the answers to `~/.muggle-ai/temp/onboarding-answers.json`:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"blanket": "customize",
|
|
43
|
+
"selectedToggleKeys": ["autoLogin", "autoSelectProject"],
|
|
44
|
+
"choices": { "autoE2ETest": "always", "defaultExecutionMode": "local", "watcherLifetime": "7d" }
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`blanket` is the value from step 3. Include `selectedToggleKeys` and `choices` only when it is `customize`.
|
|
49
|
+
|
|
50
|
+
Run `muggle init --apply ~/.muggle-ai/temp/onboarding-answers.json`, then delete the file.
|
|
51
|
+
|
|
52
|
+
## Step 6 — confirm
|
|
53
|
+
|
|
54
|
+
Print what the CLI reported. On `skip`, say it will be offered again next session and move on — a declined offer retires itself after the third time.
|
|
@@ -4,21 +4,23 @@ One file per key in this directory — `ls preference-gates/*.md` is the
|
|
|
4
4
|
authoritative key list. Skills load this contract + only the gates they
|
|
5
5
|
actually fire.
|
|
6
6
|
|
|
7
|
-
Default allowed values: `always` / `never` / `ask`. Per-key overrides
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Default allowed values: `always` / `never` / `ask`. Per-key overrides are noted
|
|
8
|
+
in their own file: `defaultExecutionMode` (`local` / `remote` / `ask`),
|
|
9
|
+
`autoE2ETest` (`always` / `ask`), and `watcherLifetime` (`1d` / `7d` / `never`).
|
|
10
10
|
|
|
11
11
|
## Resolution
|
|
12
12
|
|
|
13
13
|
`SessionStart` injects a `Muggle Test Preferences` line (`key=value` pairs) from
|
|
14
14
|
`~/.muggle-ai/preferences.json`. Preferences are user-level — there is no
|
|
15
|
-
per-project layer.
|
|
15
|
+
per-project layer. The line carries every key, already resolved against the
|
|
16
|
+
shipped defaults in `${CLAUDE_PLUGIN_ROOT}/config/preference-defaults.json`, so a
|
|
17
|
+
key is never absent.
|
|
16
18
|
|
|
17
19
|
## Gate behavior
|
|
18
20
|
|
|
19
21
|
- `always` → take the pro-action, then **always** print the silent footer.
|
|
20
22
|
- `never` → take the skip-action, then **always** print the silent footer.
|
|
21
|
-
- `ask`
|
|
23
|
+
- `ask` → run Picker 1 (per-key file) → Picker 2 (below).
|
|
22
24
|
|
|
23
25
|
`defaultExecutionMode` uses `local`/`remote` instead of `always`/`never`.
|
|
24
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `autoResolveConflicts`
|
|
2
2
|
|
|
3
|
-
When a rebase onto `origin/{default}` hits conflicts, `always` resolves them autonomously behind a verify-or-rollback gate and `never` aborts the rebase and escalates. Take the effective value from the configured preference per [`../README.md`](../README.md#resolution) (the injected `Muggle Test Preferences` line) — don't assume a default;
|
|
3
|
+
When a rebase onto `origin/{default}` hits conflicts, `always` resolves them autonomously behind a verify-or-rollback gate and `never` aborts the rebase and escalates. Take the effective value from the configured preference per [`../README.md`](../README.md#resolution) (the injected `Muggle Test Preferences` line) — don't assume a default; the line carries every key already resolved.
|
|
4
4
|
|
|
5
5
|
**Picker 1** — header `Resolve rebase conflicts?`, question `"Rebase onto origin/{default} hit conflicts in {conflicted} file(s) — resolve them autonomously?"`
|
|
6
6
|
- `Resolve autonomously` — `Resolve the conflicts, then re-verify (build + unit + E2E) before any push; roll back and escalate if verification fails.` → `always`
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
The dev-server URL the tests will hit is a **recorded value, not a guess** — resolve it before probing anything.
|
|
6
6
|
|
|
7
7
|
1. Read the cached host with `muggle-local-last-host-get`. It reads the entry keyed on `<cwd>` in `~/.muggle-ai/last-host.json`; a worktree usually has **no cache of its own**, so when the worktree returns nothing, pass the **main** working-tree root as `cwd` — `git rev-parse --git-common-dir`, then its parent directory.
|
|
8
|
-
2. Apply the [`autoSelectLocalHost`](../../muggle-preferences/preference-gates/autoSelectLocalHost.md) gate (read its value from the `Muggle Test Preferences` session-context line
|
|
8
|
+
2. Apply the [`autoSelectLocalHost`](../../muggle-preferences/preference-gates/autoSelectLocalHost.md) gate (read its value from the `Muggle Test Preferences` session-context line, which carries every key already resolved):
|
|
9
9
|
- `always` **and** a cache exists → use it silently: `Using saved local URL {lastHost}`.
|
|
10
10
|
- otherwise (`ask` / `never`, or no cache) → **confirm before using any host.** Run the gate's Picker 1 with `{lastHost}` (cached URL, omitted when absent) and `{suggestedHost}` (a port you actually detect listening). Never auto-pick, and never fall back to a framework default like `:3000`; if nothing is cached or detected, ask the user to type the URL.
|
|
11
11
|
|
|
@@ -17,7 +17,7 @@ Load the prose companion per [e2e-instructions](./e2e-instructions.md) — `~/.m
|
|
|
17
17
|
|
|
18
18
|
## Gate `reusePreparePlan`
|
|
19
19
|
|
|
20
|
-
Per [`muggle-preferences/preference-gates/README.md`](../../muggle-preferences/preference-gates/README.md). Read the current value from the `Muggle Test Preferences` session-context line
|
|
20
|
+
Per [`muggle-preferences/preference-gates/README.md`](../../muggle-preferences/preference-gates/README.md). Read the current value from the `Muggle Test Preferences` session-context line, which carries every key already resolved.
|
|
21
21
|
|
|
22
22
|
- `always` → silently take the **reuse path** (below). Print the silent footer (substitute `{services}` with the comma-separated names from the loaded plan).
|
|
23
23
|
- `never` → take the **rediscover path**: exit this step; continue at [rebase-check](./rebase-check.md).
|