@muggleai/works 5.0.4 → 5.2.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.
- package/README.md +2 -3
- package/dist/{chunk-KDRSEHK5.js → chunk-3HSV6EXR.js} +245 -309
- package/dist/{chunk-XO5BQZM3.js → chunk-IIQZLG34.js} +3 -4
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.cursor-plugin/plugin.json +1 -1
- package/dist/plugin/scripts/ensure-electron-app.sh +1 -1
- package/dist/plugin/scripts/guardrails.mjs +4 -2
- package/dist/plugin/skills/_shared/dev-loop/publish.md +4 -8
- package/dist/plugin/skills/_shared/pr-followup-helpers/allow-list.md +1 -1
- package/dist/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +1 -1
- package/dist/plugin/skills/_shared/resolve-e2e-validation-context.md +1 -1
- package/dist/plugin/skills/_shared/test-case-chain-readiness.md +1 -2
- package/dist/plugin/skills/_shared/vcs/CLAUDE.md +9 -0
- package/dist/plugin/skills/_shared/vcs/detect-vcs.md +28 -0
- package/{plugin/skills/_shared/github-cli-recipes → dist/plugin/skills/_shared/vcs/github}/unresolved-threads.md +1 -1
- package/{plugin/skills/_shared/github-cli-recipes → dist/plugin/skills/_shared/vcs/github}/verify-working-tree.md +1 -1
- package/dist/plugin/skills/_shared/vcs/github.md +21 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/loop-user-identity.md +9 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-create.md +11 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-discussions.md +18 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-edit.md +8 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-metadata.md +22 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-note.md +7 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-pipeline.md +27 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/reply-discussion.md +9 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/resolve-discussion.md +10 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/unresolved-discussions.md +18 -0
- package/dist/plugin/skills/_shared/vcs/gitlab.md +24 -0
- package/dist/plugin/skills/do/address-reviews.md +10 -6
- package/dist/plugin/skills/do/e2e-acceptance.md +4 -4
- package/dist/plugin/skills/do/fix-ci.md +1 -1
- package/dist/plugin/skills/do/input-routing.md +4 -4
- package/dist/plugin/skills/do/open-prs/forward.md +6 -4
- package/dist/plugin/skills/do/open-prs/update.md +8 -6
- package/dist/plugin/skills/do/per-comment-replies.md +22 -13
- package/dist/plugin/skills/do/resolve-conflicts.md +1 -1
- package/dist/plugin/skills/do/resolve-reminder.md +8 -6
- package/dist/plugin/skills/muggle-browser-task/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-do/SKILL.md +2 -2
- package/dist/plugin/skills/muggle-feedback/ops/submit.md +4 -4
- package/dist/plugin/skills/muggle-pr-followup/CLAUDE.md +2 -2
- package/dist/plugin/skills/muggle-pr-followup/bootstrap.md +13 -11
- package/dist/plugin/skills/muggle-pr-followup/contract.md +13 -9
- package/dist/plugin/skills/muggle-pr-followup/finalize.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/reconcile.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +4 -1
- package/dist/plugin/skills/muggle-pr-visual-walkthrough/e2e-report-assembly.md +13 -13
- package/dist/plugin/skills/muggle-preferences/ops/configure.md +2 -2
- package/dist/plugin/skills/muggle-preferences/preference-gates/README.md +8 -5
- package/dist/plugin/skills/muggle-test/SKILL.md +23 -126
- package/dist/plugin/skills/muggle-test/execute-local.md +60 -0
- package/dist/plugin/skills/muggle-test/execute-remote.md +49 -0
- package/dist/plugin/skills/muggle-test/reference.md +1 -2
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +5 -5
- package/dist/release-manifest.json +4 -4
- package/dist/{src-2O5UH4FA.js → src-KHZUV253.js} +1 -1
- package/package.json +8 -7
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/scripts/ensure-electron-app.sh +1 -1
- package/plugin/scripts/guardrails.mjs +4 -2
- package/plugin/skills/_shared/dev-loop/publish.md +4 -8
- package/plugin/skills/_shared/pr-followup-helpers/allow-list.md +1 -1
- package/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +1 -1
- package/plugin/skills/_shared/resolve-e2e-validation-context.md +1 -1
- package/plugin/skills/_shared/test-case-chain-readiness.md +1 -2
- package/plugin/skills/_shared/vcs/CLAUDE.md +9 -0
- package/plugin/skills/_shared/vcs/detect-vcs.md +28 -0
- package/{dist/plugin/skills/_shared/github-cli-recipes → plugin/skills/_shared/vcs/github}/unresolved-threads.md +1 -1
- package/{dist/plugin/skills/_shared/github-cli-recipes → plugin/skills/_shared/vcs/github}/verify-working-tree.md +1 -1
- package/plugin/skills/_shared/vcs/github.md +21 -0
- package/plugin/skills/_shared/vcs/gitlab/loop-user-identity.md +9 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-create.md +11 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-discussions.md +18 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-edit.md +8 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-metadata.md +22 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-note.md +7 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-pipeline.md +27 -0
- package/plugin/skills/_shared/vcs/gitlab/reply-discussion.md +9 -0
- package/plugin/skills/_shared/vcs/gitlab/resolve-discussion.md +10 -0
- package/plugin/skills/_shared/vcs/gitlab/unresolved-discussions.md +18 -0
- package/plugin/skills/_shared/vcs/gitlab.md +24 -0
- package/plugin/skills/do/address-reviews.md +10 -6
- package/plugin/skills/do/e2e-acceptance.md +4 -4
- package/plugin/skills/do/fix-ci.md +1 -1
- package/plugin/skills/do/input-routing.md +4 -4
- package/plugin/skills/do/open-prs/forward.md +6 -4
- package/plugin/skills/do/open-prs/update.md +8 -6
- package/plugin/skills/do/per-comment-replies.md +22 -13
- package/plugin/skills/do/resolve-conflicts.md +1 -1
- package/plugin/skills/do/resolve-reminder.md +8 -6
- package/plugin/skills/muggle-browser-task/SKILL.md +1 -1
- package/plugin/skills/muggle-do/SKILL.md +2 -2
- package/plugin/skills/muggle-feedback/ops/submit.md +4 -4
- package/plugin/skills/muggle-pr-followup/CLAUDE.md +2 -2
- package/plugin/skills/muggle-pr-followup/bootstrap.md +13 -11
- package/plugin/skills/muggle-pr-followup/contract.md +13 -9
- package/plugin/skills/muggle-pr-followup/finalize.md +1 -1
- package/plugin/skills/muggle-pr-followup/reconcile.md +1 -1
- package/plugin/skills/muggle-pr-followup/state-schemas.md +4 -1
- package/plugin/skills/muggle-pr-visual-walkthrough/e2e-report-assembly.md +13 -13
- package/plugin/skills/muggle-preferences/ops/configure.md +2 -2
- package/plugin/skills/muggle-preferences/preference-gates/README.md +8 -5
- package/plugin/skills/muggle-test/SKILL.md +23 -126
- package/plugin/skills/muggle-test/execute-local.md +60 -0
- package/plugin/skills/muggle-test/execute-remote.md +49 -0
- package/plugin/skills/muggle-test/reference.md +1 -2
- package/plugin/skills/muggle-test-feature-local/SKILL.md +5 -5
- package/dist/plugin/skills/_shared/github-cli-recipes.md +0 -21
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoPublishLocalResults.md +0 -11
- package/plugin/skills/_shared/github-cli-recipes.md +0 -21
- package/plugin/skills/muggle-preferences/preference-gates/autoPublishLocalResults.md +0 -11
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/line-comments-for-review.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/loop-user-identity.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-checks.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-edit.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-metadata.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/push-to-branch.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/reply-line-comment.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/submitted-reviews.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/top-level-comment.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/line-comments-for-review.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/loop-user-identity.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-checks.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-edit.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-metadata.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/push-to-branch.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/reply-line-comment.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/submitted-reviews.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/top-level-comment.md +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# GitHub CLI Recipes
|
|
2
|
+
|
|
3
|
+
Reusable `gh` / `git` snippets used by `muggle-pr-followup` (watcher + bootstrap) and `/muggle-do` (address-reviews + open-prs). Each recipe is one file — load only what you need.
|
|
4
|
+
|
|
5
|
+
Skills assume a working `gh auth status`. Auth errors surface verbatim from `gh`.
|
|
6
|
+
|
|
7
|
+
## Index
|
|
8
|
+
|
|
9
|
+
| Recipe | Use case |
|
|
10
|
+
| :----- | :------- |
|
|
11
|
+
| [`pr-metadata`](github/pr-metadata.md) | Snapshot PR state, head SHA, branch, conflict + `behind_by` out-of-date detection — watcher + bootstrap. |
|
|
12
|
+
| [`submitted-reviews`](github/submitted-reviews.md) | Fetch a review by id / watcher's body-only-review check. |
|
|
13
|
+
| [`pr-checks`](github/pr-checks.md) | Check-run rollup for the head SHA — watcher's CI poll. |
|
|
14
|
+
| [`line-comments-for-review`](github/line-comments-for-review.md) | Pull a review's line comments — `/muggle-do` per-comment routing. |
|
|
15
|
+
| [`unresolved-threads`](github/unresolved-threads.md) | GraphQL unresolved-thread state — watcher's dispatch trigger + resolve-reminder. |
|
|
16
|
+
| [`reply-line-comment`](github/reply-line-comment.md) | POST a threaded reply on a line comment. |
|
|
17
|
+
| [`top-level-comment`](github/top-level-comment.md) | POST a top-level PR comment — resolve-reminder + overflow. |
|
|
18
|
+
| [`push-to-branch`](github/push-to-branch.md) | Push + capture new SHA after address-reviews work. |
|
|
19
|
+
| [`verify-working-tree`](github/verify-working-tree.md) | Three checks bootstrap runs before seeding state. |
|
|
20
|
+
| [`pr-edit`](github/pr-edit.md) | Refresh title or body when address-reviews mode flips state. |
|
|
21
|
+
| [`loop-user-identity`](github/loop-user-identity.md) | Resolve the GitHub login of the loop user. |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Identify the loop user
|
|
2
|
+
|
|
3
|
+
The GitLab identity that owns the authenticated `glab` token. Resolve-reminder thread classification and reply attribution need this.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab api user --jq '.username'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Cache in `state.md` under `Loop user:`; re-resolve only when missing.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Open a merge request
|
|
2
|
+
|
|
3
|
+
For `open-prs`. Push the branch first (see [`../github/push-to-branch.md`](../github/push-to-branch.md)), then open the MR.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab mr create -R <group>/<project> \
|
|
7
|
+
--source-branch <branch> --target-branch <base> \
|
|
8
|
+
--title "<title>" --description "$(cat <file>)"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`glab` prints the created MR's URL on success — capture stdout and store the URL for handoff (the watcher seeds from it, the user gets the link).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# MR discussions
|
|
2
|
+
|
|
3
|
+
Incoming feedback for the watcher's poll and the address-reviews fetch. GitLab has **no review envelope** — there is no submitted-review object grouping a summary body with line comments. Feedback arrives as individual notes, each belonging to a discussion (a thread). This recipe is the `submitted-reviews` analogue.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab api projects/:id/merge_requests/:iid/discussions --paginate
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Each discussion has `id` and a `notes[]` array; each note has `id`, `author.username`, `body`, `created_at`, `system` (a `true` flag marks GitLab's own activity entries — skip them).
|
|
10
|
+
|
|
11
|
+
Common filter:
|
|
12
|
+
|
|
13
|
+
- `system == false` (skip "added 2 commits", "changed the description", etc.)
|
|
14
|
+
- `author.username` in the resolved allow-list
|
|
15
|
+
|
|
16
|
+
Cursor: track the highest note/discussion `id` seen in `last_seen`; a note whose `id` exceeds it is new this tick. (GitLab ids are monotonic, so id ordering is reliable where `created_at` ties.)
|
|
17
|
+
|
|
18
|
+
Loop-echo skip: a note the loop itself posted carries the `<!-- muggle-do:bot -->` marker in its `body`. Classify by that marker per note, never by `author.username` alone — under a shared account the login is ambiguous. A marked note is the loop's own and must never re-trigger a cycle; an unmarked note from an allow-listed author is actionable.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Refresh the MR title or description
|
|
2
|
+
|
|
3
|
+
For `open-prs/update.md` when E2E state flips (passing↔failing) or validation strategy changes. GitLab calls the body the **description**.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab mr update <iid> -R <group>/<project> --title "<new-title>"
|
|
7
|
+
glab mr update <iid> -R <group>/<project> --description "$(cat <file>)"
|
|
8
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# MR metadata snapshot
|
|
2
|
+
|
|
3
|
+
Fetch the fields the watcher and bootstrap need.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab mr view <iid> -R <group>/<project> -F json
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
- `state` is one of `opened`, `merged`, `closed`, `locked` (lowercase — unlike GitHub's uppercase).
|
|
10
|
+
- `sha` is the current head SHA — store as `head_sha` in `prs.json`.
|
|
11
|
+
- `source_branch` is the branch — must match the working tree's branch in bootstrap. `target_branch` is the base.
|
|
12
|
+
- conflict comes from `detailed_merge_status`, not a `mergeable` + `mergeStateStatus` pair. The watcher's **conflict** signal is `detailed_merge_status == "broken_status"` or `"conflict"`. `"checking"`/`"unchecked"` means GitLab is still computing — treat as not-conflicting this tick.
|
|
13
|
+
|
|
14
|
+
## Behind-by (out-of-date detection)
|
|
15
|
+
|
|
16
|
+
`detailed_merge_status == "need_rebase"` reports a behind branch only when the project enforces "fast-forward merge"; otherwise it stays `mergeable` while behind. Detect out-of-date straight from commit ancestry instead — independent of merge-method config:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
glab api projects/:id/repository/compare?from=<target_branch>&to=<head_sha> --jq '.commits | length'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
GitLab's compare lists only the commits `to` is ahead by, so flip the direction: compare `from=<head_sha>&to=<target_branch>` and a non-empty `.commits` ⇒ the base has commits the head lacks ⇒ out of date. Empty ⇒ current with base.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# MR pipeline rollup
|
|
2
|
+
|
|
3
|
+
Fetch the CI state for an MR's head — what the watcher polls to detect red CI. GitLab runs **one** pipeline of jobs per commit, not independent check-runs, so the rollup is over that pipeline's jobs.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab ci status -R <group>/<project> -b <source_branch>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Or straight from the API for the latest pipeline and its jobs:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
glab api projects/:id/merge_requests/:iid/pipelines --jq '.[0].id'
|
|
13
|
+
glab api projects/:id/pipelines/<pipeline-id>/jobs --paginate
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Each job:
|
|
17
|
+
|
|
18
|
+
- `name` — the job's name (e.g. `lint`, `test`, `build`).
|
|
19
|
+
- `status` — one of `success` / `failed` / `running` / `pending` / `created` / `canceled` / `skipped` / `manual`.
|
|
20
|
+
|
|
21
|
+
Classify for the watcher:
|
|
22
|
+
|
|
23
|
+
- **red** — any job `failed`. Candidate for fix-ci.
|
|
24
|
+
- **pending** — no job `failed`, but any job `running` / `pending` / `created`. Pipeline hasn't settled → idle.
|
|
25
|
+
- **green** — every job `success` / `skipped` / `manual` / `canceled`, or no jobs at all.
|
|
26
|
+
|
|
27
|
+
The fix-ci dispatch carries the `name`s of the `failed` jobs.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Reply to a discussion (threaded)
|
|
2
|
+
|
|
3
|
+
Used by `/muggle-do` per-comment inline replies. A threaded reply is a new note appended to an existing discussion.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab api --method POST \
|
|
7
|
+
projects/:id/merge_requests/:iid/discussions/<discussion-id>/notes \
|
|
8
|
+
-f body="<reply-text>"
|
|
9
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Resolve a discussion thread
|
|
2
|
+
|
|
3
|
+
Mark a thread resolved once the loop's reply has addressed it — the resolve-reminder stage's action.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab api --method PUT \
|
|
7
|
+
"projects/:id/merge_requests/:iid/discussions/<discussion-id>?resolved=true"
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Resolves every resolvable note in the thread at once. Only resolvable (diff/line) threads accept this; a non-resolvable discussion returns an error.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Unresolved discussions
|
|
2
|
+
|
|
3
|
+
For the watcher's dispatch trigger and the resolve-reminder stage. REST exposes resolution directly — no GraphQL needed, unlike GitHub.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
glab api projects/:id/merge_requests/:iid/discussions --paginate \
|
|
7
|
+
--jq '[.[] | select(.notes[0].resolvable == true) | select(any(.notes[]; .resolved == false))]'
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
A discussion is resolvable when its notes carry `resolvable == true` (diff/line threads are; the MR description and system notes are not). A thread is **unresolved** when any of its notes has `resolved == false`.
|
|
11
|
+
|
|
12
|
+
Walk each unresolved thread's `notes[]` in `created_at` order and classify by the loop marker (see [`../../pr-followup-helpers/loop-signature.md`](../../pr-followup-helpers/loop-signature.md)), not by `author.username` — the login is ambiguous under a shared account:
|
|
13
|
+
|
|
14
|
+
- **Addressed, awaiting resolve** — the **newest** note carries `<!-- muggle-do:bot -->`. The loop has replied and nothing newer waits. → resolve-reminder.
|
|
15
|
+
- **Unaddressed human comment** — the newest note lacks the marker and is newer than the thread's newest loop-marked note (or the thread has none yet). → actionable: the round should address it.
|
|
16
|
+
- **Not addressed** — indeterminate (e.g. no notes).
|
|
17
|
+
|
|
18
|
+
Each thread carries its `id` (the `discussion_id`) — the watcher collects this from an actionable thread to build its dispatch list and to target the resolve call later.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# GitLab CLI Recipes
|
|
2
|
+
|
|
3
|
+
Reusable `glab` / `git` snippets used by `muggle-pr-followup` (watcher + bootstrap) and `/muggle-do` (address-reviews + open-prs), mirroring the `gh` set for GitLab merge requests. Each recipe is one file — load only what you need.
|
|
4
|
+
|
|
5
|
+
Skills assume a working `glab auth status`. Auth errors surface verbatim from `glab`.
|
|
6
|
+
|
|
7
|
+
The project ref `:id` is `<group>/<project>` — URL-encode it for `glab api` (`mygroup/myproj` → `mygroup%2Fmyproj`). `:iid` is the MR's per-project internal id (the `!123` number), not the global id.
|
|
8
|
+
|
|
9
|
+
## Index
|
|
10
|
+
|
|
11
|
+
| Recipe | Use case |
|
|
12
|
+
| :----- | :------- |
|
|
13
|
+
| [`mr-metadata`](gitlab/mr-metadata.md) | Snapshot MR state, head SHA, branch, conflict + out-of-date detection — watcher + bootstrap. |
|
|
14
|
+
| [`mr-pipeline`](gitlab/mr-pipeline.md) | Pipeline-job rollup for the head SHA — watcher's CI poll. |
|
|
15
|
+
| [`mr-discussions`](gitlab/mr-discussions.md) | Fetch incoming notes/discussions — watcher's feedback poll. |
|
|
16
|
+
| [`unresolved-discussions`](gitlab/unresolved-discussions.md) | Unresolved-discussion state — watcher's dispatch trigger + resolve-reminder. |
|
|
17
|
+
| [`reply-discussion`](gitlab/reply-discussion.md) | POST a threaded reply on a discussion. |
|
|
18
|
+
| [`mr-note`](gitlab/mr-note.md) | POST a top-level MR note — resolve-reminder + overflow. |
|
|
19
|
+
| [`resolve-discussion`](gitlab/resolve-discussion.md) | Mark a discussion thread resolved. |
|
|
20
|
+
| [`mr-edit`](gitlab/mr-edit.md) | Refresh title or description when address-reviews mode flips state. |
|
|
21
|
+
| [`mr-create`](gitlab/mr-create.md) | Open an MR + capture its URL for handoff. |
|
|
22
|
+
| [`loop-user-identity`](gitlab/loop-user-identity.md) | Resolve the GitLab username of the loop user. |
|
|
23
|
+
| [`push-to-branch`](github/push-to-branch.md) | Push + capture new SHA after address-reviews work (provider-agnostic). |
|
|
24
|
+
| [`verify-working-tree`](github/verify-working-tree.md) | Three checks bootstrap runs before seeding state (provider-agnostic). |
|
|
@@ -33,17 +33,21 @@ Before assembling work, rebase onto the latest default branch so the cycle addre
|
|
|
33
33
|
|
|
34
34
|
### Step 1 — Assemble the work set
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Resolve the provider per [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md), then assemble.
|
|
37
|
+
|
|
38
|
+
**`github`** — two sources, combined into one batch (dedupe by comment id):
|
|
37
39
|
|
|
38
40
|
**(a) The dispatched reviews.** For each review id in the input:
|
|
39
41
|
|
|
40
|
-
- Fetch reviews per [`../_shared/github
|
|
41
|
-
- Fetch its line comments per [`../_shared/github
|
|
42
|
+
- Fetch reviews per [`../_shared/vcs/github/submitted-reviews.md`](../_shared/vcs/github/submitted-reviews.md) (no watermark; filter to the specific id).
|
|
43
|
+
- Fetch its line comments per [`../_shared/vcs/github/line-comments-for-review.md`](../_shared/vcs/github/line-comments-for-review.md).
|
|
42
44
|
|
|
43
|
-
**(b) Unaddressed comments on every unresolved thread.** Fetch unresolved threads per [`../_shared/github
|
|
45
|
+
**(b) Unaddressed comments on every unresolved thread.** Fetch unresolved threads per [`../_shared/vcs/github/unresolved-threads.md`](../_shared/vcs/github/unresolved-threads.md). For each thread classified **unaddressed human comment** — newest comment lacks the loop marker `<!-- muggle-do:bot -->` ([`loop-signature.md`](../_shared/pr-followup-helpers/loop-signature.md)) and post-dates the loop's last marked reply — add it to the batch — unresolved thread state, not any review-id watermark, is the authority here. This is how a human thread follow-up (a marker-less reply) gets addressed. **Exclude** comments whose review id is in `last_seen.escalated_review_ids` — paused awaiting the user, not re-work.
|
|
44
46
|
|
|
45
47
|
Group (a) and (b) into one combined batch.
|
|
46
48
|
|
|
49
|
+
**`gitlab`** — single source (no review-id watermark; discussion state is the sole authority). Fetch unresolved discussions per [`../_shared/vcs/gitlab/unresolved-discussions.md`](../_shared/vcs/gitlab/unresolved-discussions.md) (drop to [`../_shared/vcs/gitlab/mr-discussions.md`](../_shared/vcs/gitlab/mr-discussions.md) for raw notes where classification needs them). The input ids are discussion ids; the batch is every discussion classified **unaddressed human comment** — newest note lacks the marker and post-dates the loop's last marked note. **Exclude** discussions whose id is in `last_seen.escalated_review_ids`. A discussion is the unit of work in place of GitHub's review + line-comment pair.
|
|
50
|
+
|
|
47
51
|
### Step 2 — Classify each review
|
|
48
52
|
|
|
49
53
|
Apply the classify rule in [`../_shared/pr-followup-helpers/classify.md`](../_shared/pr-followup-helpers/classify.md). Two outcomes per review:
|
|
@@ -93,7 +97,7 @@ Invoke [`open-prs/update.md`](open-prs/update.md) (pass the PR URL + slug + exis
|
|
|
93
97
|
|
|
94
98
|
#### 4f. Post per-comment inline replies
|
|
95
99
|
|
|
96
|
-
Invoke [`per-comment-replies.md`](per-comment-replies.md) with the actionable reviews and the new SHA. One reply per comment, in its own thread, describing what was done for it.
|
|
100
|
+
Invoke [`per-comment-replies.md`](per-comment-replies.md) with the actionable reviews (`gitlab`: discussions) and the new SHA. One reply per comment, in its own thread, describing what was done for it; on `gitlab` the same step also resolves each fully-addressed discussion.
|
|
97
101
|
|
|
98
102
|
(The resolve-reminder runs once per round in Step 5.5 below — not only after a push — so a round that pushed nothing still nudges addressed-but-unresolved threads.)
|
|
99
103
|
|
|
@@ -109,7 +113,7 @@ Invoke [`resolve-reminder.md`](resolve-reminder.md) once, regardless of whether
|
|
|
109
113
|
|
|
110
114
|
### Step 6 — Respawn the watcher
|
|
111
115
|
|
|
112
|
-
Refresh PR state per [`../_shared/github
|
|
116
|
+
Refresh PR state with the provider resolved in Step 1 — `github` per [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md), `gitlab` per [`../_shared/vcs/gitlab/mr-metadata.md`](../_shared/vcs/gitlab/mr-metadata.md) (`state == merged`/`closed`, lowercase). If the PR is now merged or closed:
|
|
113
117
|
|
|
114
118
|
1. Write `result.md` per [`../muggle-pr-followup/state-schemas.md`](../muggle-pr-followup/state-schemas.md#resultmd).
|
|
115
119
|
2. Do **not** respawn the watcher.
|
|
@@ -27,7 +27,7 @@ For local runs, the tool boundaries are:
|
|
|
27
27
|
| Scope | MCP tools |
|
|
28
28
|
| :---- | :-------- |
|
|
29
29
|
| Cloud (projects, cases, scripts, auth) | `muggle-remote-*` |
|
|
30
|
-
| Local (Electron run,
|
|
30
|
+
| Local (Electron run, results — the studio publishes during the run) | `muggle-local-*` |
|
|
31
31
|
|
|
32
32
|
This keeps execution deterministic: local runs do not depend on cloud replay execution availability.
|
|
33
33
|
|
|
@@ -96,9 +96,9 @@ Based on the changed files and the requirements goal, determine which test cases
|
|
|
96
96
|
- Test cases that cover areas potentially affected by the changes
|
|
97
97
|
- When in doubt, include the test case (better to over-test than miss a regression)
|
|
98
98
|
|
|
99
|
-
### Step 4: Run the dev loop,
|
|
99
|
+
### Step 4: Run the dev loop, gather screenshots
|
|
100
100
|
|
|
101
|
-
For each relevant test case, run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): `muggle-remote-test-script-list` by `testCaseId` to pick [replay vs regen](../_shared/dev-loop/run.md), [execute with `timeoutMs`](../_shared/dev-loop/timeouts.md), [fetch the result](../_shared/dev-loop/failures.md) and [interpret failures](../_shared/dev-loop/failures.md),
|
|
101
|
+
For each relevant test case, run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): `muggle-remote-test-script-list` by `testCaseId` to pick [replay vs regen](../_shared/dev-loop/run.md), [execute with `timeoutMs`](../_shared/dev-loop/timeouts.md), [fetch the result](../_shared/dev-loop/failures.md) and [interpret failures](../_shared/dev-loop/failures.md), then read the studio-published [cloud refs and per-step screenshots](../_shared/dev-loop/publish.md) off the run result.
|
|
102
102
|
|
|
103
103
|
Inputs to the loop: `mode` from the script-exists check, `localUrl`/project from Step 1.7, `cwd` = the working tree recorded in `state.md`.
|
|
104
104
|
|
|
@@ -161,5 +161,5 @@ Failed runs use the same evidence + diagnosis assembly as the interactive debug
|
|
|
161
161
|
- Replay/timeout/result discipline per [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md) — never hand-build `actionScript`, always pass `timeoutMs`, read structured run-result fields.
|
|
162
162
|
- No hiding failures: surface errors, exit codes, and artifact paths.
|
|
163
163
|
- In `local-e2e` mode, every relevant test case must be executed — generate a new script if none exists (no skips).
|
|
164
|
-
-
|
|
164
|
+
- The studio publishes every run during execution, so screenshots are cloud-accessible for PR comments — read the refs off the run result, never re-publish.
|
|
165
165
|
- **Never drop a test case from the report because it "couldn't run cleanly."** A test that didn't reach its assertion is `inconclusive`, not absent. Dropping it produces misleading verdicts and pushes downstream PR-comment renderers to hand-write the comment — which is the failure mode this stage exists to prevent.
|
|
@@ -10,7 +10,7 @@ Resolve red CI on a PR's head — lint/format, typecheck, and failing unit tests
|
|
|
10
10
|
|
|
11
11
|
## Input
|
|
12
12
|
|
|
13
|
-
`$ARGUMENTS` carries a `github.com/.../pull/<n>`
|
|
13
|
+
`$ARGUMENTS` carries a PR/MR URL (`github.com/.../pull/<n>` or `<host>/<group>/<project>/-/merge_requests/<iid>`), `slug=<slug>`, and the failing check names (no review ids). Parse all three. The names are GitHub check-runs or — when the URL resolves `gitlab` per [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md) — the failed pipeline-job names the watcher read off [`../_shared/vcs/gitlab/mr-pipeline.md`](../_shared/vcs/gitlab/mr-pipeline.md); the fix cycle below is identical for either.
|
|
14
14
|
|
|
15
15
|
## Inputs from disk
|
|
16
16
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Input routing
|
|
2
2
|
|
|
3
|
-
How `/muggle-do` resolves `$ARGUMENTS` to a mode. Modes 1–4 are programmatic — dispatched by the watcher — so never ask on those. Inspect in order:
|
|
3
|
+
How `/muggle-do` resolves `$ARGUMENTS` to a mode. Modes 1–4 are programmatic — dispatched by the watcher — so never ask on those. A change-URL in modes 1–3 is either a GitHub PR (`github.com/.../pull/<n>`) or a GitLab MR (`<host>/.../-/merge_requests/<iid>`); provider is resolved via [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md). Inspect in order:
|
|
4
4
|
|
|
5
|
-
1. **Address-reviews** — a
|
|
6
|
-
2. **Fix-CI** — a
|
|
7
|
-
3. **Rebase** — a
|
|
5
|
+
1. **Address-reviews** — a PR/MR URL **and** an address-reviews directive carrying review/discussion ids → [`address-reviews.md`](address-reviews.md). On GitHub these ids are integers ≥ 100000000; that magnitude is GitHub-specific lore, **not** a portable test. Under GitLab, tell this apart from other directives by the directive keyword plus the presence of discussion ids, never by id size.
|
|
6
|
+
2. **Fix-CI** — a PR/MR URL **and** a `fix ci` / `fix-ci` directive with failing check names (no review/discussion ids) → [`fix-ci.md`](fix-ci.md).
|
|
7
|
+
3. **Rebase** — a PR/MR URL **and** a `rebase` directive (or legacy `resolve conflicts` / `resolve-conflicts`; no review/discussion ids, no check names) → [`resolve-conflicts.md`](resolve-conflicts.md). Rebases the branch onto its base whether it's merely behind or actually conflicting.
|
|
8
8
|
4. **Post-merge cleanup** — a `cleanup` token and `slug=<slug>` (no PR URL, no review ids), optionally `state=<merged|closed>` (default `merged`) → [`cleanup.md`](cleanup.md).
|
|
9
9
|
5. **Empty / `help` / `menu` / `?`** → menu + session selector.
|
|
10
10
|
6. **Task automation** (perform an action on a website) → `muggle:muggle-browser-task`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Open PR — forward mode
|
|
2
2
|
|
|
3
|
-
Forward pipeline's Stage 7. Invoked by `/muggle-do` after stages 1–6 of a fresh feature.
|
|
3
|
+
Forward pipeline's Stage 7. Invoked by `/muggle-do` after stages 1–6 of a fresh feature. Opens the change — a PR on GitHub (`gh pr create`) or an MR on GitLab (`glab mr create`), provider resolved in Step 4 — then seeds session state and dispatches the first watcher.
|
|
4
4
|
|
|
5
5
|
## Turn preamble
|
|
6
6
|
|
|
@@ -30,11 +30,13 @@ Forward pipeline's Stage 7. Invoked by `/muggle-do` after stages 1–6 of a fres
|
|
|
30
30
|
- `## Acceptance Criteria` — bulleted; omit if empty.
|
|
31
31
|
- `## Changes` — summary of what changed in this repo.
|
|
32
32
|
- `## Validation` — one line: link to E2E report, `unit-only`, or `skip — <reason>`.
|
|
33
|
-
- **
|
|
33
|
+
- **Walkthrough block** — only when an E2E report exists. Fire [`postPRVisualWalkthrough`](../../muggle-preferences/preference-gates/postPRVisualWalkthrough.md); on skip, omit this block. Otherwise invoke [`../../muggle-pr-visual-walkthrough/SKILL.md`](../../muggle-pr-visual-walkthrough/SKILL.md) Mode B and embed the returned `body` verbatim. No report → skip the block.
|
|
34
34
|
|
|
35
|
-
4. **Create:**
|
|
35
|
+
4. **Create:** resolve the provider per [`../../_shared/vcs/detect-vcs.md`](../../_shared/vcs/detect-vcs.md).
|
|
36
|
+
- `github` → `gh pr create --title "..." --body "..." --head <branch>`. Capture the PR URL and number.
|
|
37
|
+
- `gitlab` → open the change via [`../../_shared/vcs/gitlab/mr-create.md`](../../_shared/vcs/gitlab/mr-create.md): `glab mr create --source-branch <branch> --target-branch <base> --title "..." --description "..."`. Capture the MR URL and iid.
|
|
36
38
|
|
|
37
|
-
5. **Overflow comment:** if the walkthrough skill returned a non-null `comment`, post it once per [`../../_shared/github
|
|
39
|
+
5. **Overflow comment:** if the walkthrough skill returned a non-null `comment`, post it once using the provider resolved in Step 4 — `github` per [`../../_shared/vcs/github/top-level-comment.md`](../../_shared/vcs/github/top-level-comment.md), `gitlab` per [`../../_shared/vcs/gitlab/mr-note.md`](../../_shared/vcs/gitlab/mr-note.md). Never post when `comment` is `null`.
|
|
38
40
|
|
|
39
41
|
## Stage 8 handoff
|
|
40
42
|
|
|
@@ -20,21 +20,23 @@ Does **not** create a PR, seed session state, or dispatch a watcher (`/muggle-do
|
|
|
20
20
|
|
|
21
21
|
Skip `autoCreatePR` (it gates creation, not update). The PR's title is left intact unless state changed in Step 3.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Resolve the provider once per [`../../_shared/vcs/detect-vcs.md`](../../_shared/vcs/detect-vcs.md). Wherever Steps 3–4 below edit title/description: `github` uses `gh pr edit` per [`../../_shared/vcs/github/pr-edit.md`](../../_shared/vcs/github/pr-edit.md); `gitlab` uses `glab mr update --title --description` per [`../../_shared/vcs/gitlab/mr-edit.md`](../../_shared/vcs/gitlab/mr-edit.md).
|
|
24
|
+
|
|
25
|
+
1. **Push:** per [`../../_shared/vcs/github/push-to-branch.md`](../../_shared/vcs/github/push-to-branch.md). Capture the new SHA.
|
|
24
26
|
|
|
25
27
|
2. **Append new SHA** to `last_seen.json[<key>].pushed_shas` (the resolve-reminder stage uses this to recognize threads addressed by the loop). Set `last_seen.last_pushed_sha` to the new SHA too.
|
|
26
28
|
|
|
27
29
|
3. **Refresh title if state changed.** Compare the new state against the current PR title prefix:
|
|
28
|
-
- E2E now passing, current title has `[E2E FAILING]` → strip the prefix per [`../../_shared/github
|
|
30
|
+
- E2E now passing, current title has `[E2E FAILING]` → strip the prefix per [`../../_shared/vcs/github/pr-edit.md`](../../_shared/vcs/github/pr-edit.md).
|
|
29
31
|
- E2E now failing, current title has no `[E2E FAILING]` → add the prefix.
|
|
30
32
|
- Validation now ran (was unit-only/skip, now has E2E report) → strip `[UNVERIFIED]` or `[UNIT-ONLY]`.
|
|
31
33
|
- Otherwise → no title change.
|
|
32
34
|
|
|
33
|
-
4. **Refresh body when validation outcome changed** — only when the `## Validation` section's content differs from what's in the body. Use the `--body-file` form in [`../../_shared/github
|
|
35
|
+
4. **Refresh body when validation outcome changed** — only when the `## Validation` section's content differs from what's in the body. Use the `--body-file` form in [`../../_shared/vcs/github/pr-edit.md`](../../_shared/vcs/github/pr-edit.md). Preserve `## Goal` and `## Acceptance Criteria` verbatim.
|
|
34
36
|
|
|
35
|
-
5. **Visual walkthrough comment** —
|
|
37
|
+
5. **Visual walkthrough comment** — only when an E2E report exists. Fire [`postPRVisualWalkthrough`](../../muggle-preferences/preference-gates/postPRVisualWalkthrough.md) (PR number from `prs.json`); on skip, record `skipped (gate)` and continue. Otherwise invoke [`../../muggle-pr-visual-walkthrough/SKILL.md`](../../muggle-pr-visual-walkthrough/SKILL.md) Mode A — a fresh comment per cycle; do not edit prior walkthrough comments.
|
|
36
38
|
|
|
37
|
-
6. **Overflow comment** — same rule as forward mode: post when the walkthrough skill returns non-null `comment`, via [`../../_shared/github
|
|
39
|
+
6. **Overflow comment** — same rule as forward mode: post when the walkthrough skill returns non-null `comment`, via [`../../_shared/vcs/github/top-level-comment.md`](../../_shared/vcs/github/top-level-comment.md).
|
|
38
40
|
|
|
39
41
|
## Handoff
|
|
40
42
|
|
|
@@ -50,5 +52,5 @@ Return control to `/muggle-do`'s address-reviews orchestrator. The orchestrator
|
|
|
50
52
|
**PR updated:** URL (new SHA: `<short-sha>`)
|
|
51
53
|
**Title refreshed:** yes | no
|
|
52
54
|
**Body refreshed:** yes | no
|
|
53
|
-
**Walkthrough comment:** posted | skipped (no report)
|
|
55
|
+
**Walkthrough comment:** posted | skipped (no report) | skipped (gate)
|
|
54
56
|
**Overflow comment:** posted | skipped
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
A `/muggle-do` step invoked from [`address-reviews.md`](address-reviews.md) (Step 4f) after the push has succeeded. Posts one inline nested reply on each line comment from the actionable reviews, describing what was done for that comment and referencing the new SHA.
|
|
4
4
|
|
|
5
|
-
This is **not** a top-level "summary reply on the review." Each comment thread gets its own reply, in context
|
|
5
|
+
This is **not** a top-level "summary reply on the review." Each comment thread gets its own reply, in context — on `github` via the `/comments/{id}/replies` endpoint, on `gitlab` via a threaded note on the discussion.
|
|
6
6
|
|
|
7
7
|
## Inputs
|
|
8
8
|
|
|
9
|
-
- `actionable_reviews` — the list of reviews classified actionable in `address-reviews.md` Step 2.
|
|
9
|
+
- `actionable_reviews` — the list of reviews classified actionable in `address-reviews.md` Step 2. On `gitlab`, these are the actionable **discussions** (no review envelope) — read each as a thread of notes.
|
|
10
10
|
- `new_sha` — the SHA `open-prs/update.md` just pushed.
|
|
11
|
-
- The PR's owner, repo, number.
|
|
11
|
+
- The PR's owner, repo, number. On `gitlab`, the project ref and MR iid.
|
|
12
|
+
|
|
13
|
+
Resolve the provider once per [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md).
|
|
12
14
|
|
|
13
15
|
## Procedure
|
|
14
16
|
|
|
@@ -23,14 +25,18 @@ If a comment has no associated change in either source (e.g. the comment was a q
|
|
|
23
25
|
|
|
24
26
|
### Step 2 — Post one reply per comment
|
|
25
27
|
|
|
26
|
-
For each comment id with a description:
|
|
28
|
+
For each comment id with a description, post the reply with the resolved provider:
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
- **`github`** — nested reply on the line comment:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
gh api --method POST \
|
|
34
|
+
-H "Accept: application/vnd.github+json" \
|
|
35
|
+
repos/<owner>/<repo>/pulls/<n>/comments/<comment-id>/replies \
|
|
36
|
+
-f body="<reply-body>"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- **`gitlab`** — one threaded note per actionable discussion per [`../_shared/vcs/gitlab/reply-discussion.md`](../_shared/vcs/gitlab/reply-discussion.md) (the discussion id stands in for the comment id), then resolve each fully-addressed thread per [`../_shared/vcs/gitlab/resolve-discussion.md`](../_shared/vcs/gitlab/resolve-discussion.md). The loop-marked reply is the addressed signal; the resolve is GitLab's equivalent of a reviewer closing the thread, which the loop can do directly. Resolving folds the discussion out of the next tick's actionable set, so no separate resolve-reminder nudge is needed for it.
|
|
34
40
|
|
|
35
41
|
Reply body uses the template in [`../muggle-pr-followup/output-templates/inline-reply.md`](../muggle-pr-followup/output-templates/inline-reply.md):
|
|
36
42
|
|
|
@@ -43,7 +49,10 @@ Addressed in <short-sha>: <one-line summary of the change made for THIS comment>
|
|
|
43
49
|
|
|
44
50
|
`<short-sha>` is the first 7 chars of `new_sha`; the body must contain that substring so the resolve-reminder stage knows which push addressed the thread. The trailing signature block is mandatory — its `<!-- muggle-do:bot -->` marker is what identifies the reply as loop-authored (see [`../_shared/pr-followup-helpers/loop-signature.md`](../_shared/pr-followup-helpers/loop-signature.md)).
|
|
45
51
|
|
|
46
|
-
### Step 3 — Handle review-body-only comments
|
|
52
|
+
### Step 3 — Handle review-body-only comments (GitHub only)
|
|
53
|
+
|
|
54
|
+
GitLab has no review envelope — every note belongs to a discussion handled in Step 2 — so this step is GitHub-only.
|
|
55
|
+
|
|
47
56
|
|
|
48
57
|
If an actionable review has a non-empty `body` and **zero** line comments, GitHub has no `/replies` endpoint for the review body itself (the API has been inconsistent on this and the only reliable path is a top-level PR comment that references the review). Use the *top-level reference* form:
|
|
49
58
|
|
|
@@ -54,7 +63,7 @@ Re: review #<review_id> — addressed in <short-sha>: <one-line summary>.
|
|
|
54
63
|
🤖 _Automated reply from muggle-do._
|
|
55
64
|
```
|
|
56
65
|
|
|
57
|
-
Posted per [`../_shared/github
|
|
66
|
+
Posted per [`../_shared/vcs/github/top-level-comment.md`](../_shared/vcs/github/top-level-comment.md). Fires at most once per actionable review-with-no-line-comments. Does not fire if the review has line comments — Step 2 covers those.
|
|
58
67
|
|
|
59
68
|
## Failure modes
|
|
60
69
|
|
|
@@ -63,5 +72,5 @@ Posted per [`../_shared/github-cli-recipes/top-level-comment.md`](../_shared/git
|
|
|
63
72
|
|
|
64
73
|
## Invariants
|
|
65
74
|
|
|
66
|
-
- One reply per line comment. No per-review summary reply anywhere.
|
|
75
|
+
- One reply per line comment (`gitlab`: per discussion). No per-review summary reply anywhere.
|
|
67
76
|
- Every reply body contains the new SHA's 7-char prefix (which push addressed it) and ends with the loop signature block — the `<!-- muggle-do:bot -->` marker, not the author login, is what identifies loop-authored comments.
|
|
@@ -20,7 +20,7 @@ From `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR + branch + `head_
|
|
|
20
20
|
|
|
21
21
|
### Step 1 — Re-attach
|
|
22
22
|
|
|
23
|
-
Materialize the PR branch in its worktree per [`../_shared/pr-branch-worktree.md`](../_shared/pr-branch-worktree.md) (or use `state.md`'s `worktreePath`). Capture `rebase_sha = prs.json[0].head_sha` and the base branch (`baseRefName` from [`../_shared/github
|
|
23
|
+
Materialize the PR branch in its worktree per [`../_shared/pr-branch-worktree.md`](../_shared/pr-branch-worktree.md) (or use `state.md`'s `worktreePath`). Capture `rebase_sha = prs.json[0].head_sha` and the base branch (`baseRefName` from [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md)).
|
|
24
24
|
|
|
25
25
|
### Step 2 — Rebase onto base (resolve conflicts if any)
|
|
26
26
|
|
|
@@ -14,21 +14,23 @@ This stage does not print a turn preamble — it runs inside `/muggle-do`'s addr
|
|
|
14
14
|
|
|
15
15
|
## Inputs
|
|
16
16
|
|
|
17
|
-
- The current PR (URL, owner, repo, number) from the session's `prs.json`.
|
|
17
|
+
- The current PR (URL, owner, repo, number) from the session's `prs.json`. On `gitlab`, the project ref and MR iid.
|
|
18
18
|
- `last_seen.pushed_shas[]` from `last_seen.json` — the list of every SHA `/muggle-do` has pushed for this PR.
|
|
19
|
-
- The loop user's
|
|
19
|
+
- The loop user's login (cached in `state.md` under `Loop user:`) — re-resolve when missing, `github` per [`../_shared/vcs/github/loop-user-identity.md`](../_shared/vcs/github/loop-user-identity.md), `gitlab` per [`../_shared/vcs/gitlab/loop-user-identity.md`](../_shared/vcs/gitlab/loop-user-identity.md).
|
|
20
|
+
|
|
21
|
+
Resolve the provider once per [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md).
|
|
20
22
|
|
|
21
23
|
## Procedure
|
|
22
24
|
|
|
23
25
|
### Step 1 — Fetch unresolved comment threads
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
`github` per [`../_shared/vcs/github/unresolved-threads.md`](../_shared/vcs/github/unresolved-threads.md) (filter client-side to `isResolved == false`; each thread carries its line comments with `author.login`, `body`, `databaseId`); `gitlab` per [`../_shared/vcs/gitlab/unresolved-discussions.md`](../_shared/vcs/gitlab/unresolved-discussions.md) (each discussion carries its `notes[]` and `id`).
|
|
26
28
|
|
|
27
29
|
If the API call fails, log the error to `followup.log` and skip the stage. Do not surface a user-facing error — the resolve reminder is a nice-to-have, not load-bearing. The reply summaries on the threads themselves still happen.
|
|
28
30
|
|
|
29
31
|
### Step 2 — Classify each thread
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
Walk each thread's comments (`gitlab`: notes) in chronological order and classify by the loop marker `<!-- muggle-do:bot -->` ([`../_shared/pr-followup-helpers/loop-signature.md`](../_shared/pr-followup-helpers/loop-signature.md)), not by `author.login` — `github` per [`../_shared/vcs/github/unresolved-threads.md`](../_shared/vcs/github/unresolved-threads.md), `gitlab` per [`../_shared/vcs/gitlab/unresolved-discussions.md`](../_shared/vcs/gitlab/unresolved-discussions.md):
|
|
32
34
|
|
|
33
35
|
- **Addressed, awaiting resolve** — the **newest** comment carries the marker. The loop replied and nothing newer is waiting. These feed the reminder.
|
|
34
36
|
- **Unaddressed human comment** — the newest comment lacks the marker and post-dates the loop's last marked reply (or there is no loop reply yet). The address-reviews round handles these as work (Step 1 sweep), not the reminder.
|
|
@@ -42,7 +44,7 @@ Collect the thread `databaseId` of every thread classified **addressed, awaiting
|
|
|
42
44
|
|
|
43
45
|
### Step 4 — Post the top-level reminder comment
|
|
44
46
|
|
|
45
|
-
If the resolve-reminder list is non-empty, post **one** top-level
|
|
47
|
+
If the resolve-reminder list is non-empty, post **one** top-level comment using the template in [`../muggle-pr-followup/output-templates/resolve-reminder.md`](../muggle-pr-followup/output-templates/resolve-reminder.md) — `github` per [`../_shared/vcs/github/top-level-comment.md`](../_shared/vcs/github/top-level-comment.md), `gitlab` per [`../_shared/vcs/gitlab/mr-note.md`](../_shared/vcs/gitlab/mr-note.md). The comment carries the loop signature, so a later round's scan won't read it back as a human comment.
|
|
46
48
|
|
|
47
49
|
If the list is empty, post **nothing**. Still emit telemetry so the stage's run is observable.
|
|
48
50
|
|
|
@@ -59,7 +61,7 @@ Emit one event per [`../_shared/telemetry-events/muggle-do-resolve-reminder.md`]
|
|
|
59
61
|
|
|
60
62
|
This stage is best-effort. Any failure is logged to `followup.log` and silently skipped — the reviewer still gets the per-comment inline replies (the canonical signal that work was done), and the cycle continues to respawn the watcher.
|
|
61
63
|
|
|
62
|
-
The one exception: do not silently swallow a `gh pr comment`
|
|
64
|
+
The one exception: do not silently swallow a Step 4 post failure (`gh pr comment` / `glab mr note`) if Step 4 ran. The comment is a user-visible artifact; if it fails, surface the underlying CLI error to the user so they know the reminder didn't post.
|
|
63
65
|
|
|
64
66
|
## Invariants
|
|
65
67
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-browser-task
|
|
3
|
-
description:
|
|
3
|
+
description: "Perform a real action on a website or web app from a plain-English instruction — log in and do the thing: submit a form, create or update a record, place an order, refund a charge, file a ticket, publish a post, click through and complete a multi-step flow (Stripe, Jira, Shopify, the AWS console, WordPress, LinkedIn, an admin dashboard). Use whenever the user wants something actually done in a web UI ('log into X and …', 'submit the form', 'create the ticket', 'refund the charge', 'place the order', 'update the listing'); Muggle drives a real browser to do it, so reach for this rather than declining or doing it by hand. Boundary: this performs the action (operating a site's own UI), not migrating personal data between consumer apps; to verify a flow works instead, use muggle-test-feature-local."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test Task Runner
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-do
|
|
3
|
-
description:
|
|
3
|
+
description: Take a feature request, spec, design, bug, or ticket and carry it autonomously to an opened pull request — write the code, test it, raise the PR. Use whenever the user wants something built, implemented, added, or fixed with a PR opened, raised, or put up at the end — "implement rate limiting and raise a PR", "build the CSV export and put up a PR", "take this Jira ticket and run with it, ping me when the PR is up", "fix this bug and open a pr", or "muggle do …". Also handles the internal `address-reviews` directive the muggle-pr-followup watcher dispatches when new reviews land. Not for testing or validating existing changes (use muggle-test), nor watching a PR's incoming reviews (use muggle-pr-followup).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test Do
|
|
@@ -65,7 +65,7 @@ When invoked with the directive (PR URL + slug + review ids), routes to [`../do/
|
|
|
65
65
|
| `autoResolveConflicts` | On rebase conflict — resolve autonomously behind a verify-or-rollback gate (opt-in), or abort + escalate (default `never`) |
|
|
66
66
|
| `autoRouteBuildToMuggleDo` | Front-door guardrail — route build/implement/fix requests through this pipeline (build delegated to superpowers); fired by the UserPromptSubmit guardrail, default `ask` |
|
|
67
67
|
|
|
68
|
-
`autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
|
|
68
|
+
`autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup`, `postPRVisualWalkthrough` fire from per-stage files.
|
|
69
69
|
|
|
70
70
|
## Session model
|
|
71
71
|
|
|
@@ -20,15 +20,15 @@ A Muggle dashboard URL looks like `https://www.muggle-ai.com/muggleTestV0/dashbo
|
|
|
20
20
|
If this skill was invoked by another skill (`muggle-test`, `muggle-test-feature-local`) the caller MUST pass the just-finished `runId` as context. If you have a `runId`:
|
|
21
21
|
|
|
22
22
|
1. `muggle-local-run-result-get` with the `runId`.
|
|
23
|
-
2. The result includes the test case context.
|
|
24
|
-
3. **
|
|
23
|
+
2. The result includes the test case context. The studio publishes every local run during execution, so the run result carries the cloud `cloudActionScriptId` — use it directly as the `actionScriptId`.
|
|
24
|
+
3. **Legacy fallback** — if `cloudActionScriptId` is absent (a run from an older Electron build that didn't publish), upload it first via `muggle-remote-local-run-upload` (passing the `runId`'s test case context and `actionScript` payload). Use the returned cloud `actionScriptId`.
|
|
25
25
|
|
|
26
26
|
If no `runId` was passed but the user is plausibly continuing from a recent test:
|
|
27
27
|
|
|
28
28
|
1. `muggle-local-list-sessions` and pick sessions completed in the last 10 minutes for the current project.
|
|
29
29
|
2. If exactly one fresh session exists, offer it as the default via `AskUserQuestion` ("Feedback on the run from <X> minutes ago?" with **Yes / Pick a different run**).
|
|
30
30
|
3. If multiple, present the top 3 via `AskUserQuestion` (most recent first).
|
|
31
|
-
4. Once picked,
|
|
31
|
+
4. Once picked, resolve `cloudActionScriptId` from the run result (legacy upload fallback above).
|
|
32
32
|
|
|
33
33
|
If neither chained nor recent fits, fall through to 1c.
|
|
34
34
|
|
|
@@ -127,4 +127,4 @@ If any pieces failed, list them under a `Failed:` header with the error.
|
|
|
127
127
|
- Always render the script (step 2) before collecting feedback.
|
|
128
128
|
- One create call per feedback piece — never concatenate paragraphs across targets.
|
|
129
129
|
- Convert step numbers from 1-based (UI) to 0-based (wire) at submit time.
|
|
130
|
-
- If
|
|
130
|
+
- If a legacy local run carries no `cloudActionScriptId`, do the upload silently before submit; do not ask for permission for the upload itself.
|
|
@@ -6,7 +6,7 @@ This folder holds the watcher loop that drives one PR toward merge-ready. The wa
|
|
|
6
6
|
|
|
7
7
|
- [`SKILL.md`](SKILL.md) — public entry. Routing between bootstrap (URL input), tick (slug + PR number), and auto-track (no args). Read first.
|
|
8
8
|
- [`auto-track.md`](auto-track.md) — the no-args procedure: discovers PRs pushed this session (any repo) and seeds one poll-only watcher each. Seeds no E2E context — the watcher only watches.
|
|
9
|
-
- [`bootstrap.md`](bootstrap.md) — the bootstrap procedure (
|
|
9
|
+
- [`bootstrap.md`](bootstrap.md) — the bootstrap procedure (resolves the validation context once when the PR has a testable surface — else seeds poll-only like auto-track — then dispatches the first watcher).
|
|
10
10
|
- [`contract.md`](contract.md) — the watcher per-tick procedure (poll → dispatch → exit).
|
|
11
11
|
- [`finalize.md`](finalize.md) — shared termination sequence for a terminal PR (mark terminal, `result.md`, log/telemetry, unschedule cron, post-merge cleanup handoff). Called by `contract.md` and `reconcile.md`.
|
|
12
12
|
- [`reconcile.md`](reconcile.md) — sweep that finalizes slots whose PR went terminal while polling lapsed; runs at the top of auto-track and on demand.
|
|
@@ -21,6 +21,6 @@ Shared with other skills, under `../_shared/`:
|
|
|
21
21
|
- [`pr-followup-helpers.md`](../_shared/pr-followup-helpers.md) — TOC of allow-list / reply-routing / classify; per-section files in `_shared/pr-followup-helpers/`. Called by `/muggle-do`, not by this folder.
|
|
22
22
|
- [`telemetry-emit.md`](../_shared/telemetry-emit.md) — how to emit a telemetry event.
|
|
23
23
|
- [`telemetry-events.md`](../_shared/telemetry-events.md) — TOC of canonical event shapes; per-event files in `_shared/telemetry-events/`.
|
|
24
|
-
- [`github
|
|
24
|
+
- [`vcs/github.md`](../_shared/vcs/github.md) — TOC of reusable `gh` / `git` snippets; per-recipe files in `_shared/vcs/github/`.
|
|
25
25
|
|
|
26
26
|
Callers (e.g. `/muggle-do`) reference this folder, not the reverse — see [`../CLAUDE.md`](../CLAUDE.md) for the one-way-dependency rule.
|