@mutmutco/kilo-plugin 3.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/agent/reviewer.md +108 -0
  2. package/package.json +23 -0
  3. package/scripts/command-ladder-core.mjs +334 -0
  4. package/scripts/command-ladder-gate.mjs +126 -0
  5. package/scripts/deny-gate-crash.mjs +179 -0
  6. package/scripts/edit-tool-paths.mjs +113 -0
  7. package/scripts/env-write-lint.mjs +137 -0
  8. package/scripts/hook-io.mjs +17 -0
  9. package/scripts/hook-policy.mjs +73 -0
  10. package/scripts/hook-run.mjs +170 -0
  11. package/scripts/hook-trace.mjs +108 -0
  12. package/scripts/pretooluse-shell-gates.mjs +420 -0
  13. package/scripts/secret-echo-lint.mjs +170 -0
  14. package/scripts/secret-redact.mjs +537 -0
  15. package/scripts/throttle-core.mjs +324 -0
  16. package/scripts/validate-hook.mjs +156 -0
  17. package/scripts/vault-edit-gate.mjs +94 -0
  18. package/server.mjs +237 -0
  19. package/skills/bootstrap/SKILL.md +493 -0
  20. package/skills/bootstrap/seeds/Dockerfile.template +30 -0
  21. package/skills/bootstrap/seeds/README.template.md +36 -0
  22. package/skills/bootstrap/seeds/architecture.template.md +34 -0
  23. package/skills/bootstrap/seeds/decisions-readme.template.md +46 -0
  24. package/skills/bootstrap/seeds/docker-compose.template.yml +26 -0
  25. package/skills/bootstrap/seeds/gate.template.yml +90 -0
  26. package/skills/bootstrap/seeds/google-login.template.md +33 -0
  27. package/skills/bootstrap/seeds/manifest.json +26 -0
  28. package/skills/bootstrap/seeds/mmi-product-required-checks.template.json +23 -0
  29. package/skills/browser-automation/SKILL.md +93 -0
  30. package/skills/doctor/SKILL.md +76 -0
  31. package/skills/epic/SKILL.md +87 -0
  32. package/skills/hotfix/SKILL.md +113 -0
  33. package/skills/mmi/SKILL.md +400 -0
  34. package/skills/onboard/SKILL.md +70 -0
  35. package/skills/rcand/SKILL.md +194 -0
  36. package/skills/release/SKILL.md +546 -0
  37. package/skills/resume/SKILL.md +68 -0
  38. package/skills/secrets/SKILL.md +157 -0
  39. package/skills/stage/SKILL.md +151 -0
  40. package/skills/worktree/SKILL.md +86 -0
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: secrets
3
+ description: Manage the full own-project vault and granted org-infra secret names.
4
+ ---
5
+
6
+ # /secrets — two-tier project secrets
7
+
8
+ **Authority:** a project-admin self-serves their own product repo's full vault tree (`mmi-cli org access
9
+ role` → `project-admin` + `train`): stageless, `dev`, `rc`, and `main`. Do not redirect them to master for
10
+ an own-project coordinate. Only org-infra grants and cross-project administration stay master-only.
11
+
12
+ Secrets in the org split by **blast radius + who manages them** (not by storage — both tiers are SSM
13
+ SecureString + KMS, and **a value is never echoed to chat or logs**):
14
+
15
+ - **YOUR REPO** — `/mmi-future/<slug>/<KEY>` (the stageless canonical) plus
16
+ `/mmi-future/<slug>/{dev,rc,main}/*` (staged per-stage overrides) for a repo you are project-admin of.
17
+ You **self-serve your own repo's full tree** — the canonical root, dev, rc, AND main prod secrets — via
18
+ `/secrets`, on your **GitHub role alone**, no AWS, no waiting on the master (#2032).
19
+ - **ORG-INFRA** — the shared/infra namespaces (`/mmi-future/{shared,cloudflare,docs,mmi-hub}/*`), at
20
+ **every** tier (their `dev/` holds Hetzner/AWS/CF tokens + Hub tooling). **Crown jewels, master-only.**
21
+ A project-admin reaches one of these only via a master **grant**; the master is unrestricted (master ⊇
22
+ project-admin).
23
+
24
+ **Grant scope (#3652).** A grant is `rw` by default — it opens both keyless `use` and `set`/`rm` on that
25
+ key. `mmi-cli secrets grant <repo> <login> <key> --read` grants **consume-only** reach: keyless `use`
26
+ works, rotate and remove still refuse. Only a `--read` grant may name a **wildcard** key — `*` for the
27
+ whole namespace, `<provider>/*` for one provider group — so "may read every crown jewel" is one grant
28
+ instead of forty. A wildcard never confers write; asking for one as `rw` is refused, not narrowed.
29
+ `mmi-cli org access capabilities` prints `grant (read)` or `grant (rw)` next to each name.
30
+
31
+ A bare `<KEY>` is the **stageless canonical** at the slug root — one value every stage shares (#2244)
32
+ and the path deploys resolve (#2523). A staged `dev/<KEY>` is a **per-stage override** and WINS for that
33
+ stage at deploy (#2522); `set`/`use` warn (names only) when an override shadows the canonical. The
34
+ `dev`/non-`dev` `tier` field in older JSON is compatibility metadata, not an authority boundary: an
35
+ own-project `main/SECRET_KEY_BASE` or `rc/DB_URL` remains project-admin self-service.
36
+
37
+ **Declare-first (#2528):** the registry catalog is the SSOT; SSM is a projection of it. A `set` to a
38
+ coordinate not declared in the catalog is **rejected** — the error names the attempted path and the fix.
39
+ Declare the key first via `mmi-cli org project set <owner/repo> --secrets-file <catalog.json>` (`stages: []`
40
+ = the shared stageless canonical, `stages: ["dev"]` = a per-stage override), then retry. See what is
41
+ declared with `mmi-cli secrets catalog` or `secrets list`; ask for a key you lack via `mmi-cli secrets
42
+ request <KEY>`. There is no master bypass. `rm` of an undeclared path stays allowed, so cleanup keeps
43
+ working. Google OAuth is one stageless pair per repo: bare `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET`
44
+ at the slug root (the staged `{dev,rc,main}/GOOGLE_*` shape is retired; `org oauth set-creds` writes the
45
+ bare keys).
46
+
47
+ All ops run through `mmi-cli secrets …`, which calls the org backend with the caller's `gh` token; the
48
+ backend re-verifies **project-admin-of-this-repo** and the **vault namespace** server-side and does the scoped
49
+ SSM op. This skill never touches AWS.
50
+
51
+ ## Step 0 — orient
52
+
53
+ Read the current repo + slug; the tier of a key follows from its name (above). `secrets list` shows what
54
+ exists and which ones **you** can manage (a `*`), never values.
55
+
56
+ ```bash
57
+ mmi-cli secrets list # names + tier + a * on the ones you can write. NEVER values.
58
+ ```
59
+
60
+ `secrets: no registry META` or `Hub API unreachable` → the repo is not registered with the Hub, GitHub auth
61
+ is missing, or the Hub API is unavailable. Run `mmi-cli org project get <owner/repo>` to distinguish those cases;
62
+ a master-admin backfills the registry before secrets can be resolved.
63
+
64
+ ## Step 1 — the verb
65
+
66
+ Default to the **current repo**; pass `--repo owner/Name` to target another (you must be its project-admin).
67
+
68
+ ```bash
69
+ # CONSUME a secret keyless — injected into the command's env, NEVER printed (raw `secrets get` was
70
+ # removed, the floor wins, #2844):
71
+ mmi-cli secrets use SCRAPER_API_KEY -- <cmd>
72
+
73
+ # Write / rotate — the VALUE is read from stdin, NEVER an argument (so it can't leak into shell history
74
+ # or process args). Pipe it in:
75
+ printf %s "$THE_VALUE" | mmi-cli secrets set SCRAPER_API_KEY
76
+
77
+ # Validate a known provider key without printing its value:
78
+ mmi-cli secrets verify RECALL_API_KEY
79
+
80
+ # Remove:
81
+ mmi-cli secrets rm SCRAPER_API_KEY
82
+ ```
83
+
84
+ **Never** pass a value as an argument (`secrets set KEY thevalue` is wrong — there is no value arg). The
85
+ confirmation prints the **name and tier only**, never the value.
86
+
87
+ ## Rotation checklist
88
+
89
+ Before rotating, enumerate every copy of the key so no tier stays stale:
90
+
91
+ ```bash
92
+ mmi-cli secrets list --repo owner/Repo
93
+ ```
94
+
95
+ Check the bare canonical plus any `dev/`, `rc/`, `main/` overrides the list shows. Rotate the provider-side
96
+ key first, then write every declared coordinate that still needs that key. For keys with a provider probe
97
+ (`RECALL_API_KEY` today), `secrets set` validates the new value before printing success; `secrets verify
98
+ <KEY>` repeats the same probe later without printing the value. If the verifier fails, treat the rotation as
99
+ incomplete even if the vault write itself succeeded.
100
+
101
+ ## Step 2 — org-infra elevation (master-only)
102
+
103
+ Your own repo's full tree (dev/rc/main) is already self-serve (#2032). The **org-infra** namespaces
104
+ (`shared`/`cloudflare`/`docs`/`mmi-hub`, every tier) stay master-only. A project-admin who needs one of
105
+ those keys asks the master, who grants a **scoped, auditable** standing access to that one key (or revokes
106
+ it). These verbs are **master-only** — the backend 403s anyone else.
107
+
108
+ ```bash
109
+ # MASTER: let @oguz-mut consume one _org provider key from their MM-Chat project
110
+ mmi-cli secrets grant mutmutco/MM-Chat oguz-mut google/SOME_SHARED_KEY
111
+ # MASTER: withdraw it
112
+ mmi-cli secrets revoke mutmutco/MM-Chat oguz-mut google/SOME_SHARED_KEY
113
+ ```
114
+
115
+ The master can also operate the org-infra key directly while guiding (master ⊇ project-admin). Org-infra
116
+ access by a project-admin **always originates from the master** — own-project access does not.
117
+
118
+ ## Coordinate — where does a new project secret belong?
119
+
120
+ - Shared across stages → bare `<KEY>` at the project slug root (the usual canonical value).
121
+ - Genuinely stage-distinct → `<stage>/<KEY>` override for `dev`, `rc`, or `main`.
122
+ - The project-admin owns both shapes across their own project. A path under `_org`/shared infrastructure is
123
+ not a project coordinate and stays master-managed.
124
+
125
+ ## Tier-to-tier copy (provider keys, #1433)
126
+
127
+ **Encryption / stage-distinct keys** (`*_ENC_KEY`, `SECRET_KEY_BASE`, etc.) must be **generated per stage** —
128
+ never copied. **Provider sandbox keys** (e.g. Recall/Gemini for Katip dev/rc) **may** be shared across dev/rc
129
+ when they point at the same sandbox project; prod should stay distinct when the provider contract requires it.
130
+
131
+ Sanctioned copy within the own-project vault (org-infra/cross-project sources remain master-gated):
132
+ ```bash
133
+ mmi-cli secrets copy --from rc --to dev --keys RECALL_API_KEY,GEMINI_API_KEY
134
+ mmi-cli secrets copy --from rc --to dev --keys RECALL_API_KEY --dry-run # plan only
135
+ ```
136
+ Prefer this over manual copy piping — audit-logged, blocklist enforced.
137
+
138
+ ## Notes
139
+
140
+ - **Never echo a value** — not in chat, a commit, a log, or an issue. No command emits a value to stdout;
141
+ consume one keyless with `secrets use <KEY> -- <cmd>` (#2844). Treat every secret as write-once.
142
+ - Authority is **GitHub**: project-admin = repo `write` plus the registry `projectAdmins` entry, master =
143
+ org owner. The backend checks both with the org App token, so the decision is server-side (your token
144
+ scope can't widen it).
145
+ - Runtime consumes declared keys through its scoped broker token (and central deploy injects the declared
146
+ stage set without a repo `.env`); CI reads keylessly through its OIDC role. Neither uses raw `/secrets`
147
+ output. `secrets use <KEY>` is the safe local command-consumption path.
148
+ - Every self-service write is **attributable** — the backend logs actor + repo + KEY name (never the value).
149
+
150
+ ## Retro — one check before you finish
151
+ Before your final report, answer one question honestly: did **this skill's own instructions** misfire
152
+ this run — ambiguous wording, a misleading message, or an environment failure it should have warned
153
+ about? (Process only — never the user's code or task; e.g. a canonical-name or tier mix-up, or a step
154
+ that risked echoing a value.) If yes, file **one** lesson and move on; a clean run is silent (hard cap:
155
+ one per run). It lands on the Hub board (deduped) and is fixed only via a reviewed PR — never edit the
156
+ skill live; the retro is advisory, so if the call fails, note it and continue:
157
+ `mmi-cli skill-lesson --skill secrets --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
@@ -0,0 +1,151 @@
1
+ ---
2
+ name: stage
3
+ description: Run a local test stage, or a personal cloud dev stage with --live.
4
+ ---
5
+
6
+ # /stage — local test environment
7
+
8
+ A throwaway **local** environment to exercise the current branch — a dev server / local stack, plus
9
+ Playwright or other tools where the project uses them. It is **off the promotion train**: any developer,
10
+ no version effect, no deploy. It lives in a **gitignored** workspace, **force-kills the previous stage**
11
+ before starting, and **auto-decommissions** when done.
12
+
13
+ Use `/stage` as the normal path for local previews, smoke tests, and Playwright targets. If the user
14
+ already asked to run or preview the app, that is enough authorization to start it; when intent is unclear,
15
+ ask before creating or destroying a stage. Manual dev-server commands are allowed when the user explicitly
16
+ wants a bypass or when a bounded diagnostic needs one, but say why. If the stage path itself fails, diagnose
17
+ from `mmi-cli stage --json`, `tmp/stage/state.json`, process/port/container evidence, and file Hub/org-default
18
+ friction instead of silently working around it.
19
+
20
+ The stage recipe is the **registry-derived default** for plumbing-free product repos: a `tenant-container`
21
+ repo that ships `docker-compose.yml` and has a Hub registry `portRange` needs **no committed config**.
22
+ `mmi-cli stage` derives a default compose stage — run `docker compose build --no-cache`, run `docker compose
23
+ up -d`, choose a free port from the registry range, and report the local URL (e.g. `http://127.0.0.1:3700/`).
24
+ The commands are shell-aware and `--apply` runs them cross-shell. Board, deploy, secret, and project registry
25
+ facts all live in the Hub registry — no repo-local control-plane file.
26
+
27
+ **Secrets are vault-native — no `.env` on disk (#2655).** The org forbids *using* `.env` files, not just
28
+ committing them. A repo **without** `.env.example` stages vault-native: `mmi-cli stage --apply` resolves the
29
+ declared dev runtime secrets (registry `requiredRuntimeSecrets[dev]`) from the vault and injects them straight
30
+ into the compose **process environment** — the compose file reads them via `environment:` passthrough, and no
31
+ secret ever touches disk. A repo that still ships `.env.example` keeps the legacy `.env` bootstrap for
32
+ back-compat until its compose migrates to passthrough; new repos should ship **no** `.env.example`.
33
+
34
+ ## Step 0 — inspect the plan
35
+
36
+ ```bash
37
+ mmi-cli stage --json
38
+ ```
39
+
40
+ The JSON reports `source` (`derived` / `local` / `none`) and, when derived, the local `url`. `source: none`
41
+ means neither a usable local recipe nor a derivable default exists — the message names the missing fact
42
+ (deployModel, `docker-compose.yml`, or registry `portRange`; `.env.example` is **not** required — #2655).
43
+ That gap does not mean the repo's Hub registry/org project setup is missing.
44
+
45
+ ## Step 1 — run the stage
46
+
47
+ A stage is **per worktree**. The CLI force-stops only the previous stage **in this worktree**, runs
48
+ `stage.build`, starts `stage.up`, records `tmp/stage/state.json`, picks a free port from the registry
49
+ range (skipping ports reserved by sibling worktrees), and polls `stage.healthUrl` when configured.
50
+ Use `--port` to pin a port when needed:
51
+
52
+ ```bash
53
+ mmi-cli stage run --apply
54
+ mmi-cli stage run --apply --port 5180
55
+ ```
56
+
57
+ Use a larger bound when the repo's local stack is known to be slow:
58
+ ```bash
59
+ mmi-cli stage run --apply --timeout-ms 120000
60
+ ```
61
+
62
+ All stage artifacts (build output, screenshots, Playwright traces, local DB files) stay under `tmp/stage/`
63
+ — never tracked.
64
+
65
+ A local stage is bound to the worktree that started it. Concurrent worktrees on one machine each keep
66
+ their own stage on separate ports — you do not need to stop one before starting another. For `jervaise`, continuity
67
+ keys on branch; use a distinct North Star slug per parallel grind or feature. Stage JSON/state records
68
+ the starting `cwd` plus git branch/commit when available.
69
+
70
+ ### Step 1a — post-smoke panel (when criteria exist)
71
+
72
+ When grinding or the user supplied **acceptance criteria** (from the issue body at Gate 1 — not
73
+ ad-hoc chat text), run a **Budget-routing panel** on observable stage signals before teardown:
74
+
75
+ 1. **Panel** (parallel):
76
+ - **requirements-match** (budget tier) — does the staged URL/behavior meet the criteria?
77
+ - **runtime-health** (budget tier) — console errors, failed `healthUrl`, broken UI signals
78
+ *(smoke observability — not the grind `correctness` hard lens)*
79
+ - **tests-actually-test** (budget tier) — if Playwright ran, did it exercise the changed path?
80
+ 2. **Confirm** — get an independent second model to verify the staged URL or behavior meets the acceptance criteria.
81
+ 3. Feed the result back to the active loop or report to the human. A blocker
82
+ means the stage failed smoke — do not claim the grind criterion met.
83
+ This panel is **not** a security clearance — grind Phase 2 still runs the `security` hard lens.
84
+
85
+ Skip when `/stage` is ad-hoc preview with no criteria.
86
+
87
+ ## Step 2 — stop when done
88
+
89
+ ```bash
90
+ mmi-cli stage stop --apply
91
+ ```
92
+
93
+ Stop the stage when the work is done, before switching context, or before replacing it with another stage.
94
+ If the user clearly wants the preview to stay up, leave it running and report that. The next `/stage` also
95
+ stops the previous recorded stage before starting, so a stale server does not linger between runs. For the
96
+ registry-derived Docker Compose default, stop also runs the recorded compose teardown (`docker compose down`)
97
+ from the original stage working directory.
98
+
99
+ ## /stage --live — personal cloud dev stage
100
+
101
+ dev.x stages are **not standing environments**: without `--live` the dev stage is dark. `--live`
102
+ deploys the **current branch** to the project's dev runtime and serves it **only to your public IP** —
103
+ gated at the **Cloudflare edge** (#1761). The CLI detects your IP, dispatches the central
104
+ `tenant-deploy.yml` (stage=dev), then `tenant-control.yml` `cf-gate-allow` (an ephemeral Cloudflare WAF
105
+ rule scoped to your dev host + IP). The box no longer IP-gates dev. No SSH from your machine; everything
106
+ moves through the central workflows.
107
+
108
+ ```bash
109
+ mmi-cli stage --live # dry-run plan
110
+ mmi-cli stage --live --apply # deploy + gate your IP at the Cloudflare edge
111
+ ```
112
+
113
+ Tear it down when done — the runtime stops and the Cloudflare edge gate is removed:
114
+
115
+ ```bash
116
+ mmi-cli stage --live --down --apply
117
+ ```
118
+
119
+ Personal dev stages only — rc/live environments still move exclusively through the promotion train.
120
+
121
+ ## Step 3 — report
122
+
123
+ The stage URL, what's running (server + tools), the workspace path (`tmp/stage/`), and the teardown command.
124
+
125
+ ## Notes
126
+
127
+ - `/stage` is local — no AWS, no deploy, no board or version effect. The one cloud exception is
128
+ `--live`: an on-demand **dev** stage of your branch, gated to your IP at the Cloudflare edge (above).
129
+ - `/stage-live` is not an org command: remote rc/live environments move only through `/rcand`, `/release`, and `/hotfix`.
130
+ - Everything is gitignored; `/stage` never produces a tracked change.
131
+ - **Playwright MCP output goes to `tmp/`**, never the repo root: if you drive the Playwright MCP server,
132
+ pass `--output-dir tmp/playwright-mcp` (or point its output there). `.playwright-mcp/` is kept gitignored
133
+ by the org `.gitignore` managed block (`mmi-cli doctor`) as a safety net, so a stray default capture is
134
+ never tracked.
135
+ - `tools[]` is declarative for now; stage hardening starts/stops the main configured process. Repos with
136
+ extra local services should encode them behind `stage.up` until a tool runner is added.
137
+ - **Stale Docker bundle:** the registry-derived Docker Compose default builds with `docker compose build
138
+ --no-cache` before `up`. If the browser still serves an old bundle, run `mmi-cli stage stop --apply`, rerun
139
+ `/stage`, then inspect `tmp/stage/state.json` identity, container image labels, and compose build inputs.
140
+ - **Stale `.env`:** when `.env` already exists from a prior `/stage` run, `stage run` does **not** refresh it
141
+ from an updated `.env.example` — it warns on stderr and keeps the stale file. Delete `.env` (or merge in the
142
+ new keys by hand) when `.env.example` changes, then re-run `/stage`.
143
+
144
+ ## Retro — one check before you finish
145
+ Before your final report, answer one question honestly: did **this skill's own instructions** misfire
146
+ this run — ambiguous wording, a misleading message, or an environment failure it should have warned
147
+ about? (Process only — never the user's code or task; e.g. a teardown that left a port bound, or a
148
+ Playwright output path aimed at the repo root.) If yes, file **one** lesson and move on; a clean run is
149
+ silent (hard cap: one per run). It lands on the Hub board (deduped) and is fixed only via a reviewed PR —
150
+ never edit the skill live; the retro is advisory, so if the call fails, note it and continue:
151
+ `mmi-cli skill-lesson --skill stage --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: worktree
3
+ description: Orchestrate a worktree from create to landed PR, tied to board status.
4
+ ---
5
+
6
+ # /worktree — create → work → land
7
+
8
+ Drive an item through an isolated worktree: cut it from latest `development`, claim the board item, do the
9
+ work, open and land the PR, and clean up — with the board moving automatically at each boundary. One
10
+ worktree per session; everything under `../mmi-worktrees/` is ephemeral and sweepable.
11
+
12
+ ## Step 1 — create + provision
13
+
14
+ ```bash
15
+ mmi-cli worktree create <owner/repo#N> --claim --from origin/development
16
+ ```
17
+
18
+ `worktree create` cuts the branch from `origin/development` (fetched first) and provisions it: installs
19
+ deps (`npm ci`) and copies local-only config (`.claude/settings.local.json`) a fresh checkout lacks. Use
20
+ `--from <ref>` for a non-default base, `--path <path>` to override the location. An existing worktree that
21
+ lost its deps re-provisions with `mmi-cli worktree setup [path]` (the SessionStart hook fires this
22
+ automatically).
23
+
24
+ The issue-ref form derives `<issue-number>-<short-slug>`, assigns the item, and moves it to In Progress.
25
+
26
+ ## Step 2 — claim + work
27
+
28
+ Work in the provisioned worktree. Exercise the change with `/stage` (a local stage is bound to the worktree that
29
+ started it — stop it before switching worktrees). Sequential related items in one session reuse the active
30
+ worktree; do not churn one worktree per issue unless a true parallel or PR boundary needs it.
31
+
32
+ ## Step 3 — open the PR
33
+
34
+ Push the branch and open the PR against `development`. The board moves to In Review automatically on PR
35
+ open — never move it by hand.
36
+
37
+ ```bash
38
+ git push origin <branch>:<branch> # explicit feature refspec — see below
39
+ mmi-cli pr create --title "<title>" --body-file PR_BODY.md --base development
40
+ mmi-cli pr checks-wait <PR-number> # wait for required CI to go green
41
+ ```
42
+
43
+ The push must be the explicit `<branch>:<branch>` refspec (the branch Step 1 derived, e.g.
44
+ `git push origin 3795-my-slice:3795-my-slice`). The #1660 protected-push gate denies the
45
+ `HEAD`/remote-only form (`git push -u origin HEAD`) — its target cannot be proven safe. And never
46
+ share the push with staging or commit verbs in one compound command: the deny applies to the whole
47
+ command, so a refused `git add … && git commit … && git push …` chain discards the add and commit
48
+ with it. Stage, commit, and push as separate commands.
49
+
50
+ ## Step 4 — land + clean up
51
+
52
+ Under standing go (green CI, CI-gated PR) land to `development`:
53
+
54
+ ```bash
55
+ mmi-cli pr land <PR-number>
56
+ ```
57
+
58
+ `pr land` waits for checks, squash-merges, and does the full cleanup at the branch boundary: removes the
59
+ worktree, deletes the merged branch (local + origin), and prunes tracking refs. A worktree the IDE has
60
+ locked is queued and retried by `mmi-cli worktree gc sweep-deferred`. Self-authored merges need an explicit
61
+ per-session merge grant — ask early if you don't have one.
62
+
63
+ ## Step 5 — record + next
64
+
65
+ Record durable decisions on the issue or PR, then check the board again:
66
+
67
+ ```bash
68
+ mmi-cli wave status # remaining worktrees, open PRs, local stages at a glance
69
+ mmi-cli next # the next actionable item
70
+ ```
71
+
72
+ ## Notes
73
+
74
+ - Cut worktrees only at `../mmi-worktrees/<RepoName>/<branch>` (#3471) — generic helpers that force `.claude/worktrees/` or
75
+ `.worktrees/` are not the MMI path.
76
+ - Multiple independent items → one worktree each, run in parallel, one PR per item (`/mmi` Leverage).
77
+ - Never land to a protected/release branch here — that is `/rcand` and `/release`.
78
+
79
+ ## Retro — one check before you finish
80
+ Before your final report, answer one question honestly: did **this skill's own instructions** misfire
81
+ this run — ambiguous wording, a misleading message, or an environment failure it should have warned
82
+ about? (Process only — never the user's code or task; e.g. a create that branched from a stale base, or a
83
+ land that left a worktree behind.) If yes, file **one** lesson and move on; a clean run is silent (hard
84
+ cap: one per run). It lands on the Hub board (deduped) and is fixed only via a reviewed PR — never edit
85
+ the skill live; the retro is advisory, so if the call fails, note it and continue:
86
+ `mmi-cli skill-lesson --skill worktree --title "<what misfired>" --body "<what; evidence; proposed amendment>"`