@muggleai/works 5.27.0 → 5.28.0-staging.250

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 (31) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/{chunk-6BAB7IVG.js → chunk-HBCASFGN.js} +300 -99
  3. package/dist/{chunk-B5BWBZZ5.js → chunk-KGNRBL52.js} +46 -58
  4. package/dist/cli.js +2 -2
  5. package/dist/index.js +2 -2
  6. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  7. package/dist/plugin/.codex-mcp.json +1 -1
  8. package/dist/plugin/.codex-plugin/plugin.json +1 -1
  9. package/dist/plugin/.cursor-plugin/plugin.json +1 -1
  10. package/dist/plugin/.mcp.json +1 -1
  11. package/dist/plugin/skills/_shared/dev-loop/run.md +1 -1
  12. package/dist/plugin/skills/do/pre-flight.md +1 -1
  13. package/dist/plugin/skills/muggle-test/execute-local.md +8 -6
  14. package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +4 -2
  15. package/dist/plugin/skills/muggle-test-prepare/SKILL.md +7 -4
  16. package/dist/plugin/skills/muggle-test-prepare/steps/claim-stack.md +10 -4
  17. package/dist/release-manifest.json +3 -3
  18. package/dist/src-ZOCXV6PT.js +1 -0
  19. package/package.json +2 -2
  20. package/plugin/.claude-plugin/plugin.json +1 -1
  21. package/plugin/.codex-mcp.json +1 -1
  22. package/plugin/.codex-plugin/plugin.json +1 -1
  23. package/plugin/.cursor-plugin/plugin.json +1 -1
  24. package/plugin/.mcp.json +1 -1
  25. package/plugin/skills/_shared/dev-loop/run.md +1 -1
  26. package/plugin/skills/do/pre-flight.md +1 -1
  27. package/plugin/skills/muggle-test/execute-local.md +8 -6
  28. package/plugin/skills/muggle-test-feature-local/SKILL.md +4 -2
  29. package/plugin/skills/muggle-test-prepare/SKILL.md +7 -4
  30. package/plugin/skills/muggle-test-prepare/steps/claim-stack.md +10 -4
  31. package/dist/src-MCJFH7AB.js +0 -1
@@ -8,14 +8,10 @@
8
8
  - Per-case `mode` — `replay` or `regen`, chosen during replay-vs-regen classification.
9
9
  - `cwd` — the PR-branch worktree if one exists, else the repo root.
10
10
 
11
- ## Local environment readiness
12
-
13
- Before anything else, invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) from `cwd` — the readiness/service-start owner (idempotent; halt on what it surfaces). It syncs `cwd` onto the latest base before starting anything, and serves every other repo from its latest default branch. The URL gate below only *selects* the target; prepare is what guarantees the right code is listening and compiled. Confirm its readiness table shows `cwd` as the `Source` of this repo's services, at `cwd`'s current HEAD — a different source means the run would test someone else's code; halt.
14
-
15
- Then read `~/.muggle-ai/e2e-instructions/<key>.md` when it exists — this stack's recorded startup order, manual steps, and local gotchas. Use it to interpret what you see: a gotcha listed there explains a symptom that would otherwise read as a failure. Absent is normal.
16
-
17
11
  ## Pre-flight question — Local URL (gated by `autoSelectLocalHost`)
18
12
 
13
+ Both pre-flight gates resolve before prepare runs: prepare's grant holds ports peers wait for, and its lease ends if the first run does not follow soon after the services come up.
14
+
19
15
  Skill responsibilities (the rest is in `preference-gates/autoSelectLocalHost.md`):
20
16
  - **Read the cache**: `Muggle Test Last Host: <url>` session-context line, or `muggle-local-last-host-get`. Pass as `{lastHost}` substitution.
21
17
  - **Auto-detect a suggested URL**: `lsof -iTCP -sTCP:LISTEN -nP | grep -E ':(3000|3001|4200|5173|8080)'`. Pass as `{suggestedHost}`.
@@ -30,6 +26,12 @@ Gate `showElectronBrowser` (per `preference-gates/README.md`). Resolve once; app
30
26
  - `never` → pass `showUi: false`.
31
27
  - `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
32
28
 
29
+ ## Local environment readiness
30
+
31
+ Once both pre-flight questions are answered, invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) from `cwd` — the readiness/service-start owner (idempotent; halt on what it surfaces). It syncs `cwd` onto the latest base before starting anything, and serves every other repo from its latest default branch. The URL gate above only *selects* the target; prepare is what guarantees the right code is listening and compiled. Confirm its readiness table shows `cwd` as the `Source` of this repo's services, at `cwd`'s current HEAD — a different source means the run would test someone else's code; halt. From here to the first run, ask nothing.
32
+
33
+ Then read `~/.muggle-ai/e2e-instructions/<key>.md` when it exists — this stack's recorded startup order, manual steps, and local gotchas. Use it to interpret what you see: a gotcha listed there explains a symptom that would otherwise read as a failure. Absent is normal.
34
+
33
35
  ## Prerequisite chain
34
36
 
35
37
  Before the first run, resolve each selected test case's prerequisite chain and make every ancestor ready, per [`../_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md). Ancestors are generated, never replayed, root-first; the session an ancestor leaves behind is what the target starts from, so ordering here is what makes `freshSession: false` mean anything below.
@@ -31,7 +31,7 @@ Three gates apply, each per the standard procedure in [`preference-gates/README.
31
31
 
32
32
  ## Local environment prerequisites
33
33
 
34
- Before any workflow step, invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) from the checkout under test. Halt on what it surfaces — a checkout it cannot bring onto the latest base included.
34
+ Before the first run, once every question that run needs is answered (Step 3), invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) from the checkout under test. Halt on what it surfaces — a checkout it cannot bring onto the latest base included.
35
35
 
36
36
  Then read `~/.muggle-ai/e2e-instructions/<key>.md` when it exists — this stack's recorded startup order, manual steps, and local gotchas. A gotcha listed there explains a symptom that would otherwise read as a failure. Absent is normal.
37
37
 
@@ -112,7 +112,9 @@ Prompt for projects: "Pick the project to group this test into:"
112
112
 
113
113
  ### 3. Ensure Local Services Are Ready
114
114
 
115
- Before detecting the local URL, invoke the `muggle:muggle-test-prepare` skill via the `Skill` tool from the checkout under test — every run, even when services look up. Live PIDs prove nothing about which code they serve: prepare syncs this checkout onto the latest base, starts sibling services from base checkouts on the latest default branch, and keeps a running service only when it still serves the right commit. It fast-exits when everything is proven. Once it reports ready, check its readiness table: this checkout's services must show this checkout as their `Source` at its current HEAD. Then proceed to Step 4.
115
+ **Ask first.** Prepare's grant holds ports other sessions wait for, and its lease ends four minutes after the services come up with no run. So before invoking it, resolve every question asked on the way to the first run: Step 4's URL gate, Step 5's script choice (applied after Step 4a), and Step 7's `showElectronBrowser` gate. From prepare to the first execute call, ask nothing.
116
+
117
+ Then invoke the `muggle:muggle-test-prepare` skill via the `Skill` tool from the checkout under test — every run, even when services look up. Live PIDs prove nothing about which code they serve: prepare syncs this checkout onto the latest base, starts sibling services from base checkouts on the latest default branch, and keeps a running service only when it still serves the right commit. It fast-exits when everything is proven. Once it reports ready, check its readiness table: this checkout's services must show this checkout as their `Source` at its current HEAD. Then proceed to Step 4.
116
118
 
117
119
  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.
118
120
 
@@ -91,11 +91,11 @@ Decide stages, in order; read each detail file when you reach it:
91
91
  | [derive-service-graph](./steps/derive-service-graph.md) | Derive services from workspace manifests |
92
92
  | [rebase-check](./steps/rebase-check.md) | Sync every checkout under test onto the latest base — replays too |
93
93
  | [resolve-sources](./steps/resolve-sources.md) | Pick the checkout each service runs from — replays too |
94
- | [claim-stack](./steps/claim-stack.md) | Claim the shared ports this run needs — replays too; busy returns to the caller |
95
94
  | [scope](./steps/scope.md) | Frontend / backend / full stack |
96
95
  | [viability-check](./steps/viability-check.md) | Exclude services that can't run locally |
97
96
  | [identify-services](./steps/identify-services.md) | Confirm the derived graph; fill the gaps |
98
97
  | [e2e-instructions](./steps/e2e-instructions.md) | Startup order, manual steps, local gotchas |
98
+ | [claim-stack](./steps/claim-stack.md) | Claim the shared ports this run needs, after the last question — replays too; busy returns to the caller |
99
99
 
100
100
  The Decide phase's output is the **resolved prepare plan**: `services[]` (name, run directory from [resolve-sources](./steps/resolve-sources.md), start command, expected port, `external` flag, approval granted, and the port's `keep` / `start` / `restart` from [claim-stack](./steps/claim-stack.md)), `testingScope`, `excludedServices[]`, the recorded dev-server URL, the E2E run instructions, and resolved gate outcomes.
101
101
 
@@ -132,9 +132,11 @@ Stopped 3 services:
132
132
 
133
133
  ## Integration Contract (for other skills)
134
134
 
135
- `muggle-test-feature-local`, `muggle-do`, and local-mode `muggle-test` MUST invoke this skill before any workflow step. Idempotent — fast exit when healthy. Treat success as short-lived; re-invoke if more than a few minutes pass before testing. Never bypass on "the user knows their stack is up" — that assumption is why this skill exists.
135
+ `muggle-test-feature-local`, `muggle-do`, and local-mode `muggle-test` MUST invoke this skill before their first run. Idempotent — fast exit when healthy. Never bypass on "the user knows their stack is up" — that assumption is why this skill exists.
136
136
 
137
- After a test run, the caller re-invokes for cleanup once the batch is done. Services stay up only while runs keep coming: two minutes after the last run, the lease ends and its services stop ([claim-stack](./steps/claim-stack.md#the-lease)).
137
+ **Ask first, then prepare.** Every question a caller asks before its first run — target, local URL, which script, browser visibility — is answered before it invokes this skill. From the grant to the first run nothing waits on the user or on any other work: a lease whose services are up ends four minutes later with no run, and its services stop ([claim-stack](./steps/claim-stack.md#the-lease)).
138
+
139
+ After a test run, the caller re-invokes for cleanup once the batch is done. Services stay up only while runs keep coming: two minutes after the last run, the lease ends and its services stop.
138
140
 
139
141
  **The caller's checkout.** Invoke from the checkout under test — the worktree the change lives in. Its repo is the repo under test, and its services start from that checkout; every other repo's services start from that repo's base checkout ([resolve-sources](./steps/resolve-sources.md)). Pass `base` when the change targets a branch other than the remote default.
140
142
 
@@ -158,7 +160,8 @@ The readiness table names the directory and commit each service runs from, so th
158
160
  - **Never leave orphan processes untracked** — every background PID goes into its checkout's tracking file.
159
161
  - **Never kill a process the user started independently** — `external: true` survives cleanup.
160
162
  - **Never kill or test against another checkout's service** — a listener tracked under a different checkout belongs to a peer session; see [check-running](./steps/check-running.md). The one exception is a port the stack claim planned as `restart`: no session's lease needs that service any more.
161
- - **Never start, restart or kill a service on a port this run has not claimed** — [claim-stack](./steps/claim-stack.md) runs first, and a busy stack goes back to the caller instead of being worked around.
163
+ - **Never start, restart or kill a service on a port this run has not claimed** — [claim-stack](./steps/claim-stack.md) runs before anything is started, and a busy stack goes back to the caller instead of being worked around.
164
+ - **Never hold a lease while waiting** — every question goes before [claim-stack](./steps/claim-stack.md); a `needs-input:` from the runner is a question too, so release before asking it and claim again after.
162
165
  - **Never start code that is not on the latest base** — no replay, preference, or approval skips [rebase-check](./steps/rebase-check.md) or [resolve-sources](./steps/resolve-sources.md).
163
166
  - **Never assume start commands** — verify via indicator file; confirm with user.
164
167
  - **Bail early on non-viable services** — don't start what can't run locally.
@@ -1,6 +1,6 @@
1
1
  # Claim the stack
2
2
 
3
- The machine runs **one** set of local services: one process per port, shared by every session on it. Before anything is checked, started or restarted, claim the ports this run needs, so two sessions never restart each other's services mid-run, or test against code that isn't theirs. Runs on every invocation, learning runs and replays alike, right after [resolve-sources](./resolve-sources.md) — in-session, never in the agent, because a busy stack has to reach the caller.
3
+ The machine runs **one** set of local services: one process per port, shared by every session on it. Before anything is checked, started or restarted, claim the ports this run needs, so two sessions never restart each other's services mid-run, or test against code that isn't theirs. Runs on every invocation, learning runs and replays alike, as the **last** Decide stage — after every question this run asks is answered, right before dispatching the runner — in-session, never in the agent, because a busy stack has to reach the caller. A claim made before a question holds peers' ports while the user reads it.
4
4
 
5
5
  ## Claim
6
6
 
@@ -25,23 +25,29 @@ The claim answers at once. It never waits on a peer unless asked to.
25
25
 
26
26
  ## The lease
27
27
 
28
- A granted claim is a lease, and it is held only while this session is testing. Each local execute run records itself on the lease while it is in flight. Nothing else extends it: not a re-claim, and not `muggle stack check`. So go straight from the grant to starting services and running. Never hold a lease while rebasing, editing code or waiting on CI; a renew loop cannot keep it. The lease ends, and its ports pass to whoever is next in line, when:
28
+ A granted claim is a lease, and it is held only while this session is testing. Each local execute run records itself on the lease while it is in flight. Nothing else extends it: not a re-claim, and not `muggle stack check`. So go straight from the grant to starting services and running. Never hold a lease while asking the user anything, rebasing, editing code or waiting on CI; a renew loop cannot keep it. The lease ends, and its ports pass to whoever is next in line, when:
29
29
 
30
30
  - **Two minutes pass with no run in flight** after the last run ended. That covers the turn between consecutive runs of one batch. Debugging a failure, rebasing or fixing code takes longer: the lease ends, and prepare re-claims before the next run.
31
- - **15 minutes pass after the grant with no run started.** That is the time prepare has to start its services.
31
+ - **Eight minutes pass after the grant before every claimed port serves the claimed code.** That is the time prepare has to install and start its services. A port counts as served once a service tracked at the claimed directory and commit is alive on it.
32
+ - **Four minutes pass after the services come up with no run started.** That covers the dev server's compile, the smoke test and the first execute call — not a question to the user.
32
33
  - **The session died.** Each run records the session's MCP server as a holder. Once every holder has exited and a minute has passed, the lease ends. The minute rides out an MCP server restart.
33
34
  - **It is released** in [Cleanup](../SKILL.md#cleanup).
34
35
 
36
+ A lease that ends any way but a release is remembered for 30 minutes: the checkout's next run is refused `Run refused — this checkout's stack lease ended and its services were stopped` (`muggle stack check` answers `ENDED`). Re-invoke prepare; it claims again.
37
+
35
38
  **A lease that ends takes its services with it.** Whatever listens on a port whose code no remaining lease needs is stopped. That covers services prepare started and ones started by hand, along with their launchers. The session's own MCP server ends the lease two minutes after its last run. Otherwise the next claim, run or release on the machine does it. A service marked `external: true` is never stopped, and neither is one another lease still needs.
36
39
 
37
40
  The lease belongs to the checkout, not to one run. Every test case of the same change, including cases run in parallel, runs under it, and none of them waits on the others.
38
41
 
39
- The line is first come, first served per port, and it is pulled, not pushed: nothing calls a waiting session back. A session keeps its place by asking again within the suggested delay, and is served before anyone behind it who wants the same port. A session that stops asking keeps its turn for 30 seconds after the port frees, and its place for 10 minutes.
42
+ The line is ordered per port by the checkout's open pull request: the oldest-opened PR first, so the work nearest to merging drains the backlog, and a re-run after a rebase or a review fix goes back ahead of newer PRs rather than to the end. Checkouts with no open PR yet follow, in the order they first asked. The claim finds the PR itself with `gh pr view`; without `gh` or a PR, the checkout ranks as one with none. `muggle stack status` shows each waiter's PR. The machine-wide execution lock every local run takes orders its waiters the same way.
43
+
44
+ The line is pulled, not pushed: nothing calls a waiting session back. A session keeps its place by asking again within the suggested delay, and is served before anyone behind it who wants the same port. A session that stops asking keeps its turn for 30 seconds after the port frees, and its place for 10 minutes.
40
45
 
41
46
  Holding a lease is optimistic, not exclusive. Nothing stops another process from binding a port. Instead, the local execute tools check the lease before every run and again when it ends:
42
47
 
43
48
  - A run whose port another session's lease holds, from a checkout that never claimed it, is refused: `Run refused — the target port is leased to another checkout`.
44
49
  - A run whose claimed port no longer serves the claimed code is refused: `Run refused — the service stack changed since this checkout claimed it`. Re-invoke prepare: it re-claims and restarts what moved.
50
+ - A run whose lease ended unreleased is refused: `Run refused — this checkout's stack lease ended and its services were stopped`. Re-invoke prepare.
45
51
  - A run during which the stack changed returns its result with a warning, and that result is not trusted until it has been re-run.
46
52
 
47
53
  None of these is a test result. Never route them through failure handling.
@@ -1 +0,0 @@
1
- export { ACTION_SCRIPT_FILE_NAME, BASE_REMOTE_NAME, BLOCKING_FRESHNESS_VERDICTS, BRANCH_CREATION_REFLOG_PREFIX, BUSY_EXIT_CODE, CLAUDE_CODE_AUTH_STATUS_ARGS, CLAUDE_CODE_CHECK_TIMEOUT_MS, CLAUDE_CODE_EXECUTABLE, CLAUDE_CODE_EXECUTABLE_NOT_FOUND_CODE, CLAUDE_CODE_SESSION_LINK_ENV_VARS, CLAUDE_CODE_VERSION_ARGS, CheckoutFreshnessVerdict, ClaudeCodeReadiness, DEFAULT_LOCAL_LLM_BASE_URL, DEFAULT_PREFERENCES, ELECTRON_APP_EXECUTABLE_PATH_SEGMENTS, ElectronAppPlatform, ElectronAppReleaseStream, HTML_VIEW_OFFER_LINE, LLM_CREDENTIALS_FILE_MODE, LLM_CREDENTIALS_FILE_NAME, LLM_SOURCE_HEADER, LLM_SOURCE_OPTIONS, LLM_SOURCE_OWNED_ENV_NAMES, LLM_SOURCE_PROMPT, LLM_SOURCE_SCOPE_NOTE, LlmSource, MASKED_API_KEY_PREFIX, MASKED_API_KEY_VISIBLE_CHARS, MAX_LISTED_INHERITED_COMMITS, 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, RUN_SESSIONS_DIR_NAME, RUN_VIEW_DASHBOARD_LINK_LABEL, RunViewError, RuntimeTarget, SCREENSHOT_DIR_RELATIVE_PATH, SCREENSHOT_FILE_EXTENSION, StackCheckVerdict, StackClaimVerdict, StackMismatchKind, StackPortAction, WATCHER_LIFETIME_SECONDS, WATCHER_LIFETIME_UNBOUNDED_SECONDS, applyLlmSourceSelection, applyOnboardingAnswers, assertDeviceCodeClientProvisioned, buildElectronAppChecksumsUrl, buildElectronAppDirName, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, buildLlmSourcePlan, buildOnboardingPlan, buildToolInputJsonSchema, calculateFileChecksum, checkServiceStack, claimServiceStack, completeOnboarding, createApiKeyWithToken, createChildLogger, decideStackClaim, decideStackReap, decideStackRelease, decideStackRunEnd, decideStackRunStart, deleteApiKeyData, deleteCredentials, describeLlmSourceStatus, describeStackMismatch, e2e_exports as e2e, evaluateCheckoutFreshness, findVacatedNeeds, finishStackRun, formatPreferencesOneLiner, getActiveElectronAppReleaseStream, getActiveRuntimeTarget, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDashboardBaseUrl, getDataDir2 as getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppReleaseTagPrefix, getElectronAppSignedFromVersion, getElectronAppVersion, getElectronAppVersionSource, getLlmSourceOption, getLocalQaTools, getLogger, getOnboardingToggleKeys, getPlatformKey, getQaTools, getReleaseSignerIdentityUri, getRunSessionsDir, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isElectronAppPlatform, isFirstRun, isValidLocalBaseUrl, loadApiKeyData, loadCredentials, local_exports as localQa, markOnboardingCompleted, maskLlmApiKey, mcp_exports as mcp, needsConflict, needsOnboarding, openBrowserUrl, parseElectronAppDirName, performLogin, performLogout, pollDeviceCode, portOfUrl, e2e_exports as qa, readPreferencesMetadata, readRunView, readServiceStackStatus, reapServiceStack, reconcileProjectPreferences, recordOnboardingSkip, releaseServiceStack, renderRunViewHtml, renderRunViewText, resetConfig, resetLogger, resetPreference, resolveActiveProfile, resolveActiveReleaseStream, resolveActiveReleaseTagPrefix, resolveBlanketPreferences, resolveElectronAppExecutablePath, resolveElectronAppPathOrNull, resolveLlmSourceStatus, resolveOnboardingAnswers, resolvePreferences, resolveRunSessionPath, resolveRuntimeTarget, resolveTogglePreferences, runGitCommand, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, startStackRun, stopVacatedServices, toDisplayRef, toolRequiresAuth, validatePreference, verifyFileChecksum, writeLlmEnvBlock, writePreferences, writePreferencesWithMetadata, writeRunViewHtml } from './chunk-6BAB7IVG.js';