@mutmutco/claude-plugin 4.5.160 → 4.5.162
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/.claude-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +226 -100
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/skills/board/SKILL.md +3 -20
- package/skills/board/examples.md +12 -0
- package/skills/board/reference.md +11 -0
- package/skills/bootstrap/SKILL.md +5 -418
- package/skills/bootstrap/reference.md +421 -0
- package/skills/hotfix/SKILL.md +2 -4
- package/skills/hotfix/recovery.md +4 -0
- package/skills/hotfix/suite.md +2 -0
- package/skills/org-guide/SKILL.md +1 -1
- package/skills/org-guide/references/work-and-releases.md +21 -1
- package/skills/rcand/SKILL.md +2 -2
- package/skills/rcand/recovery.md +2 -0
- package/skills/rcand/suite.md +2 -0
- package/skills/release/SKILL.md +6 -10
- package/skills/release/suite.md +5 -0
- package/skills/release/vercel.md +2 -0
- package/skills/release/verification.md +7 -0
- package/skills/secrets/SKILL.md +3 -64
- package/skills/secrets/reference.md +67 -0
- package/skills/stage/SKILL.md +4 -96
- package/skills/stage/live.md +34 -0
- package/skills/stage/reference.md +49 -0
- package/skills/stage/smoke.md +17 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
`deployModel: vercel` (on either track): the push to `main` is the go-live — Vercel builds `main` itself. The train dispatches nothing; with `--watch` it waits for the **Production** GitHub Deployment the Vercel GitHub app posts for the release SHA, probes the served URL once, and announces once it is green. Unwatched or timed out, the deploy leg stays `pending` and settles on `release --resume` or the next doctor `--heal`, which re-read the Deployment. No version-file bump on a vercel repo — the tag is the version. The receipt's `workflowRuns` carries a `vercel` row with the Vercel log URL; `pending` with "is the Vercel GitHub app connected?" means no Deployment was ever posted — connect the app, never re-tag.
|
|
2
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
For the independent run recheck, scope the read to the release window, so a busy repo's unrelated runs cannot fill the cap: note the UTC instant you started `--apply` (`date -u +%Y-%m-%dT%H:%M:%SZ`), then run `gh run list --repo {owner}/{repo} --created ">=<apply-start-utc>" --limit 100 --json databaseId,headSha,workflowName,status,conclusion,url > .jerv/tmp/release-runs.json`, then filter locally by the exact SHA from the saved receipt with `node -e 'const rows = require("./.jerv/tmp/release-runs.json"); const sha = process.argv[1]; const matches = rows.filter((run) => run.headSha === sha); if (rows.length >= 100 || !matches.length) throw new Error("release run set is incomplete or absent"); console.log(JSON.stringify(matches, null, 2));' "<release-sha>"`.
|
|
2
|
+
|
|
3
|
+
Do not use the raw `releases/latest` API route, a `--jq` formatter, or `gh run list --commit`; if the bounded list reaches 100 rows or has no SHA match, the run set is unverified and must not be called green.
|
|
4
|
+
|
|
5
|
+
- A `private` npm surface (`surfaces.json`): the doctor's `npm-token-rejected` finding comes first. A 401 from `npm whoami` through the `_org` `npm/NPM_TOKEN` vault hop means the token is rejected, and every authenticated `npm view` then 404s exactly like an absent package — rotate the token; only after a login is a restricted 404 "unverifiable from here", never "not published" (`publish-private-package`). On a repo whose workflows publish through Trusted Publishing and name no registry token, that row is `info`, not a warning: no lane consumes the org token, so it constrains your manual read only.
|
|
6
|
+
|
|
7
|
+
- `served-channel(<product>)` row — the release's proof that new installs get it: the public `/release/version` pointer of the releasing repo's OWN channel (the Hub's `mmi`, or the product its registry `installer` declaration names; no declaration → no row), read after deploy and publish are green. `success` names the version read. `failure` is either a channel still on the previous version or a stale served process (the route answers 401/404): the note names what moves that channel and the exact remedy; run it, then re-read the pointer. `pending` means not probed (legs not green) or unreadable, never proof. The row is receipt evidence only, never a ledger leg, so it never blocks the next train.
|
package/skills/secrets/SKILL.md
CHANGED
|
@@ -23,12 +23,7 @@ SecureString + KMS, and **a value is never echoed to chat or logs**):
|
|
|
23
23
|
A project-admin reaches one of these only via a master **grant**; the master is unrestricted (master ⊇
|
|
24
24
|
project-admin).
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
key. `mmi-cli vault secrets grant <repo> <login> <key> --read` grants **consume-only** reach: keyless `use`
|
|
28
|
-
works, rotate and remove still refuse. Only a `--read` grant may name a **wildcard** key — `*` for the
|
|
29
|
-
whole namespace, `<provider>/*` for one provider group — so "may read every crown jewel" is one grant
|
|
30
|
-
instead of forty. A wildcard never confers write; asking for one as `rw` is refused, not narrowed.
|
|
31
|
-
`mmi-cli oracle org access capabilities` prints `grant (read)` or `grant (rw)` next to each name.
|
|
26
|
+
For org-infra grants (including read-only wildcards), read [reference.md](reference.md) before granting access.
|
|
32
27
|
|
|
33
28
|
A bare `<KEY>` is the **stageless canonical** at the slug root — one value every stage shares (#2244)
|
|
34
29
|
and the path deploys resolve (#2523). A staged `dev/<KEY>` is a **per-stage override** and WINS for that
|
|
@@ -86,65 +81,9 @@ mmi-cli vault secrets rm SCRAPER_API_KEY
|
|
|
86
81
|
**Never** pass a value as an argument (`secrets set KEY thevalue` is wrong — there is no value arg). The
|
|
87
82
|
confirmation prints the **name and tier only**, never the value.
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
newline, so an inline `node -e "<multiline script>"` after `--` reaches the child truncated and fails
|
|
91
|
-
before your code runs. Write the script to a **project-local ignored file** (e.g. `tmp/fetch-models.mjs`
|
|
92
|
-
— git-ignored, never tracked) and wrap the file instead; the key is still injected into the child's env:
|
|
84
|
+
On Windows, read [reference.md](reference.md) before wrapping a multiline command.
|
|
93
85
|
|
|
94
|
-
|
|
95
|
-
mmi-cli vault secrets use GEMINI_API_KEY -- node tmp/fetch-models.mjs
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Rotation checklist
|
|
99
|
-
|
|
100
|
-
Before rotating, enumerate every copy of the key so no tier stays stale:
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
mmi-cli vault secrets list --repo owner/Repo
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Check the bare canonical plus any `dev/`, `rc/`, `main/` overrides the list shows. Rotate the provider-side
|
|
107
|
-
key first, then write every declared coordinate that still needs that key. For keys with a provider probe
|
|
108
|
-
(`RECALL_API_KEY` today), `secrets set` validates the new value before printing success; `secrets verify
|
|
109
|
-
<KEY>` repeats the same probe later without printing the value. If the verifier fails, treat the rotation as
|
|
110
|
-
incomplete even if the vault write itself succeeded.
|
|
111
|
-
|
|
112
|
-
## Step 2 — org-infra elevation (master-only)
|
|
113
|
-
|
|
114
|
-
Your own repo's full tree (dev/rc/main) is already self-serve (#2032). The **org-infra** namespaces
|
|
115
|
-
(`shared`/`cloudflare`/`docs`/`mmi-hub`, every tier) stay master-only. A project-admin who needs one of
|
|
116
|
-
those keys asks the master, who grants a **scoped, auditable** standing access to that one key (or revokes
|
|
117
|
-
it). These verbs are **master-only** — the backend 403s anyone else.
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
# MASTER: let @oguz-mut consume one _org provider key from their MM-Chat project
|
|
121
|
-
mmi-cli vault secrets grant mutmutco/MM-Chat oguz-mut google/SOME_SHARED_KEY
|
|
122
|
-
# MASTER: withdraw it
|
|
123
|
-
mmi-cli vault secrets revoke mutmutco/MM-Chat oguz-mut google/SOME_SHARED_KEY
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
The master can also operate the org-infra key directly while guiding (master ⊇ project-admin). Org-infra
|
|
127
|
-
access by a project-admin **always originates from the master** — own-project access does not.
|
|
128
|
-
|
|
129
|
-
## Coordinate — where does a new project secret belong?
|
|
130
|
-
|
|
131
|
-
- Shared across stages → bare `<KEY>` at the project slug root (the usual canonical value).
|
|
132
|
-
- Genuinely stage-distinct → `<stage>/<KEY>` override for `dev`, `rc`, or `main`.
|
|
133
|
-
- The project-admin owns both shapes across their own project. A path under `_org`/shared infrastructure is
|
|
134
|
-
not a project coordinate and stays master-managed.
|
|
135
|
-
|
|
136
|
-
## Tier-to-tier copy (provider keys, #1433)
|
|
137
|
-
|
|
138
|
-
**Encryption / stage-distinct keys** (`*_ENC_KEY`, `SECRET_KEY_BASE`, etc.) must be **generated per stage** —
|
|
139
|
-
never copied. **Provider sandbox keys** (e.g. Recall/Gemini for Katip dev/rc) **may** be shared across dev/rc
|
|
140
|
-
when they point at the same sandbox project; prod should stay distinct when the provider contract requires it.
|
|
141
|
-
|
|
142
|
-
Sanctioned copy within the own-project vault (org-infra/cross-project sources remain master-gated):
|
|
143
|
-
```bash
|
|
144
|
-
mmi-cli vault secrets copy --from rc --to dev --keys RECALL_API_KEY,GEMINI_API_KEY
|
|
145
|
-
mmi-cli vault secrets copy --from rc --to dev --keys RECALL_API_KEY --dry-run # plan only
|
|
146
|
-
```
|
|
147
|
-
Prefer this over manual copy piping — audit-logged, blocklist enforced.
|
|
86
|
+
For rotation, org-infra elevation, new-key coordinates, or tier-to-tier copies, read [reference.md](reference.md) before the operation.
|
|
148
87
|
|
|
149
88
|
## Notes
|
|
150
89
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
**Grant scope (#3652).** A grant is `rw` by default — it opens both keyless `use` and `set`/`rm` on that
|
|
2
|
+
key. `mmi-cli vault secrets grant <repo> <login> <key> --read` grants **consume-only** reach: keyless `use`
|
|
3
|
+
works, rotate and remove still refuse. Only a `--read` grant may name a **wildcard** key — `*` for the
|
|
4
|
+
whole namespace, `<provider>/*` for one provider group — so "may read every crown jewel" is one grant
|
|
5
|
+
instead of forty. A wildcard never confers write; asking for one as `rw` is refused, not narrowed.
|
|
6
|
+
`mmi-cli oracle org access capabilities` prints `grant (read)` or `grant (rw)` next to each name.
|
|
7
|
+
|
|
8
|
+
**Windows: a multiline wrapped command must be file-backed (#6048).** `cmd.exe` truncates at the first
|
|
9
|
+
newline, so an inline `node -e "<multiline script>"` after `--` reaches the child truncated and fails
|
|
10
|
+
before your code runs. Write the script to a **project-local ignored file** (e.g. `tmp/fetch-models.mjs`
|
|
11
|
+
— git-ignored, never tracked) and wrap the file instead; the key is still injected into the child's env:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
mmi-cli vault secrets use GEMINI_API_KEY -- node tmp/fetch-models.mjs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Rotation checklist
|
|
18
|
+
|
|
19
|
+
Before rotating, enumerate every copy of the key so no tier stays stale:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
mmi-cli vault secrets list --repo owner/Repo
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Check the bare canonical plus any `dev/`, `rc/`, `main/` overrides the list shows. Rotate the provider-side
|
|
26
|
+
key first, then write every declared coordinate that still needs that key. For keys with a provider probe
|
|
27
|
+
(`RECALL_API_KEY` today), `secrets set` validates the new value before printing success; `secrets verify
|
|
28
|
+
<KEY>` repeats the same probe later without printing the value. If the verifier fails, treat the rotation as
|
|
29
|
+
incomplete even if the vault write itself succeeded.
|
|
30
|
+
|
|
31
|
+
## Step 2 — org-infra elevation (master-only)
|
|
32
|
+
|
|
33
|
+
Your own repo's full tree (dev/rc/main) is already self-serve (#2032). The **org-infra** namespaces
|
|
34
|
+
(`shared`/`cloudflare`/`docs`/`mmi-hub`, every tier) stay master-only. A project-admin who needs one of
|
|
35
|
+
those keys asks the master, who grants a **scoped, auditable** standing access to that one key (or revokes
|
|
36
|
+
it). These verbs are **master-only** — the backend 403s anyone else.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# MASTER: let @oguz-mut consume one _org provider key from their MM-Chat project
|
|
40
|
+
mmi-cli vault secrets grant mutmutco/MM-Chat oguz-mut google/SOME_SHARED_KEY
|
|
41
|
+
# MASTER: withdraw it
|
|
42
|
+
mmi-cli vault secrets revoke mutmutco/MM-Chat oguz-mut google/SOME_SHARED_KEY
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The master can also operate the org-infra key directly while guiding (master ⊇ project-admin). Org-infra
|
|
46
|
+
access by a project-admin **always originates from the master** — own-project access does not.
|
|
47
|
+
|
|
48
|
+
## Coordinate — where does a new project secret belong?
|
|
49
|
+
|
|
50
|
+
- Shared across stages → bare `<KEY>` at the project slug root (the usual canonical value).
|
|
51
|
+
- Genuinely stage-distinct → `<stage>/<KEY>` override for `dev`, `rc`, or `main`.
|
|
52
|
+
- The project-admin owns both shapes across their own project. A path under `_org`/shared infrastructure is
|
|
53
|
+
not a project coordinate and stays master-managed.
|
|
54
|
+
|
|
55
|
+
## Tier-to-tier copy (provider keys, #1433)
|
|
56
|
+
|
|
57
|
+
**Encryption / stage-distinct keys** (`*_ENC_KEY`, `SECRET_KEY_BASE`, etc.) must be **generated per stage** —
|
|
58
|
+
never copied. **Provider sandbox keys** (e.g. Recall/Gemini for Katip dev/rc) **may** be shared across dev/rc
|
|
59
|
+
when they point at the same sandbox project; prod should stay distinct when the provider contract requires it.
|
|
60
|
+
|
|
61
|
+
Sanctioned copy within the own-project vault (org-infra/cross-project sources remain master-gated):
|
|
62
|
+
```bash
|
|
63
|
+
mmi-cli vault secrets copy --from rc --to dev --keys RECALL_API_KEY,GEMINI_API_KEY
|
|
64
|
+
mmi-cli vault secrets copy --from rc --to dev --keys RECALL_API_KEY --dry-run # plan only
|
|
65
|
+
```
|
|
66
|
+
Prefer this over manual copy piping — audit-logged, blocklist enforced.
|
|
67
|
+
|
package/skills/stage/SKILL.md
CHANGED
|
@@ -26,33 +26,7 @@ up -d`, choose a free port from the registry range, and report the local URL (e.
|
|
|
26
26
|
The commands are shell-aware and `--apply` runs them cross-shell. Board, deploy, secret, and project registry
|
|
27
27
|
facts all live in the Hub registry — no repo-local control-plane file.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
committing them. A repo **without** `.env.example` stages vault-native: `mmi-cli stage --apply` resolves the
|
|
31
|
-
declared dev runtime secrets (registry `requiredRuntimeSecrets[dev]`) from the vault and injects them straight
|
|
32
|
-
into the compose **process environment**, which Compose interpolates the file with — no secret ever touches
|
|
33
|
-
disk. A repo that still ships `.env.example` keeps the legacy `.env` bootstrap for back-compat until its
|
|
34
|
-
compose migrates to passthrough; new repos should ship **no** `.env.example`.
|
|
35
|
-
|
|
36
|
-
**Runtime env reaches the container through the generated passthrough (#6345).** Interpolation is not
|
|
37
|
-
delivery: a container receives only what its own `environment:` declares. So `/stage` mirrors the box deploy —
|
|
38
|
-
it generates `tmp/stage/runtime-env.override.yml` (gitignored, **key names only**, values stay in the process
|
|
39
|
-
env) passing every runtime key through to each service the compose marks `labels: {"mmi.runtime-env": "true"}`,
|
|
40
|
-
and loads it beside `docker-compose.yml` for the whole stage. Mark the app service with that label; a repo
|
|
41
|
-
that hand-declares its variables needs nothing. Unmarked sidecars (db, cache) keep getting only what they
|
|
42
|
-
interpolate themselves. Never wrap an individual `docker compose` call in `mmi-cli vault secrets use` to work
|
|
43
|
-
around a missing value (#6344) — that value is scoped to the one child process it wraps, so the next `docker
|
|
44
|
-
compose logs`/`down` fails the same `required variable … is missing a value`. Declare the key in registry
|
|
45
|
-
`requiredRuntimeSecrets[dev]` and let `/stage` carry it across the whole lifecycle.
|
|
46
|
-
|
|
47
|
-
**Build-time secrets (#5381).** When META declares `requiredBuildSecrets` (e.g. Katip's
|
|
48
|
-
`NODE_AUTH_TOKEN=@github-packages-token` for `@mutmutco/example-ui` on GitHub Packages), `/stage` injects those
|
|
49
|
-
BuildKit ids into the **`docker compose build`** process env only — not into the running container. Central
|
|
50
|
-
deploy mints the packages sentinel from Actions `GITHUB_TOKEN`; a laptop cannot. Resolution order: existing
|
|
51
|
-
process env → stageless project vault secret under the BuildKit id → existing GitHub sign-in
|
|
52
|
-
(`GH_TOKEN`, `GITHUB_TOKEN`, or `gh auth token`). Package read access is still required and is enforced
|
|
53
|
-
by GitHub Packages during the build. Cloud containers whose GH_TOKEN is a proxy placeholder set MMI_GH_PAT to a fine-grained PAT (resource owner mutmutco, Organization → Members: read); mmi-cli prefers it. If every source is missing, `/stage` fails before the build.
|
|
54
|
-
Setup: [`docs/Guides/tenant-runtime.md`](../../docs/Guides/tenant-runtime.md) § Local `/stage`. Never commit
|
|
55
|
-
or print the PAT.
|
|
29
|
+
For vault/env passthrough or build-time secret setup, read [reference.md](reference.md) before running the stage.
|
|
56
30
|
|
|
57
31
|
## Step 0 — inspect the plan
|
|
58
32
|
|
|
@@ -101,22 +75,7 @@ their own stage on separate ports — you do not need to stop one before startin
|
|
|
101
75
|
keys on branch; use a distinct North Star slug per parallel grind or feature. Stage JSON/state records
|
|
102
76
|
the starting `cwd` plus git branch/commit when available.
|
|
103
77
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
When grinding or the user supplied **acceptance criteria** (from the issue body at Gate 1 — not
|
|
107
|
-
ad-hoc chat text), run a **Budget-routing panel** on observable stage signals before teardown:
|
|
108
|
-
|
|
109
|
-
1. **Panel** (parallel):
|
|
110
|
-
- **requirements-match** (budget tier) — does the staged URL/behavior meet the criteria?
|
|
111
|
-
- **runtime-health** (budget tier) — console errors, failed `healthUrl`, broken UI signals
|
|
112
|
-
*(smoke observability — not the grind `correctness` hard lens)*
|
|
113
|
-
- **tests-actually-test** (budget tier) — if Playwright ran, did it exercise the changed path?
|
|
114
|
-
2. **Confirm** — get an independent second model to verify the staged URL or behavior meets the acceptance criteria.
|
|
115
|
-
3. Feed the result back to the active loop or report to the human. A blocker
|
|
116
|
-
means the stage failed smoke — do not claim the grind criterion met.
|
|
117
|
-
This panel is **not** a security clearance — grind Phase 2 still runs the `security` hard lens.
|
|
118
|
-
|
|
119
|
-
Skip when `/stage` is ad-hoc preview with no criteria.
|
|
78
|
+
When grinding or issue acceptance criteria exist, read [smoke.md](smoke.md) and run its post-smoke panel before teardown.
|
|
120
79
|
|
|
121
80
|
## Step 2 — stop when done
|
|
122
81
|
|
|
@@ -132,64 +91,13 @@ from the original stage working directory. Stop re-fetches the declared dev runt
|
|
|
132
91
|
can interpolate the same file (`${POSTGRES_PASSWORD:?}`, `${PORT:?}`) — secrets never come from the state
|
|
133
92
|
file (#6351). A vault-native repo with no `.env` gets `PORT` defaulted to the bound stage port.
|
|
134
93
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
Project admins can deploy the **current branch** to their project's dev runtime without an IP
|
|
138
|
-
restriction. The CLI dispatches legacy gate cleanup, then the dev deploy through the Hub backend.
|
|
139
|
-
Cleanup removes only that project's old stage rules and creates no Cloudflare rules, so rule-slot
|
|
140
|
-
quotas do not block staging. It still reads Cloudflare to detect old gates; cleanup failures stay visible.
|
|
141
|
-
The stage is accessible from any IP after both workflows succeed. The app's own sign-in still applies.
|
|
142
|
-
No SSH from your machine; project authorization remains enforced by the Hub.
|
|
143
|
-
|
|
144
|
-
**Deploy-model preflight (#5466 / #5467).** `/stage --live` is **not** generally available. Read
|
|
145
|
-
`deployModel` first (`mmi-cli oracle org project get {owner}/{repo}` → `deployModel`, or the dry
|
|
146
|
-
`mmi-cli stage --live --json` refusal). It applies only to **`tenant-container`** repos (the same
|
|
147
|
-
model the Hub tenant-deploy + tenant-control gates require). **`registry-publish` is not applicable**
|
|
148
|
-
for live stages — nor are hub-serverless, solo-container, static-cdn, vercel (its preview URL is on the
|
|
149
|
-
plain `/stage` receipt), content, or none. For an
|
|
150
|
-
unsupported model the dry plan refuses **before** offering `--apply` / `--down`; do not invent a
|
|
151
|
-
tenant deploy.
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
mmi-cli stage --live # dry-run plan (refuses when deployModel is not tenant-container)
|
|
155
|
-
mmi-cli stage --live --apply # clear legacy gates + deploy without an IP restriction
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Tear it down when done — **only when `--apply` actually created a runtime**. This stops the runtime
|
|
159
|
-
without Cloudflare work:
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
mmi-cli stage --live --down --apply
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
If apply never landed (unsupported model, failed dispatch, or you never ran `--apply`), `--down` is a
|
|
166
|
-
**safe no-op** — do not promise teardown of a stage that was never created. Personal dev stages only —
|
|
167
|
-
rc/live environments still move exclusively through the promotion train.
|
|
94
|
+
For a personal cloud dev stage (`--live`), read [live.md](live.md) before offering, applying, or tearing it down.
|
|
168
95
|
|
|
169
96
|
## Step 3 — report
|
|
170
97
|
|
|
171
98
|
The stage URL, what's running (server + tools), the workspace path (`tmp/stage/`), and the teardown command.
|
|
172
99
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
- `/stage` is local — no AWS, no deploy, no board or version effect. The one cloud exception is
|
|
176
|
-
`--live`: an on-demand **dev** stage of your branch for **`tenant-container`** repos only, without
|
|
177
|
-
a stage IP restriction (above). Preflight `deployModel` before offering it; `registry-publish`
|
|
178
|
-
and other models have no live stage.
|
|
179
|
-
- Remote rc/live environments move only through `/rcand`, `/release`, and `/hotfix`.
|
|
180
|
-
- Everything is gitignored; `/stage` never produces a tracked change.
|
|
181
|
-
- **Playwright MCP output goes to `tmp/`**, never the repo root: if you drive the Playwright MCP server,
|
|
182
|
-
pass `--output-dir tmp/playwright-mcp` (or point its output there). `.playwright-mcp/` is kept gitignored
|
|
183
|
-
by the org `.gitignore` managed block (`mmi-cli doctor`) as a safety net, so a stray default capture is
|
|
184
|
-
never tracked.
|
|
185
|
-
- `tools[]` is declarative for now; stage hardening starts/stops the main configured process. Repos with
|
|
186
|
-
extra local services should encode them behind `stage.up` until a tool runner is added.
|
|
187
|
-
- **Stale Docker bundle:** the registry-derived Docker Compose default builds with `docker compose build
|
|
188
|
-
--no-cache` before `up`. If the browser still serves an old bundle, run `mmi-cli stage stop --apply`, rerun
|
|
189
|
-
`/stage`, then inspect `tmp/stage/state.json` identity, container image labels, and compose build inputs.
|
|
190
|
-
- **Stale `.env`:** when `.env` already exists from a prior `/stage` run, `stage run` does **not** refresh it
|
|
191
|
-
from an updated `.env.example` — it warns on stderr and keeps the stale file. Delete `.env` (or merge in the
|
|
192
|
-
new keys by hand) when `.env.example` changes, then re-run `/stage`.
|
|
100
|
+
For Playwright output placement, extra services, or stale Docker/env troubleshooting, read [reference.md](reference.md) Notes.
|
|
193
101
|
|
|
194
102
|
## Retro — one check before you finish
|
|
195
103
|
Before your final report, answer one question honestly: did **this skill's own instructions** misfire
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## /stage --live — personal cloud dev stage
|
|
2
|
+
|
|
3
|
+
Project admins can deploy the **current branch** to their project's dev runtime without an IP
|
|
4
|
+
restriction. The CLI dispatches legacy gate cleanup, then the dev deploy through the Hub backend.
|
|
5
|
+
Cleanup removes only that project's old stage rules and creates no Cloudflare rules, so rule-slot
|
|
6
|
+
quotas do not block staging. It still reads Cloudflare to detect old gates; cleanup failures stay visible.
|
|
7
|
+
The stage is accessible from any IP after both workflows succeed. The app's own sign-in still applies.
|
|
8
|
+
No SSH from your machine; project authorization remains enforced by the Hub.
|
|
9
|
+
|
|
10
|
+
**Deploy-model preflight (#5466 / #5467).** `/stage --live` is **not** generally available. Read
|
|
11
|
+
`deployModel` first (`mmi-cli oracle org project get {owner}/{repo}` → `deployModel`, or the dry
|
|
12
|
+
`mmi-cli stage --live --json` refusal). It applies only to **`tenant-container`** repos (the same
|
|
13
|
+
model the Hub tenant-deploy + tenant-control gates require). **`registry-publish` is not applicable**
|
|
14
|
+
for live stages — nor are hub-serverless, solo-container, static-cdn, vercel (its preview URL is on the
|
|
15
|
+
plain `/stage` receipt), content, or none. For an
|
|
16
|
+
unsupported model the dry plan refuses **before** offering `--apply` / `--down`; do not invent a
|
|
17
|
+
tenant deploy.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
mmi-cli stage --live # dry-run plan (refuses when deployModel is not tenant-container)
|
|
21
|
+
mmi-cli stage --live --apply # clear legacy gates + deploy without an IP restriction
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Tear it down when done — **only when `--apply` actually created a runtime**. This stops the runtime
|
|
25
|
+
without Cloudflare work:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
mmi-cli stage --live --down --apply
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If apply never landed (unsupported model, failed dispatch, or you never ran `--apply`), `--down` is a
|
|
32
|
+
**safe no-op** — do not promise teardown of a stage that was never created. Personal dev stages only —
|
|
33
|
+
rc/live environments still move exclusively through the promotion train.
|
|
34
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
**Secrets are vault-native — no `.env` on disk (#2655).** The org forbids *using* `.env` files, not just
|
|
2
|
+
committing them. A repo **without** `.env.example` stages vault-native: `mmi-cli stage --apply` resolves the
|
|
3
|
+
declared dev runtime secrets (registry `requiredRuntimeSecrets[dev]`) from the vault and injects them straight
|
|
4
|
+
into the compose **process environment**, which Compose interpolates the file with — no secret ever touches
|
|
5
|
+
disk. A repo that still ships `.env.example` keeps the legacy `.env` bootstrap for back-compat until its
|
|
6
|
+
compose migrates to passthrough; new repos should ship **no** `.env.example`.
|
|
7
|
+
|
|
8
|
+
**Runtime env reaches the container through the generated passthrough (#6345).** Interpolation is not
|
|
9
|
+
delivery: a container receives only what its own `environment:` declares. So `/stage` mirrors the box deploy —
|
|
10
|
+
it generates `tmp/stage/runtime-env.override.yml` (gitignored, **key names only**, values stay in the process
|
|
11
|
+
env) passing every runtime key through to each service the compose marks `labels: {"mmi.runtime-env": "true"}`,
|
|
12
|
+
and loads it beside `docker-compose.yml` for the whole stage. Mark the app service with that label; a repo
|
|
13
|
+
that hand-declares its variables needs nothing. Unmarked sidecars (db, cache) keep getting only what they
|
|
14
|
+
interpolate themselves. Never wrap an individual `docker compose` call in `mmi-cli vault secrets use` to work
|
|
15
|
+
around a missing value (#6344) — that value is scoped to the one child process it wraps, so the next `docker
|
|
16
|
+
compose logs`/`down` fails the same `required variable … is missing a value`. Declare the key in registry
|
|
17
|
+
`requiredRuntimeSecrets[dev]` and let `/stage` carry it across the whole lifecycle.
|
|
18
|
+
|
|
19
|
+
**Build-time secrets (#5381).** When META declares `requiredBuildSecrets` (e.g. Katip's
|
|
20
|
+
`NODE_AUTH_TOKEN=@github-packages-token` for `@mutmutco/example-ui` on GitHub Packages), `/stage` injects those
|
|
21
|
+
BuildKit ids into the **`docker compose build`** process env only — not into the running container. Central
|
|
22
|
+
deploy mints the packages sentinel from Actions `GITHUB_TOKEN`; a laptop cannot. Resolution order: existing
|
|
23
|
+
process env → stageless project vault secret under the BuildKit id → existing GitHub sign-in
|
|
24
|
+
(`GH_TOKEN`, `GITHUB_TOKEN`, or `gh auth token`). Package read access is still required and is enforced
|
|
25
|
+
by GitHub Packages during the build. Cloud containers whose GH_TOKEN is a proxy placeholder set MMI_GH_PAT to a fine-grained PAT (resource owner mutmutco, Organization → Members: read); mmi-cli prefers it. If every source is missing, `/stage` fails before the build.
|
|
26
|
+
Setup: [`docs/Guides/tenant-runtime.md`](../../docs/Guides/tenant-runtime.md) § Local `/stage`. Never commit
|
|
27
|
+
or print the PAT.
|
|
28
|
+
|
|
29
|
+
## Notes
|
|
30
|
+
|
|
31
|
+
- `/stage` is local — no AWS, no deploy, no board or version effect. The one cloud exception is
|
|
32
|
+
`--live`: an on-demand **dev** stage of your branch for **`tenant-container`** repos only, without
|
|
33
|
+
a stage IP restriction (above). Preflight `deployModel` before offering it; `registry-publish`
|
|
34
|
+
and other models have no live stage.
|
|
35
|
+
- Remote rc/live environments move only through `/rcand`, `/release`, and `/hotfix`.
|
|
36
|
+
- Everything is gitignored; `/stage` never produces a tracked change.
|
|
37
|
+
- **Playwright MCP output goes to `tmp/`**, never the repo root: if you drive the Playwright MCP server,
|
|
38
|
+
pass `--output-dir tmp/playwright-mcp` (or point its output there). `.playwright-mcp/` is kept gitignored
|
|
39
|
+
by the org `.gitignore` managed block (`mmi-cli doctor`) as a safety net, so a stray default capture is
|
|
40
|
+
never tracked.
|
|
41
|
+
- `tools[]` is declarative for now; stage hardening starts/stops the main configured process. Repos with
|
|
42
|
+
extra local services should encode them behind `stage.up` until a tool runner is added.
|
|
43
|
+
- **Stale Docker bundle:** the registry-derived Docker Compose default builds with `docker compose build
|
|
44
|
+
--no-cache` before `up`. If the browser still serves an old bundle, run `mmi-cli stage stop --apply`, rerun
|
|
45
|
+
`/stage`, then inspect `tmp/stage/state.json` identity, container image labels, and compose build inputs.
|
|
46
|
+
- **Stale `.env`:** when `.env` already exists from a prior `/stage` run, `stage run` does **not** refresh it
|
|
47
|
+
from an updated `.env.example` — it warns on stderr and keeps the stale file. Delete `.env` (or merge in the
|
|
48
|
+
new keys by hand) when `.env.example` changes, then re-run `/stage`.
|
|
49
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
### Step 1a — post-smoke panel (when criteria exist)
|
|
2
|
+
|
|
3
|
+
When grinding or the user supplied **acceptance criteria** (from the issue body at Gate 1 — not
|
|
4
|
+
ad-hoc chat text), run a **Budget-routing panel** on observable stage signals before teardown:
|
|
5
|
+
|
|
6
|
+
1. **Panel** (parallel):
|
|
7
|
+
- **requirements-match** (budget tier) — does the staged URL/behavior meet the criteria?
|
|
8
|
+
- **runtime-health** (budget tier) — console errors, failed `healthUrl`, broken UI signals
|
|
9
|
+
*(smoke observability — not the grind `correctness` hard lens)*
|
|
10
|
+
- **tests-actually-test** (budget tier) — if Playwright ran, did it exercise the changed path?
|
|
11
|
+
2. **Confirm** — get an independent second model to verify the staged URL or behavior meets the acceptance criteria.
|
|
12
|
+
3. Feed the result back to the active loop or report to the human. A blocker
|
|
13
|
+
means the stage failed smoke — do not claim the grind criterion met.
|
|
14
|
+
This panel is **not** a security clearance — grind Phase 2 still runs the `security` hard lens.
|
|
15
|
+
|
|
16
|
+
Skip when `/stage` is ad-hoc preview with no criteria.
|
|
17
|
+
|