@muggleai/works 5.18.0 → 5.19.0-staging.123
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/dist/plugin/skills/_shared/post-merge-cleanup.md +24 -5
- package/dist/plugin/skills/_shared/use-worktrees.md +2 -0
- package/dist/plugin/skills/do/cleanup.md +2 -0
- package/dist/release-manifest.json +3 -3
- package/package.json +2 -2
- package/plugin/skills/_shared/post-merge-cleanup.md +24 -5
- package/plugin/skills/_shared/use-worktrees.md +2 -0
- package/plugin/skills/do/cleanup.md +2 -0
|
@@ -6,11 +6,29 @@ On `always`, the steps below run as one pre-authorized sequence (no per-step pro
|
|
|
6
6
|
|
|
7
7
|
**Verify every step, assume none.** Each step states what proves it succeeded. A step whose side effect *usually* happens is not a step that ran — that assumption is how a branch survives a cleanup that reported success. The [report](#report) states verified state, never intent.
|
|
8
8
|
|
|
9
|
+
**A blocked step is reported, never handed back.** On `always` the gate already authorized this whole sequence, so nobody is sitting on the prompt: stopping to describe an obstacle and wait turns cleanup into a run that hangs until the user next looks at the terminal. Every step ends exactly one of three ways — done, `—` nothing to do, or `❌` with its reason in the [report](#report) and the sequence stopped. Waiting for the user is not a fourth ending. An obstacle you can clear yourself (standing in the directory you are about to remove) you clear and continue; one you cannot (a lock held by another process, a permission you lack) you record and stop. Print the report either way — the report is what tells the user cleanup is over.
|
|
10
|
+
|
|
9
11
|
## Preconditions
|
|
10
12
|
|
|
11
13
|
Confirm the PR is `MERGED` from provider state. A closed-unmerged PR keeps its branch and worktree: the work never landed, so deleting it destroys it.
|
|
12
14
|
|
|
13
|
-
## 1.
|
|
15
|
+
## 1. Leave the worktree
|
|
16
|
+
|
|
17
|
+
Only if a worktree was used. This runs **before** anything is deleted — the working directory is the precondition the rest of the sequence stands on.
|
|
18
|
+
|
|
19
|
+
`git worktree remove` refuses to remove the worktree the command is standing in, and a shell whose directory is deleted out from under it fails everything afterwards with `getcwd`/`No such file or directory`. Both surface as "cleanup can't proceed", and the reflex — announcing that you are inside the directory and waiting for the user — is the stall this step exists to prevent. Moving is yours to do; it needs no one's permission, and the gate already gave it.
|
|
20
|
+
|
|
21
|
+
1. **Resolve the anchor** — the repo's main working tree, which removing a worktree never touches:
|
|
22
|
+
```bash
|
|
23
|
+
git -C {worktreePath} worktree list --porcelain # the first `worktree ` line is the main tree
|
|
24
|
+
```
|
|
25
|
+
2. **Compare resolved paths, not strings.** Resolve the current directory and `{worktreePath}` through symlinks before asking whether one contains the other; `/var/…` against `/private/var/…` reads as "already outside" and the removal then fails anyway. Match on path segments, so a sibling like `<name>-old` is not mistaken for being inside `<name>`.
|
|
26
|
+
3. If the cwd is at or under `{worktreePath}`, move to the anchor now.
|
|
27
|
+
4. Run every remaining command against an explicit repo — `git -C <anchor> …` — so no later step walks back into the tree it is deleting.
|
|
28
|
+
|
|
29
|
+
**Verify:** the resolved cwd is outside `{worktreePath}` **and** still exists (a directory that resolves, not just a string). A cwd that was deleted rather than left is the same stall arriving one step later.
|
|
30
|
+
|
|
31
|
+
## 2. Remove the worktree — link-safe
|
|
14
32
|
|
|
15
33
|
Only if a worktree was used.
|
|
16
34
|
|
|
@@ -26,7 +44,7 @@ A worktree's dependency dir (`node_modules`, and nested workspace copies) is oft
|
|
|
26
44
|
|
|
27
45
|
**Verify:** the path is gone, it no longer appears in `git worktree list`, **and** the shared dependency tree the links pointed at still exists. That last check is the one that catches a link-follow.
|
|
28
46
|
|
|
29
|
-
##
|
|
47
|
+
## 3. Delete the local branch
|
|
30
48
|
|
|
31
49
|
**Skip entirely when no worktree was used** — the branch is then the user's live checkout, and a checked-out branch must never be deleted.
|
|
32
50
|
|
|
@@ -39,7 +57,7 @@ Do not reach for `-D` on faith. Replace the ancestry check with a content check:
|
|
|
39
57
|
|
|
40
58
|
**Verify:** the branch is absent from `git branch --list`.
|
|
41
59
|
|
|
42
|
-
##
|
|
60
|
+
## 4. Delete the remote branch
|
|
43
61
|
|
|
44
62
|
**A provider that auto-deletes the head branch on merge is a setting, not a guarantee.** It can be off for the repo, off for a fork, or simply not fire. Treat auto-delete as something to detect, never as this step having run.
|
|
45
63
|
|
|
@@ -48,7 +66,7 @@ Do not reach for `-D` on faith. Replace the ancestry check with a content check:
|
|
|
48
66
|
|
|
49
67
|
**Verify:** querying the ref returns not-found.
|
|
50
68
|
|
|
51
|
-
##
|
|
69
|
+
## 5. Clear the session slot
|
|
52
70
|
|
|
53
71
|
The slot is `~/.muggle-ai/muggle-do/sessions/<slug>/` — the home directory, not the project.
|
|
54
72
|
|
|
@@ -56,7 +74,7 @@ Clear it only when `prs.json` records a terminal state. A slot for a still-open
|
|
|
56
74
|
|
|
57
75
|
**Verify:** the slot directory is gone, and no non-terminal slot was touched.
|
|
58
76
|
|
|
59
|
-
##
|
|
77
|
+
## 6. Clear this run's prepare artifacts
|
|
60
78
|
|
|
61
79
|
The PID tracker and per-service logs written during environment prep — `/tmp/muggle-test-prepare.json` and `/tmp/muggle-prepare-*.log`.
|
|
62
80
|
|
|
@@ -75,6 +93,7 @@ Cleanup — <slug> (PR #<n>, merged)
|
|
|
75
93
|
|
|
76
94
|
| Step | Result |
|
|
77
95
|
|:----------------------|:------------------------------------------------|
|
|
96
|
+
| Left the worktree | ✅ moved to <repo root> (cwd was inside) |
|
|
78
97
|
| Worktree removed | ✅ .claude/worktrees/<name> (shared deps intact) |
|
|
79
98
|
| Local branch deleted | ✅ users/<user>/<branch> |
|
|
80
99
|
| Remote branch deleted | ✅ (already gone — provider auto-delete) |
|
|
@@ -51,3 +51,5 @@ Use this for feature development, local validation, and PR iteration.
|
|
|
51
51
|
|
|
52
52
|
After merge, remove the worktree.
|
|
53
53
|
See [`post-merge-cleanup.md`](post-merge-cleanup.md).
|
|
54
|
+
|
|
55
|
+
**Never remove a worktree you are standing in.** Step back to the repo's main working tree first — `git worktree remove` refuses from inside, and a deleted working directory breaks every command that follows. Relocating is part of teardown, not a reason to stop and ask.
|
|
@@ -13,3 +13,5 @@ Invoked by `/muggle-do` when the watcher forwards a PR's terminal state. On `mer
|
|
|
13
13
|
3. **Teardown (`merged` only).** When the PR is `merged`, run [`../_shared/post-merge-cleanup.md`](../_shared/post-merge-cleanup.md) with `{worktreePath}` and `{branch}`. That file owns the teardown sequence **and its safety rules** — including skipping worktree-remove and local branch deletion when no worktree was used. This stage adds no teardown logic of its own. On `closed`, skip teardown — the branch and any worktree stay intact.
|
|
14
14
|
4. Append a cleanup line to the session's `followup.log`, recording whether teardown ran.
|
|
15
15
|
5. Suggest the next step per [`next-step.md`](next-step.md), passing whether teardown ran. This is the stage's last action.
|
|
16
|
+
|
|
17
|
+
**Teardown never returns a question.** It finishes with its report — every step done, skipped, or blocked-with-a-reason — so steps 4 and 5 always run. A teardown that appears to be waiting on the user has stalled mid-sequence; the stage is not complete until the report and the next-step suggestion are both printed.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"release": "5.18.0",
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-09-19T08:
|
|
3
|
+
"buildId": "run-123-1",
|
|
4
|
+
"commitSha": "2b145da7762e28c9a4416e8df783c2941766c4f4",
|
|
5
|
+
"buildTime": "2026-09-19T08:36:46Z",
|
|
6
6
|
"serviceName": "muggle-ai-works-mcp"
|
|
7
7
|
}
|
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.19.0-staging.123",
|
|
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",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"muggleConfig": {
|
|
55
55
|
"electronAppVersion": "1.10.6",
|
|
56
56
|
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
|
|
57
|
-
"runtimeTargetDefault": "
|
|
57
|
+
"runtimeTargetDefault": "staging",
|
|
58
58
|
"checksumsByStream": {
|
|
59
59
|
"production": {
|
|
60
60
|
"win32-x64": "c20acdc2fd7a05039c62f9e5b079e3068d1b3a23a1b3b37b75e2a650b5401de6",
|
|
@@ -6,11 +6,29 @@ On `always`, the steps below run as one pre-authorized sequence (no per-step pro
|
|
|
6
6
|
|
|
7
7
|
**Verify every step, assume none.** Each step states what proves it succeeded. A step whose side effect *usually* happens is not a step that ran — that assumption is how a branch survives a cleanup that reported success. The [report](#report) states verified state, never intent.
|
|
8
8
|
|
|
9
|
+
**A blocked step is reported, never handed back.** On `always` the gate already authorized this whole sequence, so nobody is sitting on the prompt: stopping to describe an obstacle and wait turns cleanup into a run that hangs until the user next looks at the terminal. Every step ends exactly one of three ways — done, `—` nothing to do, or `❌` with its reason in the [report](#report) and the sequence stopped. Waiting for the user is not a fourth ending. An obstacle you can clear yourself (standing in the directory you are about to remove) you clear and continue; one you cannot (a lock held by another process, a permission you lack) you record and stop. Print the report either way — the report is what tells the user cleanup is over.
|
|
10
|
+
|
|
9
11
|
## Preconditions
|
|
10
12
|
|
|
11
13
|
Confirm the PR is `MERGED` from provider state. A closed-unmerged PR keeps its branch and worktree: the work never landed, so deleting it destroys it.
|
|
12
14
|
|
|
13
|
-
## 1.
|
|
15
|
+
## 1. Leave the worktree
|
|
16
|
+
|
|
17
|
+
Only if a worktree was used. This runs **before** anything is deleted — the working directory is the precondition the rest of the sequence stands on.
|
|
18
|
+
|
|
19
|
+
`git worktree remove` refuses to remove the worktree the command is standing in, and a shell whose directory is deleted out from under it fails everything afterwards with `getcwd`/`No such file or directory`. Both surface as "cleanup can't proceed", and the reflex — announcing that you are inside the directory and waiting for the user — is the stall this step exists to prevent. Moving is yours to do; it needs no one's permission, and the gate already gave it.
|
|
20
|
+
|
|
21
|
+
1. **Resolve the anchor** — the repo's main working tree, which removing a worktree never touches:
|
|
22
|
+
```bash
|
|
23
|
+
git -C {worktreePath} worktree list --porcelain # the first `worktree ` line is the main tree
|
|
24
|
+
```
|
|
25
|
+
2. **Compare resolved paths, not strings.** Resolve the current directory and `{worktreePath}` through symlinks before asking whether one contains the other; `/var/…` against `/private/var/…` reads as "already outside" and the removal then fails anyway. Match on path segments, so a sibling like `<name>-old` is not mistaken for being inside `<name>`.
|
|
26
|
+
3. If the cwd is at or under `{worktreePath}`, move to the anchor now.
|
|
27
|
+
4. Run every remaining command against an explicit repo — `git -C <anchor> …` — so no later step walks back into the tree it is deleting.
|
|
28
|
+
|
|
29
|
+
**Verify:** the resolved cwd is outside `{worktreePath}` **and** still exists (a directory that resolves, not just a string). A cwd that was deleted rather than left is the same stall arriving one step later.
|
|
30
|
+
|
|
31
|
+
## 2. Remove the worktree — link-safe
|
|
14
32
|
|
|
15
33
|
Only if a worktree was used.
|
|
16
34
|
|
|
@@ -26,7 +44,7 @@ A worktree's dependency dir (`node_modules`, and nested workspace copies) is oft
|
|
|
26
44
|
|
|
27
45
|
**Verify:** the path is gone, it no longer appears in `git worktree list`, **and** the shared dependency tree the links pointed at still exists. That last check is the one that catches a link-follow.
|
|
28
46
|
|
|
29
|
-
##
|
|
47
|
+
## 3. Delete the local branch
|
|
30
48
|
|
|
31
49
|
**Skip entirely when no worktree was used** — the branch is then the user's live checkout, and a checked-out branch must never be deleted.
|
|
32
50
|
|
|
@@ -39,7 +57,7 @@ Do not reach for `-D` on faith. Replace the ancestry check with a content check:
|
|
|
39
57
|
|
|
40
58
|
**Verify:** the branch is absent from `git branch --list`.
|
|
41
59
|
|
|
42
|
-
##
|
|
60
|
+
## 4. Delete the remote branch
|
|
43
61
|
|
|
44
62
|
**A provider that auto-deletes the head branch on merge is a setting, not a guarantee.** It can be off for the repo, off for a fork, or simply not fire. Treat auto-delete as something to detect, never as this step having run.
|
|
45
63
|
|
|
@@ -48,7 +66,7 @@ Do not reach for `-D` on faith. Replace the ancestry check with a content check:
|
|
|
48
66
|
|
|
49
67
|
**Verify:** querying the ref returns not-found.
|
|
50
68
|
|
|
51
|
-
##
|
|
69
|
+
## 5. Clear the session slot
|
|
52
70
|
|
|
53
71
|
The slot is `~/.muggle-ai/muggle-do/sessions/<slug>/` — the home directory, not the project.
|
|
54
72
|
|
|
@@ -56,7 +74,7 @@ Clear it only when `prs.json` records a terminal state. A slot for a still-open
|
|
|
56
74
|
|
|
57
75
|
**Verify:** the slot directory is gone, and no non-terminal slot was touched.
|
|
58
76
|
|
|
59
|
-
##
|
|
77
|
+
## 6. Clear this run's prepare artifacts
|
|
60
78
|
|
|
61
79
|
The PID tracker and per-service logs written during environment prep — `/tmp/muggle-test-prepare.json` and `/tmp/muggle-prepare-*.log`.
|
|
62
80
|
|
|
@@ -75,6 +93,7 @@ Cleanup — <slug> (PR #<n>, merged)
|
|
|
75
93
|
|
|
76
94
|
| Step | Result |
|
|
77
95
|
|:----------------------|:------------------------------------------------|
|
|
96
|
+
| Left the worktree | ✅ moved to <repo root> (cwd was inside) |
|
|
78
97
|
| Worktree removed | ✅ .claude/worktrees/<name> (shared deps intact) |
|
|
79
98
|
| Local branch deleted | ✅ users/<user>/<branch> |
|
|
80
99
|
| Remote branch deleted | ✅ (already gone — provider auto-delete) |
|
|
@@ -51,3 +51,5 @@ Use this for feature development, local validation, and PR iteration.
|
|
|
51
51
|
|
|
52
52
|
After merge, remove the worktree.
|
|
53
53
|
See [`post-merge-cleanup.md`](post-merge-cleanup.md).
|
|
54
|
+
|
|
55
|
+
**Never remove a worktree you are standing in.** Step back to the repo's main working tree first — `git worktree remove` refuses from inside, and a deleted working directory breaks every command that follows. Relocating is part of teardown, not a reason to stop and ask.
|
|
@@ -13,3 +13,5 @@ Invoked by `/muggle-do` when the watcher forwards a PR's terminal state. On `mer
|
|
|
13
13
|
3. **Teardown (`merged` only).** When the PR is `merged`, run [`../_shared/post-merge-cleanup.md`](../_shared/post-merge-cleanup.md) with `{worktreePath}` and `{branch}`. That file owns the teardown sequence **and its safety rules** — including skipping worktree-remove and local branch deletion when no worktree was used. This stage adds no teardown logic of its own. On `closed`, skip teardown — the branch and any worktree stay intact.
|
|
14
14
|
4. Append a cleanup line to the session's `followup.log`, recording whether teardown ran.
|
|
15
15
|
5. Suggest the next step per [`next-step.md`](next-step.md), passing whether teardown ran. This is the stage's last action.
|
|
16
|
+
|
|
17
|
+
**Teardown never returns a question.** It finishes with its report — every step done, skipped, or blocked-with-a-reason — so steps 4 and 5 always run. A teardown that appears to be waiting on the user has stalled mid-sequence; the stage is not complete until the report and the next-step suggestion are both printed.
|