@muggleai/works 5.11.0 → 5.12.0-staging.73
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/config/runtime-targets.json +33 -0
- package/dist/{chunk-MSPMXBO5.js → chunk-FCDHJD6I.js} +441 -347
- package/dist/{chunk-WUMAJOBT.js → chunk-O7LFABOC.js} +39 -35
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/plugin/hooks/README.md +4 -1
- package/dist/plugin/hooks/hooks.json +24 -0
- package/dist/plugin/scripts/guardrail-capability-claim.sh +38 -0
- package/dist/plugin/scripts/guardrail-comment-reply-gate.sh +42 -0
- package/dist/plugin/scripts/guardrail-debug-path-gate.sh +1 -1
- package/dist/plugin/scripts/guardrail-e2e-gate.sh +1 -1
- package/dist/plugin/scripts/guardrail-record-comment-replies.sh +28 -0
- package/dist/plugin/scripts/guardrail-resolve-gate.sh +22 -0
- package/dist/plugin/scripts/guardrail-stage-gate.sh +1 -1
- package/dist/plugin/scripts/guardrail-terminal-gate.sh +1 -1
- package/dist/plugin/scripts/guardrail-walkthrough-gate.sh +1 -1
- package/dist/plugin/scripts/guardrail-watch-gate.sh +1 -1
- package/dist/plugin/scripts/guardrails.mjs +506 -32
- package/dist/plugin/scripts/pr-watch-loop.sh +9 -24
- package/dist/plugin/scripts/pr-watch-state.jq +52 -0
- package/dist/plugin/skills/_shared/identity-and-inbox.md +39 -0
- package/dist/plugin/skills/_shared/sync-branch-with-base.md +29 -0
- package/dist/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +3 -2
- package/dist/plugin/skills/_shared/vcs/github/unresolved-threads.md +2 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/unresolved-discussions.md +3 -1
- package/dist/plugin/skills/_shared/vcs/gitlab.md +0 -1
- package/dist/plugin/skills/do/address-reviews.md +5 -2
- package/dist/plugin/skills/do/build.md +9 -0
- package/dist/plugin/skills/do/e2e-acceptance.md +2 -0
- package/dist/plugin/skills/do/e2e-repair.md +98 -0
- package/dist/plugin/skills/do/open-prs/forward.md +17 -9
- package/dist/plugin/skills/do/open-prs/update.md +9 -2
- package/dist/plugin/skills/do/per-comment-replies.md +13 -1
- package/dist/plugin/skills/do/pre-flight.md +2 -2
- package/dist/plugin/skills/do/resolve-conflicts.md +59 -59
- package/dist/plugin/skills/muggle-browser-task/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-do/SKILL.md +6 -5
- package/dist/plugin/skills/muggle-pr-followup/arm-watcher.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoRebase.md +5 -5
- package/dist/plugin/skills/muggle-status/SKILL.md +15 -6
- package/dist/plugin/skills/muggle-test/SKILL.md +1 -0
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +5 -3
- package/dist/plugin/skills/muggle-test-prepare/steps/rebase-check.md +1 -1
- package/dist/release-manifest.json +3 -3
- package/dist/src-TFNPZD5X.js +1 -0
- package/package.json +17 -8
- package/plugin/hooks/README.md +4 -1
- package/plugin/hooks/hooks.json +24 -0
- package/plugin/scripts/guardrail-capability-claim.sh +38 -0
- package/plugin/scripts/guardrail-comment-reply-gate.sh +42 -0
- package/plugin/scripts/guardrail-debug-path-gate.sh +1 -1
- package/plugin/scripts/guardrail-e2e-gate.sh +1 -1
- package/plugin/scripts/guardrail-record-comment-replies.sh +28 -0
- package/plugin/scripts/guardrail-resolve-gate.sh +22 -0
- package/plugin/scripts/guardrail-stage-gate.sh +1 -1
- package/plugin/scripts/guardrail-terminal-gate.sh +1 -1
- package/plugin/scripts/guardrail-walkthrough-gate.sh +1 -1
- package/plugin/scripts/guardrail-watch-gate.sh +1 -1
- package/plugin/scripts/guardrails.mjs +506 -32
- package/plugin/scripts/pr-watch-loop.sh +9 -24
- package/plugin/scripts/pr-watch-state.jq +52 -0
- package/plugin/skills/_shared/identity-and-inbox.md +39 -0
- package/plugin/skills/_shared/sync-branch-with-base.md +29 -0
- package/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +3 -2
- package/plugin/skills/_shared/vcs/github/unresolved-threads.md +2 -0
- package/plugin/skills/_shared/vcs/gitlab/unresolved-discussions.md +3 -1
- package/plugin/skills/_shared/vcs/gitlab.md +0 -1
- package/plugin/skills/do/address-reviews.md +5 -2
- package/plugin/skills/do/build.md +9 -0
- package/plugin/skills/do/e2e-acceptance.md +2 -0
- package/plugin/skills/do/e2e-repair.md +98 -0
- package/plugin/skills/do/open-prs/forward.md +17 -9
- package/plugin/skills/do/open-prs/update.md +9 -2
- package/plugin/skills/do/per-comment-replies.md +13 -1
- package/plugin/skills/do/pre-flight.md +2 -2
- package/plugin/skills/do/resolve-conflicts.md +59 -59
- package/plugin/skills/muggle-browser-task/SKILL.md +1 -1
- package/plugin/skills/muggle-do/SKILL.md +6 -5
- package/plugin/skills/muggle-pr-followup/arm-watcher.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/autoRebase.md +5 -5
- package/plugin/skills/muggle-status/SKILL.md +15 -6
- package/plugin/skills/muggle-test/SKILL.md +1 -0
- package/plugin/skills/muggle-test-feature-local/SKILL.md +5 -3
- package/plugin/skills/muggle-test-prepare/steps/rebase-check.md +1 -1
- package/scripts/postinstall.mjs +59 -2
- package/dist/plugin/skills/_shared/rebase-before-e2e.md +0 -21
- package/dist/plugin/skills/_shared/vcs/gitlab/resolve-discussion.md +0 -10
- package/dist/src-B5OTAZKM.js +0 -1
- package/plugin/skills/_shared/rebase-before-e2e.md +0 -21
- package/plugin/skills/_shared/vcs/gitlab/resolve-discussion.md +0 -10
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
# Rebase (watcher-dispatched)
|
|
2
|
-
|
|
3
|
-
Rebase a PR's branch onto its base — whether it's merely **behind** (out of date, no conflict) or actually **conflicting** — behind a verify-or-rollback gate, then force-push, so a PR doesn't sit stale or un-mergeable forever. A dumb-pipe dispatch like fix-ci: the watcher detects the branch is behind or conflicting and hands off; the executor owns the rebase (and any conflict resolution), never the decision to dispatch.
|
|
4
|
-
|
|
5
|
-
## Turn preamble
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
**/muggle-do rebase** — rebasing <owner>/<repo>#<n> onto <base> to bring the branch up to date.
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Input
|
|
12
|
-
|
|
13
|
-
`$ARGUMENTS` carries a `github.com/.../pull/<n>` URL, `slug=<slug>`, and a `rebase` directive (no review ids, no failing check names). Parse all three.
|
|
14
|
-
|
|
15
|
-
## Inputs from disk
|
|
16
|
-
|
|
17
|
-
From `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR + branch + `head_sha`), `last_seen.json` (`conflict_resolve_attempts`, `conflict_escalated_keys`, `pushed_shas`), `state.md` (worktree path, validation strategy, base branch).
|
|
18
|
-
|
|
19
|
-
## Procedure
|
|
20
|
-
|
|
21
|
-
### Step 1 — Re-attach
|
|
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/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md)). Capture the base tip too — `.base_commit.sha` from that recipe's `compare` call — and form `rebase_key = "<rebase_sha>..<base_tip_sha>"`. Both budget fields below are keyed on that pair, matching the watcher's Step 5; writing a bare SHA instead leaves an entry the watcher ignores, and the rebase re-dispatches forever.
|
|
24
|
-
|
|
25
|
-
### Step 2 — Rebase onto base (resolve conflicts if any)
|
|
26
|
-
|
|
27
|
-
Run the rebase from [`../_shared/
|
|
28
|
-
|
|
29
|
-
- **Clean replay** — a behind-only branch (and any rebase that hits no conflicts) replays without intervention. Proceed to Step 3.
|
|
30
|
-
- **Conflicts** — handle per [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md):
|
|
31
|
-
- `never` → abort and escalate per Step 5 (`kind: "rebase-conflict"`). The watcher keeps polling; the user resolves on GitHub.
|
|
32
|
-
- `always` → resolve via [`../_shared/resolve-rebase-conflicts.md`](../_shared/resolve-rebase-conflicts.md); Steps 3 and 5 below are this mode's instance of the [`../_shared/verify-or-rollback-gate.md`](../_shared/verify-or-rollback-gate.md).
|
|
33
|
-
|
|
34
|
-
### Step 3 — Verify the resolution
|
|
35
|
-
|
|
36
|
-
Build (typecheck + lint on the changed surface) + unit suite must pass. Run E2E per [`e2e-acceptance.md`](e2e-acceptance.md) when app logic changed and the session carries validation context. A rebase that does not verify is rolled back → escalate per Step 5. **Never push an unverified rebase.**
|
|
37
|
-
|
|
38
|
-
### Step 4 — Force-push + respawn
|
|
39
|
-
|
|
40
|
-
Force-push per [`../_shared/vcs/common/push-to-branch.md`](../_shared/vcs/common/push-to-branch.md) (tool-agnostic instruction; handles the signing gate for rebased commits and directs to provider-specific force-push paths). Use `git push --force-with-lease` for the force operation. Append the new SHA to `last_seen.pushed_shas`; increment `last_seen.conflict_resolve_attempts[rebase_key]` — both whole-file rewrites (Read → change field → Write) per [`../_shared/session-state-writes.md`](../_shared/session-state-writes.md), never the Edit tool. Respawn the watcher per [`respawn-watcher.md`](respawn-watcher.md). Its next tick re-checks the branch against its base on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
|
|
41
|
-
|
|
42
|
-
### Step 5 — Escalate (can't resolve / budget spent)
|
|
43
|
-
|
|
44
|
-
When `autoResolveConflicts=never`, the resolution failed verification, or `conflict_resolve_attempts[rebase_key]` has reached 2:
|
|
45
|
-
|
|
46
|
-
1. Add `rebase_key` to `last_seen.conflict_escalated_keys` so the watcher does not re-dispatch this head against this base. If the base later moves, the key changes and the branch re-arms on its own — a conflict the user resolved upstream stops being this watcher's dead end.
|
|
47
|
-
2. Emit one terminal escalation naming the PR and the conflicting files (or the failing verification, for a behind-only rebase that didn't verify).
|
|
48
|
-
3. Respawn the watcher per [`respawn-watcher.md`](respawn-watcher.md) — it keeps polling for the user's manual resolution or any new reviews.
|
|
49
|
-
|
|
50
|
-
### Step 6 — Telemetry
|
|
51
|
-
|
|
52
|
-
Emit one `muggle-do:cycle` event ([`../_shared/telemetry-events/muggle-do-cycle.md`](../_shared/telemetry-events/muggle-do-cycle.md)) with `outcome: "rebased"` (a verified rebase pushed — behind-only or conflicts resolved) or `"rebase-escalated"`.
|
|
53
|
-
|
|
54
|
-
## Guardrails
|
|
55
|
-
|
|
56
|
-
- Max 2 rebase attempts per SHA; then escalate rather than churn.
|
|
57
|
-
- Never push an unverified rebase — verify-or-rollback always.
|
|
58
|
-
- Never push unsigned commits — every push or force-push goes through the signing gate in [`../_shared/vcs/common/push-to-branch.md`](../_shared/vcs/common/push-to-branch.md).
|
|
59
|
-
- Resolve `autoResolveConflicts` from the configured preference (per the gate contract — don't assume a default): `always` resolves conflicts behind the verify-or-rollback gate, `never` escalates to the user. A clean behind-only rebase needs neither.
|
|
1
|
+
# Rebase (watcher-dispatched)
|
|
2
|
+
|
|
3
|
+
Rebase a PR's branch onto its base — whether it's merely **behind** (out of date, no conflict) or actually **conflicting** — behind a verify-or-rollback gate, then force-push, so a PR doesn't sit stale or un-mergeable forever. A dumb-pipe dispatch like fix-ci: the watcher detects the branch is behind or conflicting and hands off; the executor owns the rebase (and any conflict resolution), never the decision to dispatch.
|
|
4
|
+
|
|
5
|
+
## Turn preamble
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
**/muggle-do rebase** — rebasing <owner>/<repo>#<n> onto <base> to bring the branch up to date.
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Input
|
|
12
|
+
|
|
13
|
+
`$ARGUMENTS` carries a `github.com/.../pull/<n>` URL, `slug=<slug>`, and a `rebase` directive (no review ids, no failing check names). Parse all three.
|
|
14
|
+
|
|
15
|
+
## Inputs from disk
|
|
16
|
+
|
|
17
|
+
From `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR + branch + `head_sha`), `last_seen.json` (`conflict_resolve_attempts`, `conflict_escalated_keys`, `pushed_shas`), `state.md` (worktree path, validation strategy, base branch).
|
|
18
|
+
|
|
19
|
+
## Procedure
|
|
20
|
+
|
|
21
|
+
### Step 1 — Re-attach
|
|
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/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md)). Capture the base tip too — `.base_commit.sha` from that recipe's `compare` call — and form `rebase_key = "<rebase_sha>..<base_tip_sha>"`. Both budget fields below are keyed on that pair, matching the watcher's Step 5; writing a bare SHA instead leaves an entry the watcher ignores, and the rebase re-dispatches forever.
|
|
24
|
+
|
|
25
|
+
### Step 2 — Rebase onto base (resolve conflicts if any)
|
|
26
|
+
|
|
27
|
+
Run the rebase from [`../_shared/sync-branch-with-base.md`](../_shared/sync-branch-with-base.md) against the base branch, taking its `always` path unconditionally — this programmatic mode never asks, so skip the `autoRebase` prompt (the watcher already decided a rebase is due).
|
|
28
|
+
|
|
29
|
+
- **Clean replay** — a behind-only branch (and any rebase that hits no conflicts) replays without intervention. Proceed to Step 3.
|
|
30
|
+
- **Conflicts** — handle per [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md):
|
|
31
|
+
- `never` → abort and escalate per Step 5 (`kind: "rebase-conflict"`). The watcher keeps polling; the user resolves on GitHub.
|
|
32
|
+
- `always` → resolve via [`../_shared/resolve-rebase-conflicts.md`](../_shared/resolve-rebase-conflicts.md); Steps 3 and 5 below are this mode's instance of the [`../_shared/verify-or-rollback-gate.md`](../_shared/verify-or-rollback-gate.md).
|
|
33
|
+
|
|
34
|
+
### Step 3 — Verify the resolution
|
|
35
|
+
|
|
36
|
+
Build (typecheck + lint on the changed surface) + unit suite must pass. Run E2E per [`e2e-acceptance.md`](e2e-acceptance.md) when app logic changed and the session carries validation context. A rebase that does not verify is rolled back → escalate per Step 5. **Never push an unverified rebase.**
|
|
37
|
+
|
|
38
|
+
### Step 4 — Force-push + respawn
|
|
39
|
+
|
|
40
|
+
Force-push per [`../_shared/vcs/common/push-to-branch.md`](../_shared/vcs/common/push-to-branch.md) (tool-agnostic instruction; handles the signing gate for rebased commits and directs to provider-specific force-push paths). Use `git push --force-with-lease` for the force operation. Append the new SHA to `last_seen.pushed_shas`; increment `last_seen.conflict_resolve_attempts[rebase_key]` — both whole-file rewrites (Read → change field → Write) per [`../_shared/session-state-writes.md`](../_shared/session-state-writes.md), never the Edit tool. Respawn the watcher per [`respawn-watcher.md`](respawn-watcher.md). Its next tick re-checks the branch against its base on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
|
|
41
|
+
|
|
42
|
+
### Step 5 — Escalate (can't resolve / budget spent)
|
|
43
|
+
|
|
44
|
+
When `autoResolveConflicts=never`, the resolution failed verification, or `conflict_resolve_attempts[rebase_key]` has reached 2:
|
|
45
|
+
|
|
46
|
+
1. Add `rebase_key` to `last_seen.conflict_escalated_keys` so the watcher does not re-dispatch this head against this base. If the base later moves, the key changes and the branch re-arms on its own — a conflict the user resolved upstream stops being this watcher's dead end.
|
|
47
|
+
2. Emit one terminal escalation naming the PR and the conflicting files (or the failing verification, for a behind-only rebase that didn't verify).
|
|
48
|
+
3. Respawn the watcher per [`respawn-watcher.md`](respawn-watcher.md) — it keeps polling for the user's manual resolution or any new reviews.
|
|
49
|
+
|
|
50
|
+
### Step 6 — Telemetry
|
|
51
|
+
|
|
52
|
+
Emit one `muggle-do:cycle` event ([`../_shared/telemetry-events/muggle-do-cycle.md`](../_shared/telemetry-events/muggle-do-cycle.md)) with `outcome: "rebased"` (a verified rebase pushed — behind-only or conflicts resolved) or `"rebase-escalated"`.
|
|
53
|
+
|
|
54
|
+
## Guardrails
|
|
55
|
+
|
|
56
|
+
- Max 2 rebase attempts per SHA; then escalate rather than churn.
|
|
57
|
+
- Never push an unverified rebase — verify-or-rollback always.
|
|
58
|
+
- Never push unsigned commits — every push or force-push goes through the signing gate in [`../_shared/vcs/common/push-to-branch.md`](../_shared/vcs/common/push-to-branch.md).
|
|
59
|
+
- Resolve `autoResolveConflicts` from the configured preference (per the gate contract — don't assume a default): `always` resolves conflicts behind the verify-or-rollback gate, `never` escalates to the user. A clean behind-only rebase needs neither.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-browser-task
|
|
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, send a message, place an order, refund a charge, file a ticket, publish a post, complete a multi-step flow. Muggle drives a real browser through the site's own UI and supplies the session — managed login profiles
|
|
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, send a message, place an order, refund a charge, file a ticket, publish a post, complete a multi-step flow. Muggle drives a real browser through the site's own UI and supplies the session — managed login profiles, stored credentials, and a live inbox per profile that reads magic links, emailed OTPs, and email 2FA — so a named service (Slack, Jira, Stripe, WordPress, a marketplace, a booking site, an admin panel) is a signal to reach for this skill, not to hunt for its API or connector; \"no logged-in session\" and \"the code goes to an email\" are not reasons to decline. Use whenever the user wants something done in a web UI ('log into X and …', 'send the message', 'create the ticket'), rather than declining or doing it by hand; ask for missing specifics inside the flow, not instead of starting it. 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
|
|
@@ -20,9 +20,10 @@ Runs an autonomous dev cycle from requirements to PR. **Fire and review:** user
|
|
|
20
20
|
| 5 | Unit tests | [`../do/unit-tests.md`](../do/unit-tests.md) |
|
|
21
21
|
| 6 | E2E acceptance | [`../do/e2e-acceptance.md`](../do/e2e-acceptance.md) |
|
|
22
22
|
| 7 | Create or update PR | [`../do/open-prs.md`](../do/open-prs.md) |
|
|
23
|
+
| 7.5 | E2E repair loop | [`../do/e2e-repair.md`](../do/e2e-repair.md) |
|
|
23
24
|
| 8 | Hand off to watcher | [`../muggle-pr-followup/SKILL.md`](../muggle-pr-followup/SKILL.md) |
|
|
24
25
|
|
|
25
|
-
Stage 7 dispatches one watcher per opened PR as its last action.
|
|
26
|
+
Stage 7 dispatches one watcher per opened PR as its last action, gated on Stage 7.5's clearance — a cycle with unrepaired E2E failures never reaches a watcher.
|
|
26
27
|
|
|
27
28
|
## Execution protocol (non-negotiable)
|
|
28
29
|
|
|
@@ -31,12 +32,12 @@ The pipeline table lists **pointers, not summaries**. Open each stage's file and
|
|
|
31
32
|
**Bootstrap before any code, in order:**
|
|
32
33
|
1. Emit telemetry — [`../_shared/telemetry-emit.md`](../_shared/telemetry-emit.md), `skillName: "muggle-do"`.
|
|
33
34
|
2. Create `~/.muggle-ai/muggle-do/sessions/<slug>/` with `state.md` + `iterations/001.md` (pre-flight owns this; do it even when running unattended).
|
|
34
|
-
3. `TodoWrite` one item per stage 1–8 — these stages are the checklist; never swap in your own decomposition.
|
|
35
|
+
3. `TodoWrite` one item per stage 1–8, Stage 7.5 included — these stages are the checklist; never swap in your own decomposition.
|
|
35
36
|
|
|
36
37
|
**Per stage:** read the file → execute it → append a marker to `iterations/<NNN>.md` citing the evidence that file requires (jest exit code, E2E verdict + `runId`, screenshot path). A stage is done only when its evidence is written, never on recollection.
|
|
37
38
|
|
|
38
39
|
### "Autonomous" / "without my intervention" collapses exactly one thing
|
|
39
|
-
Best-effort the Stage-1 questionnaire and don't ask. It does **not** license skipping telemetry, session artifacts, requirements, unit tests, E2E (`autoE2ETest` defaults to `always`), browser verification, the gate below, or the watcher hand-off. Run the whole pipeline silently — never a shortcut.
|
|
40
|
+
Best-effort the Stage-1 questionnaire and don't ask. It does **not** license skipping telemetry, session artifacts, requirements, unit tests, E2E (`autoE2ETest` defaults to `always`), browser verification, the gate below, the Stage-7.5 repair loop, or the watcher hand-off. Stage 7.5 investigates and repairs unattended too; only its user decision collapses, into an automatic waive. Run the whole pipeline silently — never a shortcut.
|
|
40
41
|
|
|
41
42
|
### Definition of Done — gate before Stage 7
|
|
42
43
|
Do not create or update a PR until each line holds, or is waived by a one-line reason written into `state.md` (silence is not a waiver):
|
|
@@ -81,7 +82,7 @@ When invoked with the directive (PR URL + slug + review ids), routes to [`../do/
|
|
|
81
82
|
|
|
82
83
|
## Guardrails
|
|
83
84
|
|
|
84
|
-
- Stage 1
|
|
85
|
+
- Stage 1 and Stage 7.5's user decision are the only user-facing forward stages. Stages 2–7 don't ask mid-cycle; blocker → pre-flight bug.
|
|
85
86
|
- Same stage failing 3× → escalate.
|
|
86
|
-
- 3
|
|
87
|
+
- 3 repair iterations reach E2E with failures → waive, ship with `[E2E FAILING]`, and hand to the watcher.
|
|
87
88
|
- Address-reviews escalation (ambiguous or design-adjustment) does not block the watcher; user resolves on GitHub.
|
|
@@ -14,7 +14,7 @@ How an orchestrating session starts the watch on one PR. Every arming point runs
|
|
|
14
14
|
bash "<abs>/scripts/pr-watch-loop.sh" --slot "<slot>" --repo "<owner>/<repo>" --pr <n> --base <base-branch>
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
**Never author a per-slot `watch.sh`.** The loop ships as [`../../scripts/pr-watch-loop.sh`](../../scripts/pr-watch-loop.sh), with its wake conditions in [`../../scripts/pr-watch-events.sh`](../../scripts/pr-watch-events.sh); arming runs it and passes arguments. Writing the loop from this prose was how it drifted — each arm produced an independent derivation, and a derivation that quietly dropped a wake still ran, still heartbeat, still logged, and simply never fired for the signal it lost. Two slots on one machine ended up without the behind-base wake, which left their PRs unmergeable under watchers that looked healthy. The prose below says *why* each wake exists; the shipped files are the only definition of *what* fires. A slot holding a legacy generated `watch.sh` keeps it until re-armed, at which point the supersede guard retires the old loop.
|
|
17
|
+
**Never author a per-slot `watch.sh`.** The loop ships as [`../../scripts/pr-watch-loop.sh`](../../scripts/pr-watch-loop.sh), with its wake conditions in [`../../scripts/pr-watch-events.sh`](../../scripts/pr-watch-events.sh) and its state projection in [`../../scripts/pr-watch-state.jq`](../../scripts/pr-watch-state.jq); arming runs it and passes arguments. Writing the loop from this prose was how it drifted — each arm produced an independent derivation, and a derivation that quietly dropped a wake still ran, still heartbeat, still logged, and simply never fired for the signal it lost. Two slots on one machine ended up without the behind-base wake, which left their PRs unmergeable under watchers that looked healthy. The prose below says *why* each wake exists; the shipped files are the only definition of *what* fires. A slot holding a legacy generated `watch.sh` keeps it until re-armed, at which point the supersede guard retires the old loop.
|
|
18
18
|
|
|
19
19
|
The label is `PR #<n> — <title>`. Label and command both matter: some task surfaces show one, some the other, and a slot-bearing command keeps the watch identifiable everywhere a raw script blob would not. One monitor per PR, alive from arm to terminal: it is the watch's visible handle, showing as a running task the entire time the PR is polled. Its loop checks about every 60 seconds, re-reading the watermark and touching the slot's `watch-heartbeat` file each iteration — the liveness beacon that tells [`reconcile.md`](reconcile.md) a quiet watch is still alive; on a newer submitted review, a newer thread comment (`gitlab`: a newer discussion note), a thread newly unresolved (`gitlab`: discussion), **the head SHA's checks settling red** (no check pending and one or more in the `fail` bucket per [`../_shared/vcs/common/ci-rollup.md`](../_shared/vcs/common/ci-rollup.md)), **the branch falling behind or conflicting with its base** (`behind_by > 0` or the conflict signal per [`../_shared/vcs/common/branch-standing.md`](../_shared/vcs/common/branch-standing.md)), or — **only while the watch is blocked** (`BLOCKED_CIDIGEST` non-empty) — **the head's CI digest changing in any way** (not just to red) — it prints one line and **keeps watching**, advancing its in-memory floor so each event fires the tick exactly once. The review and thread floors are monotonic ids; the other three are not. The CI-red floor is the **head SHA**, because the check rollup is non-monotonic — it flips green↔red and resets on every push — so recording the red head SHA fires CI once per red head, and a later push re-arms it on the new SHA. The rebase floor (`REBASED`) is the **`rebase_key`** — `<head_sha>..<base_tip_sha>` — because staleness is a function of both sides: keying on the pair fires once per newly-due pair and re-arms when either the head or the base moves, where a head-only key would wedge permanently the first time the base advances (the head cannot change while nobody pushes). A head whose checks are still **pending** is never a red wake, and a branch with `behind_by == 0` and `mergeable == UNKNOWN` is never a rebase wake: pending checks may yet go green and conflict state is still computing, and the tick would idle on either (Steps 5–6) regardless. The blocked-CI signal is different in kind — a **resume** probe, live only while the watch is blocked: it wakes on any move of the head's CI digest (the same bucket-plus-sorted-name/conclusion signature the blocked fingerprint records — [`blocked-tick.md`](blocked-tick.md)) away from `BLOCKED_CIDIGEST`, so a block waiting on a green pass, a rerun, or an external deploy check resumes as promptly as one waiting on red. Quiet iterations print nothing and cost nothing — no model tokens are spent while the watch is quiet.
|
|
20
20
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# `autoRebase`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Sync onto `origin/{base}` before dev servers / E2E and before a push, or run as-is. Substitute `{behind}` and `{base}`.
|
|
4
4
|
|
|
5
|
-
**Picker 1** — header `Rebase first`, question `"Branch is {behind} commits behind origin/{
|
|
6
|
-
- `Rebase first` — `Pull in
|
|
5
|
+
**Picker 1** — header `Rebase first`, question `"Branch is {behind} commits behind origin/{base} — rebase first?"`
|
|
6
|
+
- `Rebase first` — `Pull in the base branch's changes so the run reflects the merged main line.` → `always`
|
|
7
7
|
- `Run as-is` — `Skip the rebase.` → `never`
|
|
8
8
|
|
|
9
9
|
**Silent action**
|
|
10
|
-
- `always` → `Rebasing onto origin/{
|
|
11
|
-
- `never` → `Running as-is ({behind} behind origin/{
|
|
10
|
+
- `always` → `Rebasing onto origin/{base} ({behind} behind)`
|
|
11
|
+
- `never` → `Running as-is ({behind} behind origin/{base})`
|
|
@@ -16,17 +16,25 @@ Gates run per `preference-gates/README.md`.
|
|
|
16
16
|
|
|
17
17
|
| Preference | Step | Decision it gates |
|
|
18
18
|
|------------|------|-------------------|
|
|
19
|
-
| `checkForUpdates` | Check
|
|
19
|
+
| `checkForUpdates` | Check 5 | Check for newer Muggle Test version |
|
|
20
20
|
|
|
21
21
|
## Checks
|
|
22
22
|
|
|
23
|
-
1. **
|
|
23
|
+
1. **Release ring** — run `muggle status` and read its `Runtime target:` and `Backend:` lines. Report the ring and the backend it resolves to.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
This is the first check because it reframes every other one: an install on a non-production ring talks to a different backend, authenticates against a different tenant, and runs a different studio binary, so "is it healthy" cannot be answered without it.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
- `production` → render as `[pass]`.
|
|
28
|
+
- Any other ring → render as `[note]`, not a failure. A staging or dev install is a deliberate state, not a fault, but it must be visible: it is the explanation for auth and backend behaviour that would otherwise look broken.
|
|
29
|
+
- If `MUGGLE_MCP_PROMPT_SERVICE_TARGET` is set in the environment, say so and name its value. It overrides the ring baked in at publish time, it is easy to leave set from an earlier shell, and it explains a ring that disagrees with the installed package.
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
2. **Electron app** — read `~/.muggle-ai/electron-app/` to find the installed version directory. Non-production rings install to a ring-suffixed directory (`<version>-staging`), so match the directory for the ring reported in Check 1 rather than assuming the bare version — the streams publish the same version deliberately, and the bare directory belongs to production. Read `.install-metadata.json` to get version and checksum. Verify the binary exists at the expected path. On macOS, check code signing with `spctl --assess --verbose`.
|
|
32
|
+
|
|
33
|
+
3. **MCP server** — call `muggle-local-check-status` to verify the server is responsive. Report auth state (authenticated, email, token expiry).
|
|
34
|
+
|
|
35
|
+
4. **Authentication** — call `muggle-remote-auth-status`. Report whether credentials are valid and when they expire.
|
|
36
|
+
|
|
37
|
+
5. **CLI version** — gate `checkForUpdates` (per `preference-gates/README.md`):
|
|
30
38
|
- `always` → run the check below.
|
|
31
39
|
- `never` → render the row as `[skip] check disabled by preference`.
|
|
32
40
|
- `ask` → run Picker 1 from `preference-gates/checkForUpdates.md` via `AskUserQuestion`; map the answer back to one of the actions above.
|
|
@@ -38,6 +46,7 @@ Gates run per `preference-gates/README.md`.
|
|
|
38
46
|
```
|
|
39
47
|
Muggle AI — Status
|
|
40
48
|
|
|
49
|
+
Release ring [pass/note] ring, backend URL
|
|
41
50
|
Electron app [pass/fail] version, binary status
|
|
42
51
|
MCP server [pass/fail] responsive, auth state
|
|
43
52
|
Authentication [pass/fail] user, expiry
|
|
@@ -46,4 +55,4 @@ CLI version [pass/warn] installed → latest
|
|
|
46
55
|
[All systems operational / Issues found — run /muggle:muggle-repair to fix.]
|
|
47
56
|
```
|
|
48
57
|
|
|
49
|
-
Use pass/fail indicators for each check. If any check fails, tell the user to run `/muggle:muggle-repair`. If the CLI version check warns (installed < latest), tell the user to run `/muggle:muggle-upgrade`.
|
|
58
|
+
Use pass/fail indicators for each check; the release ring uses `[pass]` on production and `[note]` elsewhere, never `[fail]`. When the ring is not production, state it in the closing line too, so it is not lost in a table the reader skims. If any check fails, tell the user to run `/muggle:muggle-repair`. If the CLI version check warns (installed < latest), tell the user to run `/muggle:muggle-upgrade`.
|
|
@@ -4,6 +4,7 @@ description: "Change-driven E2E acceptance testing: detects the user's recent ch
|
|
|
4
4
|
mandatoryStages:
|
|
5
5
|
- ../_shared/failure-mode-handling.md
|
|
6
6
|
- ../_shared/debug-failed-run.md
|
|
7
|
+
- ../_shared/identity-and-inbox.md
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# Muggle Test — Change-Driven E2E Acceptance Router
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-test-feature-local
|
|
3
|
-
description: Run a real-browser end-to-end (E2E) acceptance test against localhost to verify a feature works correctly — signup flows, checkout, form validation, UI interactions, or any user-facing behavior. Launches a browser that executes test steps and captures screenshots. Use this skill whenever the user asks to test, validate, or verify their web app, UI changes, user flows, or frontend behavior on localhost or a dev server — even if they don't mention 'muggle' or 'E2E' explicitly.
|
|
3
|
+
description: Run a real-browser end-to-end (E2E) acceptance test against localhost to verify a feature works correctly — signup flows, checkout, form validation, UI interactions, or any user-facing behavior. Launches a browser that executes test steps and captures screenshots. The browser runs under a real identity: each managed login profile owns a live inbox, so magic-link and sign-in-link logins, emailed OTPs, email-based 2FA, verification mail, and password resets are all testable without a mail stub or a test-only backdoor — an email-gated flow is never a reason to call something untestable. Use this skill whenever the user asks to test, validate, or verify their web app, UI changes, user flows, or frontend behavior on localhost or a dev server — even if they don't mention 'muggle' or 'E2E' explicitly.
|
|
4
|
+
mandatoryStages:
|
|
5
|
+
- ../_shared/identity-and-inbox.md
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Muggle Test Feature Local
|
|
@@ -22,7 +24,7 @@ The local URL only changes where the browser opens; it does not change the remot
|
|
|
22
24
|
Three gates apply, each per the standard procedure in [`preference-gates/README.md`](../muggle-preferences/preference-gates/README.md):
|
|
23
25
|
|
|
24
26
|
- `autoUseWorktree` at pre-flight (see [`_shared/use-worktrees.md`](../_shared/use-worktrees.md)).
|
|
25
|
-
- `autoRebase` before Step 7 (Execute) when `behind > 0` (see [`_shared/
|
|
27
|
+
- `autoRebase` before Step 7 (Execute) when `behind > 0` (see [`_shared/sync-branch-with-base.md`](../_shared/sync-branch-with-base.md)).
|
|
26
28
|
- `autoCleanup` after the PR is merged (see [`_shared/post-merge-cleanup.md`](../_shared/post-merge-cleanup.md)).
|
|
27
29
|
|
|
28
30
|
## Local environment prerequisites
|
|
@@ -48,7 +50,7 @@ Gates run per `preference-gates/README.md`.
|
|
|
48
50
|
| `autoSelectProject` | 2 | Reuse last-used Muggle Test project for this repo |
|
|
49
51
|
| `autoSelectLocalHost` | 4 | Reuse last-used local dev server URL for this repo |
|
|
50
52
|
| `autoUseWorktree` | 0 (pre-flight) | Isolate dev work in a worktree (see [`_shared/use-worktrees.md`](../_shared/use-worktrees.md)) |
|
|
51
|
-
| `autoRebase` | 0 (pre-flight) | Rebase onto `origin/<default>` before Step 7 (Execute) (see [`_shared/
|
|
53
|
+
| `autoRebase` | 0 (pre-flight) | Rebase onto `origin/<default>` before Step 7 (Execute) (see [`_shared/sync-branch-with-base.md`](../_shared/sync-branch-with-base.md)) |
|
|
52
54
|
| `showElectronBrowser` | 7 | Show Electron browser window during local E2E tests |
|
|
53
55
|
| `openTestResultsAfterRun` | 8 | Open results page on Muggle Test dashboard after run |
|
|
54
56
|
| `postPRVisualWalkthrough` | 10 | Post visual walkthrough to PR after results |
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# Rebase check
|
|
2
2
|
|
|
3
|
-
Gated by `autoRebase`. Fire per [`../../_shared/
|
|
3
|
+
Gated by `autoRebase`. Fire per [`../../_shared/sync-branch-with-base.md`](../../_shared/sync-branch-with-base.md) when `behind > 0`. Otherwise skip silently.
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -572,6 +572,59 @@ async function verifyExistingInstall({
|
|
|
572
572
|
return { valid: true, reason: "installed executable checksum is valid" };
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
+
/**
|
|
576
|
+
* Resolve the runtime target this installed package points at.
|
|
577
|
+
*
|
|
578
|
+
* Mirrors the precedence the harness itself applies: the environment override,
|
|
579
|
+
* then the target baked in at publish time, then dev.
|
|
580
|
+
* @param {{ runtimeTargetDefault?: string }} config - The package's muggleConfig.
|
|
581
|
+
* @returns {string} The resolved runtime target name.
|
|
582
|
+
*/
|
|
583
|
+
function resolveRuntimeTarget(config) {
|
|
584
|
+
return process.env.MUGGLE_MCP_PROMPT_SERVICE_TARGET || config.runtimeTargetDefault || "dev";
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Get the electron-app release stream a runtime target installs its studio from.
|
|
589
|
+
*
|
|
590
|
+
* Downloading the wrong stream yields a binary that talks to the wrong backend
|
|
591
|
+
* and fails checksum verification against the stream's recorded hashes.
|
|
592
|
+
* @param {string} runtimeTarget - Resolved runtime target name.
|
|
593
|
+
* @returns {string} Release stream name, for example "production".
|
|
594
|
+
*/
|
|
595
|
+
function getReleaseStream(runtimeTarget) {
|
|
596
|
+
const { targets } = require("../config/runtime-targets.json");
|
|
597
|
+
const profile = targets[runtimeTarget];
|
|
598
|
+
|
|
599
|
+
if (!profile) {
|
|
600
|
+
throw new Error(
|
|
601
|
+
`Unknown runtime target '${runtimeTarget}'. ` +
|
|
602
|
+
`Expected one of: ${Object.keys(targets).join(", ")}.`,
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
return profile.electronAppReleaseStream;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Get the release tag prefix for an electron-app release stream.
|
|
611
|
+
* @param {string} releaseStream - Release stream name.
|
|
612
|
+
* @returns {string} Release tag prefix, for example "electron-app-v".
|
|
613
|
+
*/
|
|
614
|
+
function getReleaseTagPrefix(releaseStream) {
|
|
615
|
+
const { streams } = require("../config/runtime-targets.json");
|
|
616
|
+
const stream = streams[releaseStream];
|
|
617
|
+
|
|
618
|
+
if (!stream) {
|
|
619
|
+
throw new Error(
|
|
620
|
+
`Unknown electron-app release stream '${releaseStream}'. ` +
|
|
621
|
+
`Expected one of: ${Object.keys(streams).join(", ")}.`,
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return stream.electronAppReleaseTagPrefix;
|
|
626
|
+
}
|
|
627
|
+
|
|
575
628
|
/**
|
|
576
629
|
* Download and extract the Electron app.
|
|
577
630
|
*/
|
|
@@ -583,11 +636,15 @@ async function downloadElectronApp() {
|
|
|
583
636
|
const version = config.electronAppVersion || "1.0.0";
|
|
584
637
|
const baseUrl = config.downloadBaseUrl || "https://github.com/multiplex-ai/muggle-ai-works/releases/download";
|
|
585
638
|
|
|
639
|
+
const runtimeTarget = resolveRuntimeTarget(config);
|
|
640
|
+
const releaseStream = getReleaseStream(runtimeTarget);
|
|
641
|
+
const releaseTagPrefix = getReleaseTagPrefix(releaseStream);
|
|
642
|
+
|
|
586
643
|
const binaryName = getBinaryName();
|
|
587
|
-
const checksums = config.
|
|
644
|
+
const checksums = (config.checksumsByStream || {})[releaseStream] || {};
|
|
588
645
|
const platformKey = getPlatformKey();
|
|
589
646
|
const expectedChecksum = checksums[platformKey] || "";
|
|
590
|
-
const downloadUrl = `${baseUrl}
|
|
647
|
+
const downloadUrl = `${baseUrl}/${releaseTagPrefix}${version}/${binaryName}`;
|
|
591
648
|
|
|
592
649
|
const appDir = getElectronAppDir();
|
|
593
650
|
const versionDir = join(appDir, version);
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Rebase Onto the Default Branch Before Dev Server / E2E
|
|
2
|
-
|
|
3
|
-
Gated by [`autoRebase`](../muggle-preferences/preference-gates/autoRebase.md). Follow the standard procedure in [`preference-gates/README.md`](../muggle-preferences/preference-gates/README.md).
|
|
4
|
-
|
|
5
|
-
**Fire only when `behind > 0`:**
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
git fetch origin
|
|
9
|
-
default=$(git symbolic-ref refs/remotes/origin/HEAD --short | sed 's|origin/||')
|
|
10
|
-
behind=$(git rev-list --count "HEAD..origin/${default}")
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Pass `{behind}` and `{default}` to the picker prompts. On `always`:
|
|
14
|
-
|
|
15
|
-
1. Capture the rollback point: `pre_rebase_sha=$(git rev-parse HEAD)`.
|
|
16
|
-
2. `git rebase origin/${default}`.
|
|
17
|
-
3. On conflict, branch by [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md):
|
|
18
|
-
- `never` → `git rebase --abort`; stop and report, naming the conflicted files. Never auto-resolve.
|
|
19
|
-
- `always` → hand off to [`resolve-rebase-conflicts.md`](resolve-rebase-conflicts.md) with `pre_rebase_sha` to resolve the conflicts, then run the [`verify-or-rollback-gate.md`](verify-or-rollback-gate.md) with `pre_rebase_sha`; it either proceeds or restores `pre_rebase_sha` and escalates.
|
|
20
|
-
|
|
21
|
-
Stale branches produce false failures and false greens — that's why this gate exists.
|
|
@@ -1,10 +0,0 @@
|
|
|
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.
|
package/dist/src-B5OTAZKM.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { DEFAULT_PREFERENCES, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, ProjectPreferencesReconcileOutcome, WATCHER_LIFETIME_SECONDS, WATCHER_LIFETIME_UNBOUNDED_SECONDS, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports as e2e, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports as localQa, mcp_exports as mcp, openBrowserUrl, performLogin, performLogout, pollDeviceCode, e2e_exports as qa, reconcileProjectPreferences, resetConfig, resetLogger, resetPreference, resolveElectronAppPathOrNull, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences } from './chunk-MSPMXBO5.js';
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Rebase Onto the Default Branch Before Dev Server / E2E
|
|
2
|
-
|
|
3
|
-
Gated by [`autoRebase`](../muggle-preferences/preference-gates/autoRebase.md). Follow the standard procedure in [`preference-gates/README.md`](../muggle-preferences/preference-gates/README.md).
|
|
4
|
-
|
|
5
|
-
**Fire only when `behind > 0`:**
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
git fetch origin
|
|
9
|
-
default=$(git symbolic-ref refs/remotes/origin/HEAD --short | sed 's|origin/||')
|
|
10
|
-
behind=$(git rev-list --count "HEAD..origin/${default}")
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Pass `{behind}` and `{default}` to the picker prompts. On `always`:
|
|
14
|
-
|
|
15
|
-
1. Capture the rollback point: `pre_rebase_sha=$(git rev-parse HEAD)`.
|
|
16
|
-
2. `git rebase origin/${default}`.
|
|
17
|
-
3. On conflict, branch by [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md):
|
|
18
|
-
- `never` → `git rebase --abort`; stop and report, naming the conflicted files. Never auto-resolve.
|
|
19
|
-
- `always` → hand off to [`resolve-rebase-conflicts.md`](resolve-rebase-conflicts.md) with `pre_rebase_sha` to resolve the conflicts, then run the [`verify-or-rollback-gate.md`](verify-or-rollback-gate.md) with `pre_rebase_sha`; it either proceeds or restores `pre_rebase_sha` and escalates.
|
|
20
|
-
|
|
21
|
-
Stale branches produce false failures and false greens — that's why this gate exists.
|
|
@@ -1,10 +0,0 @@
|
|
|
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.
|