@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,26 @@
1
+ services:
2
+ app:
3
+ build:
4
+ context: .
5
+ dockerfile: Dockerfile
6
+ # Build-time secret opt-in:
7
+ # secrets:
8
+ # - NODE_AUTH_TOKEN
9
+ restart: unless-stopped
10
+ # The box control document writes registry coords + stage-scoped SSM secret values into the
11
+ # release ./.env before `docker compose up`; env_file is what delivers them into the container.
12
+ env_file: .env
13
+ environment:
14
+ NODE_ENV: production
15
+ MMI_STAGE: ${MMI_STAGE:-dev}
16
+ MMI_PORT: ${MMI_PORT:-3000}
17
+ PORT: ${PORT:-3000}
18
+ MMI_EDGE_DOMAIN: ${MMI_EDGE_DOMAIN:-}
19
+ ports:
20
+ - "${MMI_PORT:-3000}:${PORT:-3000}"
21
+
22
+ # Build-time secret opt-in. Requires registry META:
23
+ # requiredBuildSecrets: ["NODE_AUTH_TOKEN=@github-packages-token"]
24
+ # secrets:
25
+ # NODE_AUTH_TOKEN:
26
+ # environment: NODE_AUTH_TOKEN
@@ -0,0 +1,90 @@
1
+ name: gate
2
+ # Org-standard green-before-merge gate for product repos (#1333). Runs on PRs, train-branch pushes,
3
+ # and v* tags so /release and /hotfix can discover required contexts on the tagged SHA.
4
+ #
5
+ # Runner: self-hosted mmi-runner (mmi-live) — see docs/Guides/gh-runner-runbook.md in MMI-Hub.
6
+ # Stack-aware (#1550): the runtime is rendered into the setup-step `if:` — both the Node and Python
7
+ # setup steps live in the file but only the one matching GATE_RUNTIME runs. Knobs (override at
8
+ # bootstrap with --var):
9
+ # GATE_RUNTIME — node | python (selects which setup step fires)
10
+ # GATE_CMD — the check command ({{GATE_CMD}})
11
+ # GATE_INSTALL_CMD — the dependency-install command ({{GATE_INSTALL_CMD}})
12
+ # GATE_WORKDIR — app working directory when not the repo root ({{GATE_WORKDIR}})
13
+ # GATE_CACHE_DEP_PATH— npm lockfile path for the setup-node cache ({{GATE_CACHE_DEP_PATH}})
14
+ # GATE_PY_VERSION — Python version for setup-python ({{GATE_PY_VERSION}})
15
+ # GATE_MAX_SECONDS — run-with-budget wall-clock ceiling in seconds ({{GATE_MAX_SECONDS}}); 300 default,
16
+ # tighten per repo (org project set --var gate={"maxSeconds":N}) once measured (#3178)
17
+ # GATE_BUDGET_SHA is rendered by the CLI from its blessed run-with-budget pin — not an operator knob.
18
+ on:
19
+ pull_request:
20
+ push:
21
+ branches: {{GATE_PUSH_BRANCHES_YAML}}
22
+ tags: ['v*']
23
+
24
+ env:
25
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
26
+
27
+ # #3001: cancel superseded runs — agent push-bursts queue a full fresh run per push.
28
+ # Per-PR group only (a repo-wide group hits GitHub's one-pending-slot limit and cancels
29
+ # innocent queued runs — MMC-ZuberShade#880). Pushes group by ref: each tag and the train
30
+ # branch supersede only themselves.
31
+ concurrency:
32
+ group: gate-${{ github.event.pull_request.number || github.ref }}
33
+ cancel-in-progress: true
34
+
35
+ permissions:
36
+ contents: read
37
+
38
+ jobs:
39
+ gate:
40
+ if: ${{ github.event_name != 'push' || github.ref_name == '{{GATE_FULL_RUN_BRANCH}}' || github.ref_type == 'tag' }}
41
+ runs-on: [self-hosted, linux, x64, mmi-live]
42
+ defaults:
43
+ run: { working-directory: {{GATE_WORKDIR}} }
44
+ steps:
45
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
46
+ - if: ${{ '{{GATE_RUNTIME}}' == 'node' }}
47
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
48
+ with: { node-version: 24, cache: npm, cache-dependency-path: {{GATE_CACHE_DEP_PATH}} }
49
+ - if: ${{ '{{GATE_RUNTIME}}' == 'python' }}
50
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
51
+ with: { python-version: '{{GATE_PY_VERSION}}' }
52
+ # MMI-Hub#3446: assert the runtime toolchain is on PATH BEFORE the install step. A runner whose
53
+ # node/npm (or python) is missing, or whose setup step raced, fails `{{GATE_INSTALL_CMD}}` with a
54
+ # bare `command not found` (exit 127) that reads like a broken diff and abandons a correct PR in an
55
+ # autonomous merge loop. This names the RUNNER instead — a distinguishable infra failure that
56
+ # `mmi-cli pr checks-wait` classifies as rerunnable (title `CI runner toolchain`), mirroring the
57
+ # disk (#3366) and browser (#808) preflights. No test ran; the diff is not implicated.
58
+ - name: Toolchain preflight
59
+ if: ${{ '{{GATE_RUNTIME}}' == 'node' }}
60
+ run: |
61
+ node -v && npm -v || { echo "::error title=CI runner toolchain::RUNNER NOT PROVISIONED — node/npm not on PATH after setup-node. This is the runner, not your diff; no install or test ran. Re-run the job (a fresh lane usually clears it); if it persists the mmi-runner node toolchain needs attention (docs/Guides/gh-runner-runbook.md in MMI-Hub)."; exit 1; }
62
+ - name: Toolchain preflight
63
+ if: ${{ '{{GATE_RUNTIME}}' == 'python' }}
64
+ run: |
65
+ python3 --version || { echo "::error title=CI runner toolchain::RUNNER NOT PROVISIONED — python3 not on PATH after setup-python. This is the runner, not your diff; no install or test ran. Re-run the job; if it persists the mmi-runner python toolchain needs attention (docs/Guides/gh-runner-runbook.md in MMI-Hub)."; exit 1; }
66
+ - run: {{GATE_INSTALL_CMD}}
67
+ # #3178: the check runs under the org wall-clock budget — a hung suite dies at the ceiling instead
68
+ # of squatting a runner lane for GitHub's 6h default. ci-audit + the release train enforce this step.
69
+ - uses: mutmutco/MMI-Hub/.github/actions/run-with-budget@{{GATE_BUDGET_SHA}}
70
+ with:
71
+ command: {{GATE_CMD}}
72
+ max-seconds: {{GATE_MAX_SECONDS}}
73
+ working-directory: {{GATE_WORKDIR}}
74
+ # MMI-Hub#3329: the deterministic doc ref-gate — every file:line ref, command name,
75
+ # relative link, and pin comment in docs/** + README.md + architecture.md must resolve.
76
+ # This is the gate that makes the docs-janitor's unattended write surface safe (topology D,
77
+ # MMI-Hub epic #3325). Fleet-portable via the released CLI; runs from the repo root.
78
+ # MMI-Hub#3406: check the GENERATED index before resolving refs. docs/index.md is produced by
79
+ # `mmi-cli docs index --write`, and a stale one silently re-hosts child docs' relative links and
80
+ # backticked paths at the index's own depth — where they no longer resolve. Every finding it
81
+ # causes points at docs/index.md, so the ref-gate blames the artifact while the real fault is
82
+ # that nobody regenerated it. Worse, a copied `../../x.md` can escape the repo root, which used
83
+ # to crash the ref-gate outright rather than report (fixed in 3.44.0). Checking staleness first
84
+ # names the actual cause and the one-command fix.
85
+ - name: Doc index freshness
86
+ run: npx -y @mutmutco/cli@latest docs index --check
87
+ working-directory: '.'
88
+ - name: Doc ref-gate
89
+ run: npx -y @mutmutco/cli@latest docs refs
90
+ working-directory: '.'
@@ -0,0 +1,33 @@
1
+ # Google login — {{REPO_NAME}}
2
+
3
+ This repo has a Google OAuth client provisioned by the org — one client spanning local/`/stage`, dev, rc, and
4
+ prod. Adding Google login here is **self-serve**: you do not need master-admin help.
5
+
6
+ ## Reach the creds (from SSM — never in git, never printed)
7
+ ```bash
8
+ # Confirm they resolve for your repo (names only, no value):
9
+ mmi-cli secrets list
10
+ # Consume them keyless in a command — injected into its env, never printed (raw `secrets get` was removed, #2844):
11
+ mmi-cli secrets use GOOGLE_CLIENT_ID -- <cmd>
12
+ mmi-cli secrets use GOOGLE_CLIENT_SECRET -- <cmd>
13
+ ```
14
+ The canonical keys are the stageless `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` pair at the project vault
15
+ root. The project-admin can manage them for their own repo; runtime and CI read them keylessly. Never bake a secret into an
16
+ image or commit it. The remote fileless deploy writes no release `.env`; **do not commit or hand-edit a `.env`**.
17
+ The only `.env` you may create is the gitignored one `/stage` makes from `.env.example` for local dev.
18
+
19
+ ## The one rule that makes every environment work
20
+ Build the OAuth `redirect_uri` from the **incoming request** — never a hardcoded base URL:
21
+ - callback path: `/api/auth/callback`
22
+ - derive scheme + host from `X-Forwarded-Proto` / `X-Forwarded-Host` (set by the Caddy proxy), falling back
23
+ to the `Host` header.
24
+
25
+ The client's loopback redirect URIs are registered **port-agnostic**, so any local port works; dev/rc/prod
26
+ URIs are registered for both `mutatismutandis.co` and `mutmut.co`, so the deploy train works unchanged.
27
+
28
+ ## Reference implementation + full guide
29
+ Inspect this repo's expected URIs and confirm the client is port-agnostic:
30
+ ```bash
31
+ mmi-cli org oauth plan # the canonical JS origins + redirect URIs + SSM cred params
32
+ mmi-cli org oauth verify # probes an arbitrary :9123 loopback — no redirect_uri_mismatch = good
33
+ ```
@@ -0,0 +1,26 @@
1
+ {
2
+ "_comment": "Bootstrap seed manifest (#201) — the machine-readable contract of what /bootstrap and `mmi-cli bootstrap --apply` (#202) stamp into a target repo. Consumed by the CLI (loadBootstrapSeeds). ownership: 'org' = org-delivered, OVERWRITTEN on upgrade (the org owns it); 'repo' = created ONCE on a fresh bootstrap, never clobbered on upgrade (the repo owns its content). source: 'self' = copy MMI-Hub's own current file verbatim; 'seed:<file>' = render the named template in this dir with {{PLACEHOLDERS}}; 'managed-block' = merge the org-managed .gitignore block in place (preserves the repo's own ignore lines) — this is how the org-managed .gitignore block reaches every repo now that the fanout pipeline is retired (Hub#3010); the doctor SessionStart heal keeps it current thereafter. NOTE: this manifest seeds org-managed PRODUCT assets only — it never seeds AGENTS.md / CLAUDE.md / .claude/settings.json (personal agent guides) or a legacy repo-local control-plane marker. classes: which repo classes receive this seed.",
3
+ "placeholders": ["OWNER", "REPO", "REPO_SLUG", "REPO_NAME", "CLASS", "GATE_CMD", "GATE_PUSH_BRANCHES_YAML", "GATE_FULL_RUN_BRANCH", "GATE_RULESET_BRANCH_REFS_JSON", "PROJECT_OWNER", "PROJECT_NUMBER", "PROJECT_ID", "STATUS_FIELD_ID", "STATUS_TODO", "STATUS_IN_PROGRESS", "STATUS_IN_REVIEW", "STATUS_DONE", "STACK", "REGION"],
4
+ "seeds": [
5
+ { "target": ".github/ISSUE_TEMPLATE/bug.yml", "source": "self", "ownership": "org", "classes": ["deployable", "content"] },
6
+ { "target": ".github/ISSUE_TEMPLATE/feature.yml", "source": "self", "ownership": "org", "classes": ["deployable", "content"] },
7
+ { "target": ".github/ISSUE_TEMPLATE/task.yml", "source": "self", "ownership": "org", "classes": ["deployable", "content"] },
8
+ { "target": ".github/ISSUE_TEMPLATE/config.yml", "source": "self", "ownership": "repo", "classes": ["deployable", "content"] },
9
+ { "target": "scripts/next-version.mjs", "source": "self", "ownership": "org", "classes": ["deployable"] },
10
+ { "target": ".github/workflows/gate.yml", "source": "seed:gate.template.yml", "ownership": "org", "classes": ["deployable"] },
11
+ { "target": ".github/workflows/agent-pr.yml", "source": "self", "ownership": "org", "classes": ["deployable"] },
12
+ { "target": ".github/rulesets/mmi-product-required-checks.json", "source": "seed:mmi-product-required-checks.template.json", "ownership": "org", "classes": ["deployable"] },
13
+ { "target": ".gitignore", "source": "managed-block", "ownership": "org", "classes": ["deployable", "content"] },
14
+ { "target": "README.md", "source": "seed:README.template.md", "ownership": "repo", "classes": ["deployable", "content"] },
15
+ { "target": "architecture.md", "source": "seed:architecture.template.md", "ownership": "repo", "classes": ["deployable", "content"] },
16
+ { "target": "docs/decisions/README.md", "source": "seed:decisions-readme.template.md", "ownership": "repo", "classes": ["deployable", "content"] },
17
+ { "target": "docs/Guides/google-login.md", "source": "seed:google-login.template.md", "ownership": "repo", "classes": ["deployable"], "projectTypes": ["web-app"] },
18
+ { "target": "docker-compose.yml", "source": "seed:docker-compose.template.yml", "ownership": "repo", "classes": ["deployable"], "deployModels": ["tenant-container"] },
19
+ { "target": "Dockerfile", "source": "seed:Dockerfile.template", "ownership": "repo", "classes": ["deployable"], "deployModels": ["tenant-container"] }
20
+ ],
21
+ "labels": [
22
+ { "name": "bug", "color": "d73a4a", "description": "Something is broken or behaving wrong" },
23
+ { "name": "feature", "color": "a2eeef", "description": "New capability or enhancement" },
24
+ { "name": "task", "color": "0052cc", "description": "Task, chore, or improvement" }
25
+ ]
26
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "_comment": "Repository-level ruleset requiring the product gate job (#1333). Apply via GitHub repo rulesets (master-admin) after bootstrap seeds gate.yml — the job name gate must match this context.",
3
+ "name": "mmi-product-required-checks",
4
+ "target": "branch",
5
+ "enforcement": "active",
6
+ "conditions": {
7
+ "ref_name": {
8
+ "include": {{GATE_RULESET_BRANCH_REFS_JSON}},
9
+ "exclude": []
10
+ }
11
+ },
12
+ "rules": [
13
+ {
14
+ "type": "required_status_checks",
15
+ "parameters": {
16
+ "strict_required_status_checks_policy": false,
17
+ "required_status_checks": [
18
+ { "context": "gate" }
19
+ ]
20
+ }
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: browser-automation
3
+ description: Use DOM-first Playwright MCP for browser work.
4
+ ---
5
+
6
+ # Browser automation — DOM-first Playwright MCP
7
+
8
+ Org standard for agent browser work on Claude Code. **Playwright** is the engine; agents interact through **structure-first** MCP tools, not pixels-first defaults.
9
+
10
+ ## Doctrine (non-negotiable)
11
+
12
+ 1. **Accessibility tree first** — semantic structure the agent can reason about (`browser_snapshot`, a11y refs).
13
+ 2. **DOM second** — selectors, snapshots, network when the tree is not enough.
14
+ 3. **Vision last** — screenshots only when tree + DOM cannot answer the question.
15
+ 4. **Prefer HTTP/OpenAPI** — call APIs directly when discovery or the task allows; do not drive UI for data you can fetch.
16
+
17
+ **Never** pass `--caps=vision` (or equivalent vision-first defaults) on Playwright MCP org-wide. Vision caps burn tokens, hide structure, and break on theme/layout drift.
18
+
19
+ ## When to use what
20
+
21
+ | Need | Use |
22
+ |------|-----|
23
+ | Local dev server + smoke on current branch | **`/stage`** — gitignored stack under `tmp/stage/`; see `skills/stage/SKILL.md` |
24
+ | Personal cloud dev preview of your branch | **`/stage --live`** — IP-gated dev stage; not rc/prod |
25
+ | Interactive UI debug, one-off flow, agent-driven clicks | **Playwright MCP** (this skill) — DOM-first, artifacts under `tmp/` |
26
+ | Durable hosted automation outside dev machines | **Stagehand + Browserbase** (production path) — explicit choice, not the default for every local task |
27
+
28
+ `/stage` and Playwright MCP **complement** each other. `/stage` spins the app; MCP drives the browser against a URL (often the stage URL).
29
+
30
+ ## MCP configuration (no vision)
31
+
32
+ ### Claude Code
33
+
34
+ Enable the official Playwright plugin (`playwright@claude-plugins-official`) via `/plugin`. Follow its DOM-first tools; do not enable vision-first modes for routine agent work. Point MCP output at `tmp/playwright-mcp` when the server accepts `--output-dir`.
35
+
36
+ Editor-host MCP configs (Cursor `.cursor/mcp.json`, Codex `config.toml`) are retired org surfaces (#2741/#2808) — bootstrap no longer seeds them; do not reintroduce them.
37
+
38
+ ## Playwright availability
39
+
40
+ Check the configured/global CLI before adding a temporary local dependency. On Windows PowerShell:
41
+
42
+ ```powershell
43
+ Get-Command playwright
44
+ playwright --version
45
+ ```
46
+
47
+ `node -e "require.resolve('playwright')"` only proves a Node module is installed in the current package; it
48
+ can fail while the global or editor-configured Playwright CLI works. Use the available CLI for smoke checks
49
+ and MCP setup. Temporary per-worktree installs are fallback-only, and should stay untracked.
50
+
51
+ ## Agent workflow (MCP)
52
+
53
+ 1. **Goal** — what observable outcome proves success?
54
+ 2. **Navigate** — open the target URL (often from `/stage` JSON: `mmi-cli stage --json`).
55
+ 3. **Snapshot** — a11y tree / DOM snapshot before interacting.
56
+ 4. **Act** — click, type, select using refs from the latest snapshot.
57
+ 5. **Re-snapshot** after navigation or major DOM changes (refs go stale).
58
+ 6. **Vision only if stuck** — one screenshot to disambiguate; then return to tree/DOM.
59
+
60
+ Core MCP loop:
61
+
62
+ ```
63
+ browser_navigate → browser_snapshot → browser_click / browser_type → browser_snapshot
64
+ ```
65
+
66
+ ## Artifacts and hygiene
67
+
68
+ - **All Playwright MCP output → `tmp/playwright-mcp/`** (pass `--output-dir tmp/playwright-mcp` when the MCP server supports it).
69
+ - **Never** leave traces, screenshots, or reports at the repo root.
70
+ - `.playwright-mcp/` at repo root is gitignored as a **safety net only** — not the canonical path.
71
+ - The housekeeping gate refuses tracked browser artifacts (`.playwright-mcp/`, `playwright-report/`, `test-results/`).
72
+
73
+ ## Anti-patterns (org-wide avoid)
74
+
75
+ - `--caps=vision` or screenshot-first wrappers for routine tasks
76
+ - Skyvern, Magnitude, LaVague, or other vision-first agent browsers as org defaults
77
+ - Committing `.playwright-mcp/`, `playwright-report/`, or `test-results/` from agent runs
78
+ - Replacing `/stage` with ad-hoc MCP servers for branch smoke (use `/stage` for the stack, MCP for the browser)
79
+
80
+ ## Related
81
+
82
+ - **`/stage`** — `skills/stage/SKILL.md`
83
+ - **`/grind`** (optional external tool) — use DOM-first browser checks in verification when criteria need UI proof
84
+
85
+ ## Retro — one check before you finish
86
+
87
+ Before your final report, answer one question honestly: did **this skill's own instructions** misfire
88
+ this run — ambiguous wording, a misleading MCP snippet, or an artifact path it should have warned
89
+ about? (Process only — never the user's code or task.) If yes, file **one** lesson and move on; a clean run is
90
+ silent (hard cap: one per run). It lands on the Hub board (deduped) and is fixed only via a reviewed PR —
91
+ never edit the skill live; the retro is advisory, so if the call fails, note it and continue:
92
+
93
+ `mmi-cli skill-lesson --skill browser-automation --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: doctor
3
+ description: One hygiene pass — board drift fix, secrets diff, stale-worktree sweep, and plugin-heal.
4
+ ---
5
+
6
+ # /doctor — one hygiene pass
7
+
8
+ A single sweep that clears the residue a working repo accumulates: board invariant drift, secret-catalog
9
+ gaps, merged/closed worktrees and branches left behind, and a stale plugin/CLI. Run it when a session
10
+ opens messy or before a handoff. Each step wraps a real `mmi-cli` command — inspect first, fix on a go.
11
+
12
+ ## Step 0 — toolchain integrity
13
+
14
+ ```bash
15
+ mmi-cli doctor --self
16
+ ```
17
+
18
+ Checks CLI/plugin version parity against the published version, and that the active `gh` token can
19
+ actually resolve this repo. It reads npm and GitHub, so it is not offline-safe. It does not check PATH or
20
+ hook wiring — no such check exists (#3485). On a hard gap:
21
+
22
+ ```bash
23
+ mmi-cli plugin heal # reinstall + re-enable the MMI plugin; then restart Claude Code / reopen the workspace
24
+ ```
25
+
26
+ ## Step 1 — board drift
27
+
28
+ ```bash
29
+ mmi-cli board doctor # detect: transfer ghosts, closed-not-Done, assignee/status mismatch, stray priority:* labels
30
+ mmi-cli board doctor --fix # apply the automatic fixes once the findings look right
31
+ ```
32
+
33
+ `board doctor` (no `--fix`) exits nonzero when it finds drift and prints each finding. Review, then re-run
34
+ with `--fix` to apply. Never hand-move a board item — the fixer does the mechanical writes.
35
+
36
+ ## Step 2 — secret-catalog diff (deployable repos)
37
+
38
+ ```bash
39
+ mmi-cli secrets diff --stage dev # required-vs-vault gap + catalog drift; values never shown
40
+ ```
41
+
42
+ Runs the project-side view: declared-missing / orphan / off-scheme secrets for a stage, before any deploy.
43
+ Repeat `--stage rc` / `--stage main` for a repo that promotes. A clean diff exits 0. **Values are never
44
+ printed** — this only names keys. Skip for a repo with no runtime-secret contract.
45
+
46
+ ## Step 3 — stale worktree + branch sweep
47
+
48
+ ```bash
49
+ mmi-cli worktree gc # dry-run (default): merged/closed-PR local+remote branches, linked worktrees, stale refs
50
+ mmi-cli worktree gc --apply # remove only the listed clean items
51
+ mmi-cli worktree gc sweep-deferred # retry any IDE-locked worktree removals queued from a prior land
52
+ ```
53
+
54
+ `gc` inspects merged/closed PRs and lists exactly what is safe to delete; `--apply` removes only those. It
55
+ never touches a branch with an open PR. Pair with `mmi-cli wave status` to see worktrees, open PRs, and
56
+ local stages at a glance before sweeping.
57
+
58
+ ## Step 4 — report
59
+
60
+ One line per step: toolchain OK/healed, board findings fixed, secret gaps by stage, worktrees/branches
61
+ swept. Name anything that needs a human decision (an unowned drift, a secret only the master can grant).
62
+
63
+ ## Notes
64
+
65
+ - `/doctor` is the hygiene pass; `/resume` is the lighter read-only session open. Reach for `/doctor` when
66
+ the repo is messy, not on every session.
67
+ - `secrets diff` and `board doctor` read live state — never cache their output; re-run to confirm a fix.
68
+
69
+ ## Retro — one check before you finish
70
+ Before your final report, answer one question honestly: did **this skill's own instructions** misfire
71
+ this run — ambiguous wording, a misleading message, or an environment failure it should have warned
72
+ about? (Process only — never the user's code or task; e.g. a `gc` dry-run that proposed deleting a live
73
+ branch, or a secrets diff that flagged a key that is present.) If yes, file **one** lesson and move on; a
74
+ clean run is silent (hard cap: one per run). It lands on the Hub board (deduped) and is fixed only via a
75
+ reviewed PR — never edit the skill live; the retro is advisory, so if the call fails, note it and continue:
76
+ `mmi-cli skill-lesson --skill doctor --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: epic
3
+ description: Decompose a vision or umbrella issue into linked child issues via one batch create.
4
+ ---
5
+
6
+ # /epic — decompose an umbrella into children
7
+
8
+ Turn one large item — a vision issue, an epic, an umbrella issue — into a set of native sub-issues in a
9
+ single pre-validated batch, each already linked to its parent. This is the slice-and-fan-out act done by
10
+ hand today: draft the children, validate them all, create them, confirm the tree.
11
+
12
+ ## Step 0 — load the umbrella whole
13
+
14
+ Read the parent end-to-end before slicing — body **and every comment**, treating later comments as
15
+ superseding:
16
+
17
+ ```bash
18
+ mmi-cli board show <owner/repo#N> # status, body, and every comment for the umbrella
19
+ ```
20
+
21
+ Slice by deliverable, not by phase: each child must be independently claimable and land in its own PR.
22
+ Keep the parent as the umbrella — do not close it until the last child merges.
23
+
24
+ ## Step 1 — draft the batch file
25
+
26
+ Write a JSON array (one object per child) to a scratch path under `tmp/`. Each row:
27
+
28
+ ```json
29
+ [
30
+ { "type": "task", "title": "C1: extract the shared frame", "body": "…", "priority": "high",
31
+ "parent": "owner/repo#42" },
32
+ { "type": "feature", "title": "C2: wire the new command", "body": "…", "priority": "medium",
33
+ "parent": "owner/repo#42" }
34
+ ]
35
+ ```
36
+
37
+ - `type` — `bug` · `feature` · `task` (required; maps to the repo's issue-template label).
38
+ - `title` — required, non-empty; keep it a short, greppable deliverable.
39
+ - `parent` — the umbrella ref (`#N`, `owner/repo#N`, or URL); links each child as a native sub-issue on
40
+ create, so you do not need a separate `link-child` pass. Cross-repo is fine (a Hub umbrella can parent
41
+ product-repo children).
42
+ - `priority` — `urgent|high|medium|low` (defaults to `medium`); sets the board Priority **field**.
43
+
44
+ The batch **pre-validates every row before creating any** — one bad row fails the whole set with an
45
+ aggregate error, so you fix all of them once. Get the user's go on the drafted set before writing.
46
+
47
+ ## Step 2 — create the children
48
+
49
+ ```bash
50
+ mmi-cli issue create --type task --batch tmp/epic-children.json
51
+ ```
52
+
53
+ `--type` is required by the create command but each row's own `type` governs; pass any valid type as the
54
+ placeholder. It prints per-row `{number,url}` results and fails loud on any misfire. Add
55
+ `--idempotency-key <key>` when a retried loop must not duplicate.
56
+
57
+ ## Step 3 — confirm the tree
58
+
59
+ ```bash
60
+ mmi-cli issue children <owner/repo#N> # each child: number/title/state/repo/boardStatus/linkedPrs
61
+ ```
62
+
63
+ Verify every intended child is linked and on the board as Todo. To link a child that already existed (not
64
+ part of the batch), use the inverse-friendly single link:
65
+
66
+ ```bash
67
+ mmi-cli issue link-child <parent> <child>
68
+ ```
69
+
70
+ Each child is now a parallel item — fan them out one worktree + PR each. **When the last child merges,
71
+ close the umbrella** (its board `Done` follows automatically).
72
+
73
+ ## Notes
74
+
75
+ - Native sub-issues, not a body task-list: the parent renders a sub-issue checklist and each child renders
76
+ its parent — nothing to hand-maintain.
77
+ - Never free-type children with raw `gh issue create` — the batch path carries validation, board attach,
78
+ and structured output.
79
+
80
+ ## Retro — one check before you finish
81
+ Before your final report, answer one question honestly: did **this skill's own instructions** misfire
82
+ this run — ambiguous wording, a misleading message, or an environment failure it should have warned
83
+ about? (Process only — never the user's code or task; e.g. a batch schema that rejected a valid row, or a
84
+ link that attached to the wrong parent.) If yes, file **one** lesson and move on; a clean run is silent
85
+ (hard cap: one per run). It lands on the Hub board (deduped) and is fixed only via a reviewed PR — never
86
+ edit the skill live; the retro is advisory, so if the call fails, note it and continue:
87
+ `mmi-cli skill-lesson --skill epic --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: hotfix
3
+ description: Promote an already-merged development fix to main and production through the gated Hub train.
4
+ ---
5
+
6
+ # /hotfix — promote a development fix to main + prod
7
+
8
+ A hotfix is promotion, not authoring. The fix must land on `development` through a normal issue,
9
+ worktree, PR, review, and CI gate first. Hub then ports that merged PR or SHA to a main-base hotfix PR,
10
+ preserves the cherry-pick audit trail, and performs the PATCH release. Never author directly from `main`.
11
+ Never author the fix on a branch off `main`. The main-base branch is only the orchestrated port of a fix
12
+ that is already merged to `development`.
13
+
14
+ There is no back-merge: `development` already contains the fix, and `rc` absorbs it at the next `/rcand`.
15
+ The release hotfix-coverage guard blocks a later candidate that omits the production fix.
16
+
17
+ ## Merge floor (#3167 — non-negotiable)
18
+
19
+ - **Never squash-merge a tagged commit.** The hotfix PR itself may squash (step 2 — the tag lands *after*,
20
+ on the merged `main` HEAD, and the `-x` trailer must survive the squash message). But any merge that
21
+ carries an already-tagged commit — an alignment PR, a later `main → development` roll-forward — lands as a
22
+ true merge, never squash: a squash re-mints the SHA and orphans the tag from the branch lineage.
23
+ - **A refused release train is a stop, never a license to finish by hand.** A conflict on the port, a red
24
+ authority probe, a failed required check, a refused `hotfix release` — each ends the run. Fix the cause on
25
+ `development` through a normal PR and re-run the orchestrator; never hand-cherry-pick, bare-push, or
26
+ bypass the gate to finish.
27
+ - **Version probes anchor on the latest Release tag, not a branch.** `hotfix status` derives the PATCH from
28
+ the latest Release tag; branch manifests and stale local tags are not version sources.
29
+
30
+ ## Authority and preflight
31
+
32
+ Production changes require the authorized human's explicit approval in the current turn. Verify authority
33
+ and CLI health before starting:
34
+
35
+ ```bash
36
+ mmi-cli org access role <owner/repo> --json
37
+ mmi-cli doctor --apply --no-repo-writes
38
+ ```
39
+
40
+ Stop on a red authority or CLI-version result. The worktree must be clean; move scratch into `tmp/` or
41
+ gitignore it rather than widening the hotfix diff.
42
+
43
+ ## 1. Start from the merged development fix
44
+
45
+ Use the orchestrator with an explicit source every time:
46
+
47
+ ```bash
48
+ mmi-cli hotfix start --from <development-pr-number-or-merge-sha> --json
49
+ ```
50
+
51
+ `hotfix start` resolves the PATCH version, branches from `origin/main`, performs the cherry-pick with `-x`,
52
+ prepares Hub distribution artifacts when applicable, pushes the branch, and opens the main-base
53
+ PR. Do not duplicate those steps with raw branch commands, manual cherry-picks, or raw GitHub PR creation.
54
+
55
+ If the port conflicts, stop and report the conflict. Any behavior change needed to resolve it lands on
56
+ `development` first through another normal PR, then starts another hotfix port from that merged fix.
57
+
58
+ ## 2. Verify the hotfix PR
59
+
60
+ Run the repo's local gate against the hotfix branch, then obtain the independent reviewer required by the
61
+ active agent doctrine. Review the actual main-base diff and the original issue acceptance criteria.
62
+
63
+ Wait for required CI through Hub:
64
+
65
+ ```bash
66
+ mmi-cli pr checks-wait <hotfix-pr-number>
67
+ mmi-cli pr merge <number> --squash
68
+ ```
69
+
70
+ The main-base PR is the production gate. Do not bypass checks or protected-branch authority. After the
71
+ authorized merge, verify the merged main commit still carries the cherry-pick provenance; if the PR was
72
+ squashed, the source trailer must survive in the squash message so future coverage checks remain exact.
73
+ Because Hub's default branch is `development`, the main-base hotfix PR does not close a separate tracking
74
+ issue. The development PR should already have closed the work item; do not add raw GitHub issue operations.
75
+
76
+ ## 3. Run the gated release
77
+
78
+ Derive the tag from `mmi-cli hotfix status`, then release with the same declared source:
79
+
80
+ ```bash
81
+ mmi-cli hotfix status
82
+ mmi-cli hotfix release <vX.Y.Z> --carries <development-pr-number-or-merge-sha>
83
+ ```
84
+
85
+ For MMI-Hub, pass a fresh 2-4 line neutral summary file with `--announce-summary-file`; never reuse a
86
+ stale file and never put a product or brand name in the summary. Hub release scope never includes another
87
+ repo's board or `ds-propagate.yml`. The orchestrator creates the tag and GitHub Release, selects the
88
+ registry-declared deploy path, watches the release-triggered or central deployment, verifies distribution,
89
+ and announces best-effort. Do not hand-dispatch a second publish/deploy path: duplicate release events can
90
+ race or double-publish.
91
+
92
+ For a private package, trust the authenticated publish job and its logged package/version result; a bare
93
+ unauthenticated `npm view` cannot distinguish private from missing.
94
+
95
+ ## 4. Verify and report
96
+
97
+ Report the tag and Release URL, production run and URL, source development PR/SHA, hotfix PR, and these
98
+ branch facts:
99
+
100
+ - `main`: the tag commit is on `origin/main`.
101
+ - `development`: the source fix was already merged before the hotfix began.
102
+ - `rc`: intentionally untouched; the next release coverage gate prevents regression.
103
+
104
+ Do not open a manifest-alignment or back-merge PR. This is explicitly NOT a back-merge: the next normal
105
+ release folds version manifests and branch alignment.
106
+
107
+ ## Retro
108
+
109
+ If this skill's instructions themselves misfired, file one deduplicated lesson and continue:
110
+
111
+ ```bash
112
+ mmi-cli skill-lesson --skill hotfix --title "<what misfired>" --body "<what; evidence; proposed amendment>"
113
+ ```