@muggleai/works 4.12.4 → 4.13.1
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/{chunk-JNI7INIO.js → chunk-5G7WI7IY.js} +2 -2
- package/dist/{chunk-CPF6AR2I.js → chunk-YKR2TQ24.js} +53 -37
- 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/skills/_shared/github-cli-recipes/submitted-reviews.md +1 -1
- package/dist/plugin/skills/_shared/github-cli-recipes/unresolved-threads.md +6 -4
- package/dist/plugin/skills/_shared/pr-followup-helpers/allow-list.md +1 -1
- package/dist/plugin/skills/_shared/pr-followup-helpers/classify.md +3 -4
- package/dist/plugin/skills/_shared/pr-followup-helpers/loop-signature.md +22 -0
- package/dist/plugin/skills/_shared/pr-followup-helpers.md +1 -0
- package/dist/plugin/skills/_shared/resolve-e2e-validation-context.md +56 -0
- package/dist/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +1 -1
- package/dist/plugin/skills/_shared/test-case-chain-readiness.md +41 -0
- package/dist/plugin/skills/do/address-reviews.md +14 -8
- package/dist/plugin/skills/do/e2e-acceptance.md +7 -3
- package/dist/plugin/skills/do/per-comment-replies.md +8 -2
- package/dist/plugin/skills/do/resolve-reminder.md +16 -18
- package/dist/plugin/skills/muggle-pr-followup/CLAUDE.md +5 -3
- package/dist/plugin/skills/muggle-pr-followup/SKILL.md +10 -3
- package/dist/plugin/skills/muggle-pr-followup/auto-track.md +91 -0
- package/dist/plugin/skills/muggle-pr-followup/bootstrap.md +11 -4
- package/dist/plugin/skills/muggle-pr-followup/output-templates/help.md +2 -1
- package/dist/plugin/skills/muggle-pr-followup/output-templates/inline-reply.md +7 -1
- package/dist/plugin/skills/muggle-pr-followup/output-templates/resolve-reminder.md +6 -3
- package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +12 -0
- package/dist/plugin/skills/muggle-preferences/ops/configure.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoReuseValidationContext.md +11 -0
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +7 -0
- package/dist/release-manifest.json +4 -4
- package/dist/{src-YR5UKLPC.js → src-ECRJW2LY.js} +1 -1
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/skills/_shared/github-cli-recipes/submitted-reviews.md +1 -1
- package/plugin/skills/_shared/github-cli-recipes/unresolved-threads.md +6 -4
- package/plugin/skills/_shared/pr-followup-helpers/allow-list.md +1 -1
- package/plugin/skills/_shared/pr-followup-helpers/classify.md +3 -4
- package/plugin/skills/_shared/pr-followup-helpers/loop-signature.md +22 -0
- package/plugin/skills/_shared/pr-followup-helpers.md +1 -0
- package/plugin/skills/_shared/resolve-e2e-validation-context.md +56 -0
- package/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +1 -1
- package/plugin/skills/_shared/test-case-chain-readiness.md +41 -0
- package/plugin/skills/do/address-reviews.md +14 -8
- package/plugin/skills/do/e2e-acceptance.md +7 -3
- package/plugin/skills/do/per-comment-replies.md +8 -2
- package/plugin/skills/do/resolve-reminder.md +16 -18
- package/plugin/skills/muggle-pr-followup/CLAUDE.md +5 -3
- package/plugin/skills/muggle-pr-followup/SKILL.md +10 -3
- package/plugin/skills/muggle-pr-followup/auto-track.md +91 -0
- package/plugin/skills/muggle-pr-followup/bootstrap.md +11 -4
- package/plugin/skills/muggle-pr-followup/output-templates/help.md +2 -1
- package/plugin/skills/muggle-pr-followup/output-templates/inline-reply.md +7 -1
- package/plugin/skills/muggle-pr-followup/output-templates/resolve-reminder.md +6 -3
- package/plugin/skills/muggle-pr-followup/state-schemas.md +12 -0
- package/plugin/skills/muggle-preferences/ops/configure.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/autoReuseValidationContext.md +11 -0
- package/plugin/skills/muggle-test-feature-local/SKILL.md +7 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Resolving the E2E Validation Context
|
|
2
|
+
|
|
3
|
+
**How-to procedure.** Followed by any seeder that prepares a session for unattended Stage 6 (E2E acceptance) runs.
|
|
4
|
+
|
|
5
|
+
**Goal:** resolve — once, while the user is present — everything Stage 6 needs to run without further prompts (validation strategy, local URL, backend status, Muggle Test project, test credentials, auth), and persist it to `state.md` so every later non-interactive run reads it instead of asking.
|
|
6
|
+
|
|
7
|
+
The sections below are the steps in order: reuse an existing context if one is on disk, else detect what's resolvable silently, ask the rest in one question, and write the result. The final [`## Persisted fields`](#persisted-fields) section doubles as the schema the cycle reads back.
|
|
8
|
+
|
|
9
|
+
## Reuse an existing context
|
|
10
|
+
|
|
11
|
+
If a `## Pre-flight answers` block already exists for this working tree — the current session slot, or the most recent sibling session under `.muggle-do/sessions/*` — fire the [`autoReuseValidationContext`](../muggle-preferences/preference-gates/autoReuseValidationContext.md) gate before gathering anything:
|
|
12
|
+
|
|
13
|
+
- `always` → copy the existing block into this session; skip the questionnaire.
|
|
14
|
+
- `never` → ignore it; run the full gather below.
|
|
15
|
+
- `ask` → prompt reuse-vs-re-gather.
|
|
16
|
+
|
|
17
|
+
Run the gather only when no block exists or the user chose to re-gather.
|
|
18
|
+
|
|
19
|
+
## Silent detection
|
|
20
|
+
|
|
21
|
+
Resolve without prompting; use as questionnaire defaults:
|
|
22
|
+
|
|
23
|
+
1. Dev server + backend health — per [`dev-server-readiness.md`](dev-server-readiness.md).
|
|
24
|
+
2. Muggle Test MCP auth — `muggle-remote-auth-status`.
|
|
25
|
+
3. Candidate projects — `muggle-remote-project-list`, ranked against the repo's dev URL and the PR title.
|
|
26
|
+
4. Existing test-user secrets — `muggle-remote-secret-list` per candidate project (`managed_profile_email` / `managed_profile_password`).
|
|
27
|
+
5. Auth0 tenant for local dev — grep the repo env file for `*AUTH0_DOMAIN*`.
|
|
28
|
+
|
|
29
|
+
## Questions
|
|
30
|
+
|
|
31
|
+
One `AskUserQuestion` for the validation subset, detected values as defaults. Canonical wording lives in [`../do/pre-flight.md`](../do/pre-flight.md) — reference, don't fork:
|
|
32
|
+
|
|
33
|
+
- Validation strategy — pre-flight Q4
|
|
34
|
+
- Local URL — pre-flight Q5 (defers to [`autoSelectLocalHost`](../muggle-preferences/preference-gates/autoSelectLocalHost.md))
|
|
35
|
+
- Backend reachable — pre-flight Q6
|
|
36
|
+
- Muggle Test project — pre-flight Q7 (defers to [`autoSelectProject`](../muggle-preferences/preference-gates/autoSelectProject.md))
|
|
37
|
+
- Test-user credentials — pre-flight Q8
|
|
38
|
+
- Re-auth Muggle Test MCP — pre-flight Q10
|
|
39
|
+
|
|
40
|
+
The chosen **validation strategy is the standing decision for every cycle** — no per-tick re-prompt. It subsumes the [`autoE2ETest`](../muggle-preferences/preference-gates/autoE2ETest.md) gate (pre-flight Q13), meaningless in a loop: `local-e2e` runs Stage 6 each cycle; `unit-only` / `skip` stands down. The gate's `always` default makes `local-e2e` the default when a dev server is detected.
|
|
41
|
+
|
|
42
|
+
Skip the forward-only questions (task scope, repo, branch, PR target, worktree, rebase) — the targeted repo and head branch are already checked out.
|
|
43
|
+
|
|
44
|
+
## Persisted fields
|
|
45
|
+
|
|
46
|
+
Write to `state.md` under a `## Pre-flight answers` block:
|
|
47
|
+
|
|
48
|
+
- `Validation: <local-e2e | staging-replay | unit-only | skip>`
|
|
49
|
+
- `Local URL: <url | N/A>`
|
|
50
|
+
- `Backend status: <up | down | N/A>`
|
|
51
|
+
- `Muggle Test project: <name> (<uuid>)`
|
|
52
|
+
- `Test credentials: <existing | new | skip>`
|
|
53
|
+
- `Auth status: <ok | re-authed | N/A>`
|
|
54
|
+
- `Working tree: <path>` — the verified checkout the cycle runs against
|
|
55
|
+
|
|
56
|
+
Missing any required field is a seeding bug: escalate with the session path and halt. Never silently skip E2E.
|
|
@@ -23,4 +23,4 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
23
23
|
- `"escalated"` — all reviews were ambiguous; no push.
|
|
24
24
|
- `"mixed"` — both branches happened in the same invocation.
|
|
25
25
|
- `"no-op"` — every input id was already in the escalated set; no work.
|
|
26
|
-
- `"self-loop-skip"` — review was a synthetic wrapper around the agent's own reply (
|
|
26
|
+
- `"self-loop-skip"` — review was a synthetic wrapper around the agent's own reply (every line comment is a reply carrying the loop marker `<!-- muggle-do:bot -->`). Cursor advanced silently; no work, no escalation.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Test Case Chain Readiness
|
|
2
|
+
|
|
3
|
+
A test case may depend on prerequisite ("parent") test cases in the project's **test-plan graph** — e.g. "edit item" depends on "create item". Before generating or replaying the chosen test case, every ancestor in that chain must already have a ready script, or the run starts from missing state and fails for the wrong reason.
|
|
4
|
+
|
|
5
|
+
This is the **graph the backend owns** — do not infer the chain from titles or `precondition` text. Read it from `muggle-remote-test-case-ancestors-get`.
|
|
6
|
+
|
|
7
|
+
**Ready** = `muggle-remote-test-script-list` (with the ancestor's `testCaseId`) returns at least one replayable/succeeded script — the same bar Step 5 uses to offer replay.
|
|
8
|
+
|
|
9
|
+
## Procedure
|
|
10
|
+
|
|
11
|
+
Run once the target `testCaseId` is chosen and the local URL + services are confirmed (the generation calls below need `localUrl` and `cwd`).
|
|
12
|
+
|
|
13
|
+
1. **Resolve the chain.** `muggle-remote-test-case-ancestors-get` with the target `testCaseId`. Response: `{ testCaseId, ancestors, orphan }`.
|
|
14
|
+
- `orphan: true` **or** empty `ancestors` → no prerequisites. Skip the rest; continue to Step 5.
|
|
15
|
+
- Otherwise `ancestors` is ordered **immediate-parent → root**. Reverse it to **root-first** so prerequisites are satisfied bottom-up.
|
|
16
|
+
|
|
17
|
+
2. **For each ancestor, root-first:**
|
|
18
|
+
- Check readiness via `muggle-remote-test-script-list` (`projectId`, `testCaseId` = ancestor). Ready → skip to the next ancestor.
|
|
19
|
+
- Not ready → **generate its script only (never replay):**
|
|
20
|
+
1. `muggle-remote-test-case-get` for the ancestor.
|
|
21
|
+
2. Determine `freshSession` for that ancestor from its own content — same rules as Step 6.
|
|
22
|
+
3. `muggle-local-execute-test-generation` with the ancestor test case, `localUrl`, `cwd`, and a long `timeoutMs` (see Step 6's timeout guidance). Do **not** call `muggle-local-execute-replay`.
|
|
23
|
+
4. `muggle-local-publish-test-script` (`runId`, `cloudTestCaseId` = ancestor) so the generated script is promoted as that ancestor's canonical replay script — it now reads as ready for any case downstream.
|
|
24
|
+
|
|
25
|
+
3. **All ancestors ready** → continue to Step 5 for the target test case.
|
|
26
|
+
|
|
27
|
+
## When an ancestor's generation fails
|
|
28
|
+
|
|
29
|
+
If an ancestor's generation does not reach `passed` (read it via `muggle-local-run-result-get`, never the execute stdout tail), the target's prerequisite state is missing. **Halt the chain** and surface which ancestor failed and why, then ask via `AskUserQuestion`:
|
|
30
|
+
|
|
31
|
+
- **Stop** — don't run the target; the chain is broken.
|
|
32
|
+
- **Proceed anyway** — run the target without the prerequisite (likely to fail; only if the user judges the state already exists).
|
|
33
|
+
- **Give feedback** — invoke the `muggle-feedback` skill with the failed ancestor's `runId`.
|
|
34
|
+
|
|
35
|
+
Do not silently skip a failed ancestor and run the target.
|
|
36
|
+
|
|
37
|
+
## Notes
|
|
38
|
+
|
|
39
|
+
- The target test case is **not** in its own `ancestors` list — only its prerequisites are.
|
|
40
|
+
- Each ancestor is a single path to the root (one parent per node), so the reversed list has no duplicates; generate each at most once per session.
|
|
41
|
+
- This walks the **full** chain to root, not just the immediate parent — a grandparent without a ready script is generated before its child.
|
|
@@ -27,14 +27,18 @@ Read from `.muggle-do/sessions/<slug>/`:
|
|
|
27
27
|
|
|
28
28
|
## Procedure
|
|
29
29
|
|
|
30
|
-
### Step 1 —
|
|
30
|
+
### Step 1 — Assemble the work set
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Two sources, combined into one batch (dedupe by comment id):
|
|
33
|
+
|
|
34
|
+
**(a) The dispatched reviews.** For each review id in the input:
|
|
33
35
|
|
|
34
36
|
- Fetch reviews per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md) (cursor 0; filter to the specific id).
|
|
35
37
|
- Fetch its line comments per [`../_shared/github-cli-recipes/line-comments-for-review.md`](../_shared/github-cli-recipes/line-comments-for-review.md).
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
**(b) Unaddressed comments on every unresolved thread.** Fetch unresolved threads per [`../_shared/github-cli-recipes/unresolved-threads.md`](../_shared/github-cli-recipes/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, even if its review predates the cursor. 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.
|
|
40
|
+
|
|
41
|
+
Group (a) and (b) into one combined batch.
|
|
38
42
|
|
|
39
43
|
### Step 2 — Classify each review
|
|
40
44
|
|
|
@@ -57,7 +61,7 @@ The user clarifies on GitHub by submitting a new review. The next watcher tick p
|
|
|
57
61
|
|
|
58
62
|
### Step 4 — Handle actionables (if any)
|
|
59
63
|
|
|
60
|
-
If `actionable_review_ids` is empty, skip
|
|
64
|
+
If `actionable_review_ids` is empty, skip the rest of Step 4 and Step 5; proceed to Step 5.5 (resolve-reminder) then Step 6. Otherwise:
|
|
61
65
|
|
|
62
66
|
#### 4a. Flatten the work
|
|
63
67
|
|
|
@@ -75,7 +79,7 @@ Invoke [`unit-tests.md`](unit-tests.md). Cover the surface that just changed; re
|
|
|
75
79
|
|
|
76
80
|
#### 4d. Run ONE E2E acceptance pass
|
|
77
81
|
|
|
78
|
-
Invoke [`e2e-acceptance.md`](e2e-acceptance.md). One pass covering all related test cases for this PR, not one
|
|
82
|
+
Invoke [`e2e-acceptance.md`](e2e-acceptance.md). One pass covering all related test cases for this PR, not one per comment. The stage reads the persisted validation context (seeded by pre-flight or by bootstrap Step 6.5); a poll-only session with no context (e.g. auto-track) is reported `SKIPPED`. The persisted `Validation` strategy is the standing decision — no per-tick `autoE2ETest` prompt. See [`e2e-acceptance.md`](e2e-acceptance.md) Step 0 and [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md).
|
|
79
83
|
|
|
80
84
|
#### 4e. Create or update the PR
|
|
81
85
|
|
|
@@ -85,9 +89,7 @@ Invoke [`open-prs/update.md`](open-prs/update.md) (pass the PR URL + slug + exis
|
|
|
85
89
|
|
|
86
90
|
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.
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Invoke [`resolve-reminder.md`](resolve-reminder.md). Scans unresolved threads, classifies, and posts a top-level PR comment listing addressed-by-loop thread ids.
|
|
92
|
+
(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.)
|
|
91
93
|
|
|
92
94
|
### Step 5 — Update session state
|
|
93
95
|
|
|
@@ -95,6 +97,10 @@ Invoke [`resolve-reminder.md`](resolve-reminder.md). Scans unresolved threads, c
|
|
|
95
97
|
- `last_seen.last_pushed_sha` = the new head SHA (update.md already wrote this; verify)
|
|
96
98
|
- `last_seen.reviewId` = max(input review ids ∪ last_seen.reviewId)
|
|
97
99
|
|
|
100
|
+
### Step 5.5 — Resolve-reminder (runs every round)
|
|
101
|
+
|
|
102
|
+
Invoke [`resolve-reminder.md`](resolve-reminder.md) once, regardless of whether this round pushed. It scans unresolved threads, finds those whose newest comment is loop-marked (addressed, awaiting resolve), and posts one top-level PR comment nudging the reviewer to resolve them — or stays silent if there are none. Threads with a newer human comment were already pulled into this round's work set in Step 1(b).
|
|
103
|
+
|
|
98
104
|
### Step 6 — Respawn the watcher
|
|
99
105
|
|
|
100
106
|
Refresh PR state per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). If the PR is now merged or closed:
|
|
@@ -44,11 +44,15 @@ You receive everything from `state.md` already — pre-flight resolved it:
|
|
|
44
44
|
|
|
45
45
|
## Your Job
|
|
46
46
|
|
|
47
|
-
### Step 0: Consume
|
|
47
|
+
### Step 0: Consume the validation context (no user questions)
|
|
48
48
|
|
|
49
|
-
Read `state.md`.
|
|
49
|
+
Read `state.md`.
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
**No `## Pre-flight answers` block at all** → the session was seeded poll-only (e.g. by auto-track, [`../muggle-pr-followup/auto-track.md`](../muggle-pr-followup/auto-track.md)). Treat `Validation` as `skip`: emit a `SKIPPED` report with reason `no validation context seeded` and exit cleanly. The watcher owns no E2E context by design; "no context" is a clean skip, not a failure.
|
|
52
|
+
|
|
53
|
+
Otherwise the block was seeded by pre-flight or bootstrap per [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md) — read it the same way regardless of seeder. The persisted `Validation` field (`local-e2e`, `staging-replay`, `unit-only`, `skip`) picks execution vs early-exit below. In a forward run, [`autoE2ETest`](../muggle-preferences/preference-gates/autoE2ETest.md) `ask` was resolved by pre-flight Q13; in a watcher cycle there is no per-tick pre-flight, so `Validation` **is** the standing decision — don't re-resolve `ask`.
|
|
54
|
+
|
|
55
|
+
For a `local-e2e` block, use `localUrl`, `projectId`, and the working-tree path from `state.md`. Missing any → seeding bug; escalate with the session path and halt; do not ask the user.
|
|
52
56
|
|
|
53
57
|
### Step 0.5: Pre-flight verification probes
|
|
54
58
|
|
|
@@ -36,9 +36,12 @@ Reply body uses the template in [`../muggle-pr-followup/output-templates/inline-
|
|
|
36
36
|
|
|
37
37
|
```
|
|
38
38
|
Addressed in <short-sha>: <one-line summary of the change made for THIS comment>.
|
|
39
|
+
|
|
40
|
+
<!-- muggle-do:bot -->
|
|
41
|
+
🤖 _Automated reply from muggle-do._
|
|
39
42
|
```
|
|
40
43
|
|
|
41
|
-
`<short-sha>` is the first 7 chars of `new_sha
|
|
44
|
+
`<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)).
|
|
42
45
|
|
|
43
46
|
### Step 3 — Handle review-body-only comments
|
|
44
47
|
|
|
@@ -46,6 +49,9 @@ If an actionable review has a non-empty `body` and **zero** line comments, GitHu
|
|
|
46
49
|
|
|
47
50
|
```
|
|
48
51
|
Re: review #<review_id> — addressed in <short-sha>: <one-line summary>.
|
|
52
|
+
|
|
53
|
+
<!-- muggle-do:bot -->
|
|
54
|
+
🤖 _Automated reply from muggle-do._
|
|
49
55
|
```
|
|
50
56
|
|
|
51
57
|
Posted per [`../_shared/github-cli-recipes/top-level-comment.md`](../_shared/github-cli-recipes/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,4 +64,4 @@ Posted per [`../_shared/github-cli-recipes/top-level-comment.md`](../_shared/git
|
|
|
58
64
|
## Invariants
|
|
59
65
|
|
|
60
66
|
- One reply per line comment. No per-review summary reply anywhere.
|
|
61
|
-
- Every reply body contains the new SHA's 7-char prefix — the
|
|
67
|
+
- 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.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Resolve-Reminder Stage
|
|
2
2
|
|
|
3
|
-
A `/muggle-do` stage that runs in **address-reviews mode only**,
|
|
3
|
+
A `/muggle-do` stage that runs in **address-reviews mode only**, near the end of each review round. Scans every unresolved comment thread on the PR, classifies them by the loop signature, and posts ONE top-level PR comment listing the threads the loop has addressed that are still unresolved with no newer human reply.
|
|
4
4
|
|
|
5
|
-
Runs
|
|
5
|
+
Runs once per `/muggle-do` address-reviews invocation (one review round):
|
|
6
6
|
|
|
7
|
-
- Runs
|
|
8
|
-
-
|
|
7
|
+
- Runs every round, whether or not this round pushed — it nudges **all** still-unresolved loop-addressed threads, not only ones touched by this push.
|
|
8
|
+
- Posts a comment only when at least one such thread exists; otherwise silent.
|
|
9
9
|
- Does not run in the forward pipeline (a fresh PR has no review threads to remind about).
|
|
10
10
|
|
|
11
11
|
## Turn preamble (inline within `/muggle-do` cycle)
|
|
@@ -28,33 +28,31 @@ If the API call fails, log the error to `followup.log` and skip the stage. Do no
|
|
|
28
28
|
|
|
29
29
|
### Step 2 — Classify each thread
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Per [`../_shared/github-cli-recipes/unresolved-threads.md`](../_shared/github-cli-recipes/unresolved-threads.md): walk each thread's comments in `createdAt` 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`:
|
|
32
32
|
|
|
33
|
-
- **Addressed
|
|
34
|
-
- **
|
|
35
|
-
- **Not addressed** —
|
|
33
|
+
- **Addressed, awaiting resolve** — the **newest** comment carries the marker. The loop replied and nothing newer is waiting. These feed the reminder.
|
|
34
|
+
- **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.
|
|
35
|
+
- **Not addressed** — indeterminate.
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Consider only the threads' own comments. Do not cross-reference timeline events from outside the threads.
|
|
38
38
|
|
|
39
39
|
### Step 3 — Build the resolve-reminder list
|
|
40
40
|
|
|
41
|
-
Collect the thread `databaseId` of every thread classified
|
|
42
|
-
|
|
43
|
-
Note: the watcher does not maintain a "addressed-this-cycle" set; this stage derives it by comparing thread comments to the most-recent appended SHA. The simplest deterministic rule: include a thread iff at least one of its bot replies cites the **most recent** `pushed_shas[-1]`. Earlier SHAs were already addressed in past reminders.
|
|
41
|
+
Collect the thread `databaseId` of every thread classified **addressed, awaiting resolve** in Step 2 — every still-unresolved thread whose newest comment is loop-marked, regardless of which push addressed it. A thread stays on the list across rounds until the reviewer resolves it or replies; a human reply moves it to **unaddressed human comment** (into the round's work set, Step 1), so it drops off the reminder automatically.
|
|
44
42
|
|
|
45
43
|
### Step 4 — Post the top-level reminder comment
|
|
46
44
|
|
|
47
|
-
If the resolve-reminder list is non-empty, post **one** top-level PR comment using the template in [`../muggle-pr-followup/output-templates/resolve-reminder.md`](../muggle-pr-followup/output-templates/resolve-reminder.md) per [`../_shared/github-cli-recipes/top-level-comment.md`](../_shared/github-cli-recipes/top-level-comment.md).
|
|
45
|
+
If the resolve-reminder list is non-empty, post **one** top-level PR comment using the template in [`../muggle-pr-followup/output-templates/resolve-reminder.md`](../muggle-pr-followup/output-templates/resolve-reminder.md) per [`../_shared/github-cli-recipes/top-level-comment.md`](../_shared/github-cli-recipes/top-level-comment.md). The comment carries the loop signature, so a later round's scan won't read it back as a human comment.
|
|
48
46
|
|
|
49
|
-
If the list is empty
|
|
47
|
+
If the list is empty, post **nothing**. Still emit telemetry so the stage's run is observable.
|
|
50
48
|
|
|
51
49
|
### Step 5 — Emit telemetry
|
|
52
50
|
|
|
53
51
|
Emit one event per [`../_shared/telemetry-events/muggle-do-resolve-reminder.md`](../_shared/telemetry-events/muggle-do-resolve-reminder.md). Include:
|
|
54
52
|
|
|
55
|
-
- `addressed_by_loop` — count of threads
|
|
56
|
-
- `addressed_by_human` — count
|
|
57
|
-
- `not_addressed` — count from Step 2's
|
|
53
|
+
- `addressed_by_loop` — count of threads on the reminder list (Step 3; newest comment loop-marked).
|
|
54
|
+
- `addressed_by_human` — count of threads with an unaddressed human comment (newest comment unmarked; handled by the round's Step 1 sweep, not the reminder).
|
|
55
|
+
- `not_addressed` — count from Step 2's indeterminate category.
|
|
58
56
|
- `comment_posted` — true iff Step 4 actually posted a comment.
|
|
59
57
|
|
|
60
58
|
## Failure modes
|
|
@@ -66,5 +64,5 @@ The one exception: do not silently swallow a `gh pr comment` failure if Step 4 r
|
|
|
66
64
|
## Invariants
|
|
67
65
|
|
|
68
66
|
- Telemetry fires once per invocation, even when no comment is posted.
|
|
69
|
-
- The reminder
|
|
67
|
+
- The reminder covers **every** still-unresolved thread whose newest comment is loop-marked — not just the most recent push. A thread leaves the reminder only when the reviewer resolves it or replies (a reply routes it to the round's work set).
|
|
70
68
|
- This stage suggests; it does not resolve threads on the reviewer's behalf.
|
|
@@ -4,8 +4,9 @@ This folder holds the watcher loop for PR review follow-ups. The watcher is a **
|
|
|
4
4
|
|
|
5
5
|
## Files in this folder
|
|
6
6
|
|
|
7
|
-
- [`SKILL.md`](SKILL.md) — public entry.
|
|
8
|
-
- [`
|
|
7
|
+
- [`SKILL.md`](SKILL.md) — public entry. Routing between bootstrap (URL input), tick (slug + PR number), and auto-track (no args). Read first.
|
|
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 (asks once for the E2E validation context, seeds state, dispatches the first watcher).
|
|
9
10
|
- [`contract.md`](contract.md) — the watcher per-tick procedure (poll → dispatch → exit).
|
|
10
11
|
- [`state-schemas.md`](state-schemas.md) — canonical JSON shapes of session state files.
|
|
11
12
|
- [`output-templates.md`](output-templates.md) — TOC of message templates; per-group files in `output-templates/`.
|
|
@@ -14,6 +15,7 @@ This folder holds the watcher loop for PR review follow-ups. The watcher is a **
|
|
|
14
15
|
|
|
15
16
|
Shared with other skills, under `../_shared/`:
|
|
16
17
|
|
|
18
|
+
- [`resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md) — the E2E validation-context contract bootstrap seeds into `state.md` (Step 6.5) and `do/e2e-acceptance.md` consumes.
|
|
17
19
|
- [`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.
|
|
18
20
|
- [`telemetry-emit.md`](../_shared/telemetry-emit.md) — how to emit a telemetry event.
|
|
19
21
|
- [`telemetry-events.md`](../_shared/telemetry-events.md) — TOC of canonical event shapes; per-event files in `_shared/telemetry-events/`.
|
|
@@ -22,4 +24,4 @@ Shared with other skills, under `../_shared/`:
|
|
|
22
24
|
Caller-specific, under `../do/`:
|
|
23
25
|
|
|
24
26
|
- [`open-prs.md`](../do/open-prs.md) — TOC for the create-or-update PR stage; per-mode files in `do/open-prs/`.
|
|
25
|
-
- [`resolve-reminder.md`](../do/resolve-reminder.md) — `/muggle-do`'s
|
|
27
|
+
- [`resolve-reminder.md`](../do/resolve-reminder.md) — `/muggle-do`'s per-round stage that nudges the reviewer to resolve addressed-but-still-open threads.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-pr-followup
|
|
3
|
-
description: Watcher loop for PR review follow-ups. Polls one PR for new submitted reviews and dispatches `/muggle-do` (address-reviews mode) when there are any. A dumb pipe — no classification, no cycle execution, no replies. Use `/loop 1m /muggle:muggle-pr-followup <slug> <pr-number>` for ongoing polling, or `/muggle:muggle-pr-followup <pr-url>` to bootstrap a fresh watcher on an existing PR.
|
|
3
|
+
description: Watcher loop for PR review follow-ups. Polls one PR for new submitted reviews and dispatches `/muggle-do` (address-reviews mode) when there are any. A dumb pipe — no classification, no cycle execution, no replies. Run it with no args to auto-track every PR you pushed this session (poll-only watchers, any repo). Use `/loop 1m /muggle:muggle-pr-followup <slug> <pr-number>` for ongoing polling, or `/muggle:muggle-pr-followup <pr-url>` to bootstrap a fresh watcher on an existing PR (asks once for the E2E validation context, then runs unattended).
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ A watcher that babysits one open PR's review thread. Polls for new submitted rev
|
|
|
16
16
|
|
|
17
17
|
## Routing
|
|
18
18
|
|
|
19
|
-
The skill recognizes
|
|
19
|
+
The skill recognizes its mode by inspecting `$ARGUMENTS` and falling back to on-disk state. It never runs procedure inline — it identifies the mode and routes to the appropriate procedure file.
|
|
20
20
|
|
|
21
21
|
| Input | On-disk check | Mode |
|
|
22
22
|
| :---- | :------------ | :--- |
|
|
@@ -25,7 +25,8 @@ The skill recognizes two modes by inspecting `$ARGUMENTS` and falling back to on
|
|
|
25
25
|
| `<slug> <pr-number>` | session dir missing | **error:** "no session at `<path>`; pass a PR URL to start one" |
|
|
26
26
|
| `<pr-number>` alone | exactly one existing session contains it | **tick** for that PR |
|
|
27
27
|
| `<pr-number>` alone | zero or multiple matches | **error:** ambiguous; list candidates and exit |
|
|
28
|
-
| empty
|
|
28
|
+
| empty | — | **auto-track** → [`auto-track.md`](auto-track.md) |
|
|
29
|
+
| `help` / `?` | — | **help:** list active loops per [`output-templates/help.md`](output-templates/help.md) |
|
|
29
30
|
|
|
30
31
|
Bootstrap accepts three optional trailing flags:
|
|
31
32
|
|
|
@@ -33,6 +34,12 @@ Bootstrap accepts three optional trailing flags:
|
|
|
33
34
|
- `--resume` — opt in to reusing an existing session slot (default is refuse on conflict)
|
|
34
35
|
- `--forward-only` — pin cursor past existing reviews (skip history). Default is cursor 0, which processes prior submitted reviews on the first tick.
|
|
35
36
|
|
|
37
|
+
## Preferences
|
|
38
|
+
|
|
39
|
+
| Preference | Gate |
|
|
40
|
+
| :--------- | :--- |
|
|
41
|
+
| `autoReuseValidationContext` | Bootstrap reuses an existing validation context instead of re-asking — fired in the Step 6.5 gather per [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md) |
|
|
42
|
+
|
|
36
43
|
## Folder TOC
|
|
37
44
|
|
|
38
45
|
See [`CLAUDE.md`](CLAUDE.md) for the one-line index of every file in this folder.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Auto-Track Procedure
|
|
2
|
+
|
|
3
|
+
The procedure for the **auto-track mode** of `muggle-pr-followup` — invoked when the skill is dispatched with **no arguments**. Routing is in [`SKILL.md`](SKILL.md#routing).
|
|
4
|
+
|
|
5
|
+
Auto-track discovers the PRs you pushed or opened during this Claude Code session — across **any repo** — and starts one **poll-only watcher** per PR. The watcher only watches: it seeds nothing about E2E. Running and posting E2E is `/muggle-do`'s job; a watcher with no validation context yields a `SKIPPED` E2E verdict when `/muggle-do` runs — see [`../do/e2e-acceptance.md`](../do/e2e-acceptance.md) Step 0.
|
|
6
|
+
|
|
7
|
+
## Turn preamble
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
**muggle-pr-followup auto-track** — tracking PRs from this session.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Input
|
|
14
|
+
|
|
15
|
+
`$ARGUMENTS` is empty.
|
|
16
|
+
|
|
17
|
+
## Procedure
|
|
18
|
+
|
|
19
|
+
### Step 1 — Discover candidate PRs from session context
|
|
20
|
+
|
|
21
|
+
A PR counts as **pushed this session** if, earlier in this conversation, you:
|
|
22
|
+
|
|
23
|
+
- opened it (`gh pr create`), or
|
|
24
|
+
- pushed commits to a branch that has an open PR, or
|
|
25
|
+
- acted on it as the active PR (its URL appeared and you worked it).
|
|
26
|
+
|
|
27
|
+
Collect each candidate's canonical URL (`https://github.com/<owner>/<repo>/pull/<n>`); candidates may span repos.
|
|
28
|
+
|
|
29
|
+
### Step 2 — Decide confident vs. uncertain
|
|
30
|
+
|
|
31
|
+
- **Confident** — context clearly identifies one or more PRs pushed this session. Use that set; go to Step 4. **Do not prompt.**
|
|
32
|
+
- **Uncertain** — nothing clearly attributable, or several candidates are plausible. Go to Step 3.
|
|
33
|
+
|
|
34
|
+
### Step 3 — Picker (uncertain only)
|
|
35
|
+
|
|
36
|
+
Build a candidate list from the Step 1 URLs, plus — if the current working directory is a git repo — `gh pr list --author @me --state open --json number,title,url,headRefName` for that repo. Present an `AskUserQuestion` **multi-select** picker of the candidates (PR number + title + repo).
|
|
37
|
+
|
|
38
|
+
- Empty selection → exit with a one-line note (`No PRs selected; nothing to track.`). Write nothing.
|
|
39
|
+
- One or more selected → use them as the track list and go to Step 4.
|
|
40
|
+
|
|
41
|
+
### Step 4 — Seed one poll-only watcher per PR
|
|
42
|
+
|
|
43
|
+
For each PR URL in the track list, run the [`bootstrap.md`](bootstrap.md) procedure with these auto-track overrides:
|
|
44
|
+
|
|
45
|
+
- **Skip Step 3 (verify working tree).** The PR's checkout need not be the current tree. If you know which directory it was pushed from, record `Working tree: <path>` in `state.md`; else omit it — `/muggle-do` resolves the tree when it runs.
|
|
46
|
+
- **Skip Step 6.5 (E2E validation context).** The watcher owns no E2E concern; do **not** write a `## Pre-flight answers` block.
|
|
47
|
+
- **Existing slot → skip silently** (never the slot-conflict abort); add it to the *skipped* list.
|
|
48
|
+
- **`caller = "auto-track"`** in the bootstrap telemetry event.
|
|
49
|
+
|
|
50
|
+
Everything else is unchanged: URL parse, metadata + terminal-PR abort, slug, cursor 0 (process prior reviews on the first tick), and the `prs.json`/`last_seen.json`/`state.md` writes minus the pre-flight block.
|
|
51
|
+
|
|
52
|
+
### Step 5 — Print the summary
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
muggle-pr-followup auto-track
|
|
56
|
+
|
|
57
|
+
Tracked (new):
|
|
58
|
+
<slug> → <owner>/<repo>#<n>
|
|
59
|
+
...
|
|
60
|
+
(or "none")
|
|
61
|
+
Already tracking (skipped):
|
|
62
|
+
<slug> → <owner>/<repo>#<n>
|
|
63
|
+
...
|
|
64
|
+
(or "none")
|
|
65
|
+
|
|
66
|
+
Dispatching:
|
|
67
|
+
/loop 1m /muggle:muggle-pr-followup <slug> <n>
|
|
68
|
+
...
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Print the summary **before** the `/loop` dispatches so it stays visible.
|
|
72
|
+
|
|
73
|
+
### Step 6 — Dispatch the watchers
|
|
74
|
+
|
|
75
|
+
As the last action of the turn, emit one `/loop` line per **newly tracked** PR (not the skipped ones):
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
/loop 1m /muggle:muggle-pr-followup <slug> <n>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Each registers an independent cron — the N-independent-watchers model from [`SKILL.md`](SKILL.md).
|
|
82
|
+
|
|
83
|
+
### Step 7 — Emit telemetry
|
|
84
|
+
|
|
85
|
+
One bootstrap event per **newly tracked** PR per [`../_shared/telemetry-events/pr-followup-bootstrap.md`](../_shared/telemetry-events/pr-followup-bootstrap.md), with `caller = "auto-track"`. Fire-and-forget per [`../_shared/telemetry-emit.md`](../_shared/telemetry-emit.md). Skipped PRs emit nothing.
|
|
86
|
+
|
|
87
|
+
## Invariants
|
|
88
|
+
|
|
89
|
+
- **Tracking depends only on the PR.** No E2E context is gathered, prompted for, or required.
|
|
90
|
+
- **Idempotent.** Existing slots are skipped; re-running never double-tracks.
|
|
91
|
+
- **No-op is silent.** Empty discovery followed by an empty picker writes nothing and dispatches nothing.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The procedure for the **bootstrap mode** of `muggle-pr-followup` — invoked when a user dispatches the skill with a GitHub PR URL. Routing into this mode is documented in [`SKILL.md`](SKILL.md#routing).
|
|
4
4
|
|
|
5
|
-
Bootstrap
|
|
5
|
+
Bootstrap asks **one** questionnaire — the E2E validation context the loop will reuse — then runs through to the first watcher dispatch. The user is present at launch, so this is the only place to gather it; every later tick reads it from `state.md`. Without it, a URL-bootstrapped watcher has no `localUrl`/`projectId` and Stage 6 hard-halts instead of running E2E.
|
|
6
6
|
|
|
7
7
|
## Turn preamble
|
|
8
8
|
|
|
@@ -44,13 +44,19 @@ Default: `<repo>-pr<n>` (e.g. `muggle-ai-works-pr154`). Override: `--slug=<name>
|
|
|
44
44
|
If `.muggle-do/sessions/<slug>/` exists:
|
|
45
45
|
|
|
46
46
|
- Without `--resume` → exit with the slot-conflict abort. Both remedies (delete + re-run, or pass `--resume`) are spelled out in the message.
|
|
47
|
-
- With `--resume` → refresh `prs.json[0].head_sha` to the current `headRefOid` from Step 2
|
|
47
|
+
- With `--resume` → refresh `prs.json[0].head_sha` to the current `headRefOid` from Step 2; leave `last_seen.json` and the cursor untouched. If `state.md` already has a `## Pre-flight answers` block, skip to Step 8; if not (older session), run Step 6.5 to backfill it, then skip to Step 8.
|
|
48
48
|
|
|
49
49
|
### Step 6 — Resolve the initial cursor
|
|
50
50
|
|
|
51
51
|
- **Default (no `--forward-only`):** cursor is `0`. The watcher will pick up every existing submitted review on its first tick. This matches the common case where the user opened the PR, left review comments they want addressed, and is now running bootstrap.
|
|
52
52
|
- **With `--forward-only`:** fetch reviews per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md), then take `max(id)`. The watcher only acts on later submissions. Use when bootstrapping a PR with stale/already-handled prior reviews you don't want re-processed.
|
|
53
53
|
|
|
54
|
+
### Step 6.5 — Resolve E2E validation context
|
|
55
|
+
|
|
56
|
+
The only step that may prompt the user. Run the gather in [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md): reuse an existing context if one is found (gated by `autoReuseValidationContext`), else silent detection + one `AskUserQuestion` (strategy, local URL, backend, project, credentials, re-auth). Record Step 3's verified working tree as `Working tree`.
|
|
57
|
+
|
|
58
|
+
Capture the fields for Step 7. Do **not** run E2E now — the first watcher tick that dispatches `/muggle-do` does that.
|
|
59
|
+
|
|
54
60
|
### Step 7 — Seed state files
|
|
55
61
|
|
|
56
62
|
Identify the loop user once per [`../_shared/github-cli-recipes/loop-user-identity.md`](../_shared/github-cli-recipes/loop-user-identity.md); cache in `state.md`.
|
|
@@ -61,7 +67,7 @@ Write under `.muggle-do/sessions/<slug>/`:
|
|
|
61
67
|
|
|
62
68
|
**`last_seen.json`** — see [`state-schemas.md`](state-schemas.md#last_seenjson). One key (`"<owner>/<repo>#<n>"`), `reviewId` from Step 6, `last_pushed_sha: null`, `idle_tick_count: 0`, `cycles_completed: 0`, `escalated_review_ids: []`, `pushed_shas: []`.
|
|
63
69
|
|
|
64
|
-
**`state.md`** — see [`state-schemas.md`](state-schemas.md#statemd). `Bootstrapped from URL: yes`. Cache the loop-user login.
|
|
70
|
+
**`state.md`** — see [`state-schemas.md`](state-schemas.md#statemd). `Bootstrapped from URL: yes`. Cache the loop-user login. Append the `## Pre-flight answers` block with the fields resolved in Step 6.5, per [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md#persisted-fields).
|
|
65
71
|
|
|
66
72
|
Do **not** write `cycle.json` or `requirements.md` — those files are no longer part of the session slot.
|
|
67
73
|
|
|
@@ -85,6 +91,7 @@ Emit one event per [`../_shared/telemetry-events/pr-followup-bootstrap.md`](../_
|
|
|
85
91
|
|
|
86
92
|
## Invariants
|
|
87
93
|
|
|
88
|
-
-
|
|
94
|
+
- Step 6.5 is the **only** user prompt. If the user cancels it, abort leaving nothing on disk.
|
|
95
|
+
- All state writes happen in Step 7 — earlier aborts (including a cancelled Step 6.5) leave nothing on disk.
|
|
89
96
|
- If Step 7 fails mid-write, surface the OS error and tell the user to `rm -rf <slot>` and re-run; do not dispatch the watcher.
|
|
90
97
|
- Bootstrap never retries.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Help output
|
|
2
2
|
|
|
3
|
-
For `/muggle:muggle-pr-followup`
|
|
3
|
+
For `/muggle:muggle-pr-followup help` or `?` (no args runs **auto-track** instead — see [`../auto-track.md`](../auto-track.md)):
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
muggle-pr-followup — watcher loop for PR review follow-ups
|
|
@@ -11,6 +11,7 @@ Active loops:
|
|
|
11
11
|
(or "no active loops")
|
|
12
12
|
|
|
13
13
|
Usage:
|
|
14
|
+
/muggle:muggle-pr-followup → auto-track every PR you pushed this session
|
|
14
15
|
/muggle:muggle-pr-followup <pr-url> → bootstrap a new loop
|
|
15
16
|
/muggle:muggle-pr-followup <slug> <pr-number> → run one tick (called by /loop)
|
|
16
17
|
/muggle:muggle-pr-followup <pr-number> → run one tick (slug inferred from on-disk state)
|
|
@@ -4,9 +4,12 @@ Posted via `gh api .../comments/<comment-id>/replies` per cycle, one per line co
|
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
Addressed in <short-sha>: <one-line summary of the change made for THIS comment>.
|
|
7
|
+
|
|
8
|
+
<!-- muggle-do:bot -->
|
|
9
|
+
🤖 _Automated reply from muggle-do._
|
|
7
10
|
```
|
|
8
11
|
|
|
9
|
-
`<short-sha>` is the first 7 chars of the new SHA
|
|
12
|
+
`<short-sha>` is the first 7 chars of the new SHA; the body must contain that substring so the resolve-reminder stage knows *which push* addressed the thread. The trailing signature block — defined in [`../../_shared/pr-followup-helpers/loop-signature.md`](../../_shared/pr-followup-helpers/loop-signature.md) — is mandatory; its `<!-- muggle-do:bot -->` marker is what identifies the comment as loop-authored.
|
|
10
13
|
|
|
11
14
|
## Top-level fallback (review-body-only)
|
|
12
15
|
|
|
@@ -14,4 +17,7 @@ When an actionable review has a non-empty body but zero line comments, GitHub ha
|
|
|
14
17
|
|
|
15
18
|
```
|
|
16
19
|
Re: review #<review_id> — addressed in <short-sha>: <one-line summary>.
|
|
20
|
+
|
|
21
|
+
<!-- muggle-do:bot -->
|
|
22
|
+
🤖 _Automated reply from muggle-do._
|
|
17
23
|
```
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Resolve-reminder top-level PR comment
|
|
2
2
|
|
|
3
|
-
Posted via `gh pr comment`
|
|
3
|
+
Posted via `gh pr comment` once per review round, when at least one unresolved thread is addressed-by-loop with no newer human reply.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
|
-
|
|
6
|
+
These threads are addressed and still open — mark them resolved if satisfied, or reply if more is needed:
|
|
7
7
|
- #<thread-id-1>
|
|
8
8
|
- #<thread-id-2>
|
|
9
9
|
- ...
|
|
10
|
+
|
|
11
|
+
<!-- muggle-do:bot -->
|
|
12
|
+
🤖 _Automated reply from muggle-do._
|
|
10
13
|
```
|
|
11
14
|
|
|
12
|
-
If
|
|
15
|
+
If no such thread exists, no comment is posted (silent). The trailing signature block ([`loop-signature.md`](../../_shared/pr-followup-helpers/loop-signature.md)) keeps the loop from later mistaking its own reminder for a human comment.
|
|
@@ -60,9 +60,21 @@ Free-form markdown. No required schema beyond a few well-known fields the caller
|
|
|
60
60
|
**Created:** <ISO-8601>
|
|
61
61
|
**Bootstrapped from URL:** <yes | no>
|
|
62
62
|
|
|
63
|
+
## Pre-flight answers
|
|
64
|
+
|
|
65
|
+
- Validation: <local-e2e | staging-replay | unit-only | skip>
|
|
66
|
+
- Local URL: <url | N/A>
|
|
67
|
+
- Backend status: <up | down | N/A>
|
|
68
|
+
- Muggle Test project: <name> (<uuid>)
|
|
69
|
+
- Test credentials: <existing | new | skip>
|
|
70
|
+
- Auth status: <ok | re-authed | N/A>
|
|
71
|
+
- Working tree: <path>
|
|
72
|
+
|
|
63
73
|
...free-form notes added by /muggle-do and bootstrap...
|
|
64
74
|
```
|
|
65
75
|
|
|
76
|
+
The `## Pre-flight answers` block is the **E2E validation context** consumed by `do/e2e-acceptance.md` Step 0 — seeded by bootstrap (Step 6.5) or by pre-flight's output block. Fields: [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md#persisted-fields).
|
|
77
|
+
|
|
66
78
|
The watcher does **not** read or write `state.md`. Only bootstrap, `/muggle-do`, and the caller's stages touch it.
|
|
67
79
|
|
|
68
80
|
## `followup.log`
|
|
@@ -26,7 +26,7 @@ you can tell me which (if any) should instead be set to `never`.
|
|
|
26
26
|
For each option: label = key name, description = first paragraph of `preference-gates/<key>.md`. Multi-select question text = `Which of these should auto-proceed (set to "always")?`; selected = `always`.
|
|
27
27
|
|
|
28
28
|
- `multiSelect: true`, `header: "Auth & session"` — `autoLogin`, `autoSelectProject`, `checkForUpdates`, `verboseOutput`
|
|
29
|
-
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`
|
|
29
|
+
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`
|
|
30
30
|
- `multiSelect: true`, `header: "Test run"` — `showElectronBrowser`, `openTestResultsAfterRun`, `autoPublishLocalResults`
|
|
31
31
|
- `multiSelect: true`, `header: "Suggestions & PR"` — `suggestRelatedUseCases`, `suggestRelatedTestCases`, `postPRVisualWalkthrough`, `autoCreatePR`
|
|
32
32
|
- `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# `autoReuseValidationContext`
|
|
2
|
+
|
|
3
|
+
Reuse an existing E2E validation context (a prior session's `## Pre-flight answers` block for this working tree) instead of asking the validation questions again. Substitute `{contextSource}` (the slug + age of the block being offered). Fires only when such a block exists; with none, the calling skill runs the full gather and never reaches this gate.
|
|
4
|
+
|
|
5
|
+
**Picker 1** — header `Validation context`, question `"Reuse the validation context from {contextSource}?"`
|
|
6
|
+
- `Reuse it` — `Same local URL, project, strategy, and credentials as {contextSource}.` → copy the block into this session
|
|
7
|
+
- `Re-gather` — `Ask the validation questions fresh.` → run the full gather
|
|
8
|
+
|
|
9
|
+
**Silent action**
|
|
10
|
+
- `always` → `Reusing validation context from {contextSource}`
|
|
11
|
+
- `never` → no footer; the gather is the visible step.
|