@mutmutco/pi-plugin 4.5.173 → 4.5.175
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/package.json +1 -1
- package/skills/board/SKILL.md +36 -105
- package/skills/board/reference.md +66 -0
- package/skills/bootstrap/SKILL.md +34 -120
- package/skills/bootstrap/reference.md +65 -0
- package/skills/epic/SKILL.md +33 -78
- package/skills/hotfix/SKILL.md +22 -42
- package/skills/hotfix/recovery.md +10 -0
- package/skills/rcand/SKILL.md +18 -24
- package/skills/rcand/recovery.md +8 -0
- package/skills/release/SKILL.md +11 -73
- package/skills/release/verification.md +71 -0
- package/skills/secrets/SKILL.md +18 -80
- package/skills/secrets/reference.md +41 -0
- package/skills/stage/SKILL.md +20 -74
- package/skills/stage/reference.md +49 -0
package/package.json
CHANGED
package/skills/board/SKILL.md
CHANGED
|
@@ -5,11 +5,9 @@ description: Show the repo workboard and clear it in the fewest PRs.
|
|
|
5
5
|
|
|
6
6
|
# /board — your workboard, and the fastest way through it
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Read-only until the dev says go. Rendering a board is not permission to take it.
|
|
8
|
+
Show the dev their board for this repo, then plan the whole board into the **fewest pull requests** that can
|
|
9
|
+
safely be opened and run those lanes in parallel. Read-only until the dev says go; rendering is not
|
|
10
|
+
permission to take anything.
|
|
13
11
|
|
|
14
12
|
## Step 1 — read the board
|
|
15
13
|
|
|
@@ -17,138 +15,71 @@ Read-only until the dev says go. Rendering a board is not permission to take it.
|
|
|
17
15
|
mmi-cli oracle board read --json --out .jerv/tmp/board.json
|
|
18
16
|
```
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Project. Partial reads exit nonzero; pass `--allow-partial` only when the dev accepts an incomplete board.
|
|
26
|
-
|
|
27
|
-
Partition, as the CLI computes it:
|
|
28
|
-
|
|
29
|
-
- **Yours** — assignee includes the viewer, status in `Todo · In Progress · In Review`.
|
|
30
|
-
- **Free to claim** — status `Todo`, unassigned, and the viewer has push on the repo. Also any item in
|
|
31
|
-
any status whose claim stamp is stale: its session has done no work on it for 4 hours. A stale stamp
|
|
32
|
-
holds nothing; `board claim` takes it over without `--force` and names the old stamp.
|
|
33
|
-
- **Taken** — someone else's, any active status.
|
|
34
|
-
|
|
35
|
-
Every stamped row names its session (`lane surface/session@host`), or `stale:<age>` when the stamp is
|
|
36
|
-
stale. Work means the stamp, an issue comment, a commit on the issue's branch, or an update to an open
|
|
37
|
-
PR that closes it. Any of these in the last 4 hours keeps the hold; a date that cannot be read counts as
|
|
38
|
-
work. A takeover keeps the old branch and PR and names them, so the new session continues them.
|
|
18
|
+
One call; the JSON carries `viewer`, `repo` and the project title. Use `primary` for this repo and
|
|
19
|
+
`secondary` for other repos on the Project. Partial reads exit nonzero; `--allow-partial` only when the dev
|
|
20
|
+
accepts an incomplete board. The CLI partitions rows into **Yours**, **Free to claim** and **Taken**; stale
|
|
21
|
+
stamps (4 hours without work) hold nothing. Partition rules, stamp details and `--out` rationale:
|
|
22
|
+
[reference.md](reference.md).
|
|
39
23
|
|
|
40
24
|
## Step 2 — render it
|
|
41
25
|
|
|
42
26
|
Plain markdown, never a fenced block. Flat `-` lists under bold heads, never `##` headings, never tables.
|
|
43
|
-
Refs are `[RepoName#N](url) · short title
|
|
44
|
-
|
|
45
|
-
One screen.
|
|
46
|
-
|
|
47
|
-
For a rendering example, read [examples.md](examples.md).
|
|
27
|
+
Refs are `[RepoName#N](url) · short title`, no `owner/` prefix, no `[type]` brackets. **Taken** renders
|
|
28
|
+
id · status · owner only, never the title. Skip empty sections. One screen. Example: [examples.md](examples.md).
|
|
48
29
|
|
|
49
|
-
Status moves happen automatically as work flows
|
|
30
|
+
Status moves happen automatically as work flows. Never offer a status move.
|
|
50
31
|
|
|
51
32
|
## Step 3 — plan the fewest PRs
|
|
52
33
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Fetch the material you need to group by:
|
|
34
|
+
Never one item at a time, never one PR per issue. Fetch bodies:
|
|
56
35
|
|
|
57
36
|
```bash
|
|
58
37
|
mmi-cli oracle board read --json --bodies --out .jerv/tmp/board-full.json
|
|
59
38
|
```
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
`row.details.body` and `row.details.comments` — not `row.body` or `row.comments`. `--bundle-details` is
|
|
63
|
-
the cheaper variant that covers only `userOwned` and `claimable` — prefer it when the plan is limited
|
|
64
|
-
to claimable work. `taken` stays metadata-only either way. Do not fetch Done items.
|
|
65
|
-
|
|
66
|
-
Then build the plan:
|
|
67
|
-
|
|
68
|
-
1. **Derive each issue's touch-set** — the files and directories it will change, read from the body,
|
|
69
|
-
its comments and its `surface:*` label. An issue whose touch-set you cannot name is not plannable;
|
|
70
|
-
leave it out of the batch and say so.
|
|
71
|
-
2. **Join issues whose touch-sets overlap.** Follow the overlap transitively: if A and B share a file and
|
|
72
|
-
B and C share another, all three are one group. Each resulting group is one worktree and **one PR**.
|
|
73
|
-
3. **Groups are disjoint by construction**, so every group runs in parallel with no worktree contention.
|
|
74
|
-
That is the whole trick — the number of groups is the number of PRs, and it is the smallest number
|
|
75
|
-
reachable without two PRs fighting over the same file.
|
|
76
|
-
|
|
77
|
-
Forced splits — these override the grouping and each takes its own PR:
|
|
78
|
-
|
|
79
|
-
- **Another repo.** Never bundle across repos. Board advance is per-repo and deliberately refuses to move
|
|
80
|
-
another repo's issue, so a cross-repo bundle lands the code and leaves those issues stranded open.
|
|
81
|
-
- **Irreversible or gated work** — migrations, secret rotation, release-train changes. Bundling hides them.
|
|
82
|
-
- **An issue that must stay open** (HOLD, prep, partial delivery).
|
|
83
|
-
- **Review size.** A PR no one can review is not cheap. When a group grows past roughly ten issues or
|
|
84
|
-
spans unrelated subsystems, cut it at its weakest overlap and take two PRs.
|
|
40
|
+
(Bodies and comments are at `row.details.body` and `row.details.comments`. Skip Done.)
|
|
85
41
|
|
|
86
|
-
|
|
87
|
-
|
|
42
|
+
1. **Derive each issue's touch-set** from body, comments and `surface:*` label. If you cannot name it, leave
|
|
43
|
+
the issue out and say so.
|
|
44
|
+
2. **Join overlapping touch-sets**, transitively. Each group is one worktree and **one PR**; groups are
|
|
45
|
+
disjoint, so all run in parallel.
|
|
88
46
|
|
|
89
|
-
|
|
90
|
-
|
|
47
|
+
Forced splits, each its own PR: another repo; irreversible or gated work (migrations, secret rotation,
|
|
48
|
+
release-train changes; principle 12); an issue that must stay open; a group past roughly ten issues or
|
|
49
|
+
spanning unrelated subsystems. Reasons: [reference.md](reference.md).
|
|
91
50
|
|
|
92
|
-
|
|
51
|
+
Present the plan — batch count, issue count, one line per batch naming its shared surface — then wait for go.
|
|
93
52
|
|
|
94
|
-
|
|
53
|
+
## Step 4 — on go, claim and run
|
|
95
54
|
|
|
96
55
|
```bash
|
|
97
56
|
mmi-cli oracle board claim <ref> <ref> <ref> --json
|
|
98
57
|
```
|
|
99
58
|
|
|
100
|
-
|
|
101
|
-
`
|
|
102
|
-
`In Progress`, and stamps a lane-identity comment so other agents can attribute the hold. Any per-item failure exits nonzero — read
|
|
103
|
-
the per-item results rather than assuming the batch took. **Route is `oracle board claim` only**; there is
|
|
104
|
-
no `oracle issue claim` and no flat `board claim` — both refuse. Guessing either burns a call.
|
|
59
|
+
Say the size first: how many issues, how many PRs. Read per-item results; any failure exits nonzero. **Route
|
|
60
|
+
is `oracle board claim` only**; `oracle issue claim` and flat `board claim` refuse.
|
|
105
61
|
|
|
106
|
-
|
|
107
|
-
and PR facts. For worktree setup on Windows or concurrent ref renames, read [reference.md](reference.md).
|
|
62
|
+
The claim prints the issue's recorded owner rulings; follow them. Record a new one with `mmi-cli oracle issue decision`.
|
|
108
63
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
There is no `--issues` or `--closes` flag. A bundled PR is expressed in the **body**:
|
|
64
|
+
One worktree per batch, all concurrently. Windows setup and ref renames: [reference.md](reference.md).
|
|
112
65
|
|
|
113
|
-
|
|
114
|
-
Closes #6395, #6396, #6397
|
|
115
|
-
```
|
|
66
|
+
## Step 5 — land one PR per batch
|
|
116
67
|
|
|
117
|
-
`
|
|
118
|
-
|
|
119
|
-
that did not move. So a bundle is a first-class landing, not a trick.
|
|
68
|
+
No `--issues` or `--closes` flag; put `Closes #6395, #6396, #6397` in the **body**. After merge, board
|
|
69
|
+
advance moves each closed issue to Done.
|
|
120
70
|
|
|
121
71
|
```bash
|
|
122
72
|
mmi-cli devops pr create --body-file .jerv/tmp/pr-batch-a.md
|
|
123
73
|
mmi-cli devops pr land <pr> --json
|
|
124
74
|
```
|
|
125
75
|
|
|
126
|
-
|
|
127
|
-
`
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
GitHub closes it anyway (JC#495).
|
|
131
|
-
|
|
132
|
-
When the repo runs a guidance-learning gate, read [reference.md](reference.md) before preparing the PR body.
|
|
133
|
-
|
|
134
|
-
Landing requires a merged receipt before any cleanup: `state` `MERGED`, the head ref and OID matching the
|
|
135
|
-
local task branch, and a clean worktree. Anything else means retain and report, never clean.
|
|
136
|
-
|
|
137
|
-
## Guardrails
|
|
138
|
-
|
|
139
|
-
- **No go, no write.** The board render and the plan are free. Claims, branches, PRs are not.
|
|
140
|
-
- **Say the size out loud** before claiming: how many issues, how many PRs.
|
|
141
|
-
- **Same repo only** inside one PR.
|
|
142
|
-
- A batch is justified by a shared code surface, never by convenience. Unrelated changes in one PR make a
|
|
143
|
-
worse PR, not a cheaper one.
|
|
144
|
-
- Surface any `gh` / `mmi-cli` error verbatim.
|
|
76
|
+
Write the body as a UTF-8 file; run `mmi-cli explain devops pr create --json` first. An issue that stays
|
|
77
|
+
open: `Part of #N` or `Refs #N`, never `Does not close #N`. Guidance-learning gate: read
|
|
78
|
+
[reference.md](reference.md) first. Clean up only after a merged receipt (`state` `MERGED`, matching head
|
|
79
|
+
ref and OID, clean worktree); otherwise retain and report. Show any `gh` / `mmi-cli` error verbatim.
|
|
145
80
|
|
|
146
81
|
## Retro — one check before you finish
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
(Process only — never the user's code or task; e.g. a grouping rule that bundled two issues which turned
|
|
150
|
-
out to conflict, or a board read that misreported what was claimable.) If yes, file **one** lesson and
|
|
151
|
-
move on; a clean run is silent (hard cap: one per run). It lands on the owning board (deduped) and is
|
|
152
|
-
fixed only via a reviewed PR — never edit the skill live; the retro is advisory, so if the call fails,
|
|
153
|
-
note it and continue. File through MMI:
|
|
82
|
+
|
|
83
|
+
Did this skill's own instructions misfire this run (process only, never the user's code)? If yes, file one:
|
|
154
84
|
`mmi-cli learning skill-lesson --skill board --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
|
|
85
|
+
File one per run; a clean run is silent; if the call fails, note it and continue.
|
|
@@ -9,3 +9,69 @@ standalone `learning: none — <reason>` line unless a closing learning issue's
|
|
|
9
9
|
changed file. The line must stand alone on its own newline — a literal `\n` inside an inline edit fails
|
|
10
10
|
the gate again.
|
|
11
11
|
|
|
12
|
+
|
|
13
|
+
## Detail moved from SKILL.md
|
|
14
|
+
|
|
15
|
+
Prefer `--out` for a shell-independent UTF-8 receipt. Windows PowerShell 5.1's `>` writes
|
|
16
|
+
UTF-16LE with a BOM (#5802); Bash redirects preserve the CLI's UTF-8 output.
|
|
17
|
+
|
|
18
|
+
One call. Its JSON carries `viewer`, `repo` and the project title — do not spend extra calls on
|
|
19
|
+
`gh api user` or `gh repo view`. Use `primary` for this repo and `secondary` for other repos on the same
|
|
20
|
+
Project. Partial reads exit nonzero; pass `--allow-partial` only when the dev accepts an incomplete board.
|
|
21
|
+
|
|
22
|
+
Partition, as the CLI computes it:
|
|
23
|
+
|
|
24
|
+
- **Yours** — assignee includes the viewer, status in `Todo · In Progress · In Review`, or stamped by this
|
|
25
|
+
seat (same login, host, and surface, including a prior session on this host whose transcript is dead).
|
|
26
|
+
- **Free to claim** — status `Todo`, unassigned, and the viewer has push on the repo. Also any item in
|
|
27
|
+
any status whose foreign claim stamp is stale: its session has done no work on it for 4 hours. A stale stamp
|
|
28
|
+
holds nothing; `board claim` takes it over without `--force` and names the old stamp.
|
|
29
|
+
- **Taken** — someone else's, any active status.
|
|
30
|
+
|
|
31
|
+
Every stamped row names its session (`lane surface/session@host`), or `stale:<age>` when the stamp is
|
|
32
|
+
stale. Work means the stamp, an issue comment, a commit on the issue's branch, or an update to an open
|
|
33
|
+
PR that closes it. Any of these in the last 4 hours keeps the hold; a date that cannot be read counts as
|
|
34
|
+
work. A takeover keeps the old branch and PR and names them, so the new session continues them.
|
|
35
|
+
|
|
36
|
+
`--bodies` fetches body and comments for every scoped issue. In the JSON, read them at
|
|
37
|
+
`row.details.body` and `row.details.comments` — not `row.body` or `row.comments`. `--bundle-details` is
|
|
38
|
+
the cheaper variant that covers only `userOwned` and `claimable` — prefer it when the plan is limited
|
|
39
|
+
to claimable work. `taken` stays metadata-only either way. Do not fetch Done items.
|
|
40
|
+
|
|
41
|
+
3. **Groups are disjoint by construction**, so every group runs in parallel with no worktree contention.
|
|
42
|
+
That is the whole trick — the number of groups is the number of PRs, and it is the smallest number
|
|
43
|
+
reachable without two PRs fighting over the same file.
|
|
44
|
+
|
|
45
|
+
Forced splits — these override the grouping and each takes its own PR:
|
|
46
|
+
|
|
47
|
+
- **Another repo.** Never bundle across repos. Board advance is per-repo and deliberately refuses to move
|
|
48
|
+
another repo's issue, so a cross-repo bundle lands the code and leaves those issues stranded open.
|
|
49
|
+
- **Irreversible or gated work** — migrations, secret rotation, release-train changes. Bundling hides them.
|
|
50
|
+
- **An issue that must stay open** (HOLD, prep, partial delivery).
|
|
51
|
+
- **Review size.** A PR no one can review is not cheap. When a group grows past roughly ten issues or
|
|
52
|
+
spans unrelated subsystems, cut it at its weakest overlap and take two PRs.
|
|
53
|
+
|
|
54
|
+
> Nine claimable, three PRs: **A** #6395–#6397 board routing · **B** #6398–#6401 train doctor heal ·
|
|
55
|
+
> **C** #6402–#6403 CLI flag validation. Say go and I'll run all three in parallel.
|
|
56
|
+
|
|
57
|
+
Claiming takes a card that is unassigned or assigned to the viewer, in `Todo`, `In Progress` or
|
|
58
|
+
`In Review`, unless another session still shows work on it in the last 4 hours (then it refuses). It assigns the viewer, sets
|
|
59
|
+
`In Progress` and stamps a lane-identity comment.
|
|
60
|
+
|
|
61
|
+
Then one worktree per batch, all batches concurrently. The host owns worktree mechanics; MMI owns board
|
|
62
|
+
and PR facts.
|
|
63
|
+
|
|
64
|
+
`pr create` normalizes multiple closing directives, and after the merge the board advance walks GitHub's
|
|
65
|
+
full `closingIssuesReferences` list and moves **each** issue to Done, verifying every one and naming any
|
|
66
|
+
that did not move. So a bundle is a first-class landing, not a trick.
|
|
67
|
+
|
|
68
|
+
Materialize the body as a real UTF-8 file and pass its path; do not pipe it to `--body-file -`. Read
|
|
69
|
+
`mmi-cli explain devops pr create --json` before the write — flags change.
|
|
70
|
+
|
|
71
|
+
When an issue must stay open, write `Part of #N` or `Refs #N`. **Never** write `Does not close #N` —
|
|
72
|
+
GitHub closes it anyway (JC#495).
|
|
73
|
+
|
|
74
|
+
Landing requires a merged receipt before any cleanup: `state` `MERGED`, the head ref and OID matching the
|
|
75
|
+
local task branch, and a clean worktree. Anything else means retain and report, never clean.
|
|
76
|
+
|
|
77
|
+
Retro: the lesson lands on the owning board (deduped) and is fixed only via a reviewed PR — never edit the skill live; the retro is advisory. A misfire is ambiguous wording, a misleading message, or an environment failure the skill should have warned about (e.g. a grouping rule that bundled two issues which turned out to conflict, or a board read that misreported what was claimable). Hard cap: one lesson per run.
|
|
@@ -7,157 +7,71 @@ description: Provision an org repo with board, registry, rules, and plugin setup
|
|
|
7
7
|
|
|
8
8
|
# /bootstrap — provision a repo into the org
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
`MMI-Hub` (the hub).** Every step operates org-level resources (Project, Ruleset, org secrets, member
|
|
12
|
-
access) **through the GitHub App's installation token** — not a human credential — so the gate is who may
|
|
13
|
-
invoke the skill (the master holds the App key), not the caller's GitHub role.
|
|
10
|
+
One-time onboarding, run from `MMI-Hub` by the master (who holds the GitHub App key). It uses the App installation token, no per-repo checkout. The repo must already be named `<CATEGORY>-<PascalName>`.
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
already be named on the taxonomy `<CATEGORY>-<PascalName>`.
|
|
12
|
+
Read [reference.md](reference.md) for create vs upgrade, seed refresh, propagation rollback, or new topology values.
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
## Step 0 — confirm the four axes before any mutation
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
Before Step 0a, state a recommended default per axis and confirm all four with Jervaise through the orchestrator; never default silently.
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
never apply it silently. Use the structured-question UI; one question per axis (or one grouped confirm).
|
|
18
|
+
- **`class`** — `deployable` (full or direct train) · `content` (trunk, `main` only); sets the branch model.
|
|
19
|
+
- **`project-type`** — `web-app`, `cli-tool`, `worker`, `desktop-app`, `desktop-game`, `mobile-app`, `content`…; sets Hub services.
|
|
20
|
+
- **`deploy-model`** — `tenant-container`, `none`, `content`…; sets the deploy path.
|
|
21
|
+
- **`release-track`** — `full` (development·rc·main) · `direct` (development·main) · `trunk` (`main`); sets the branch set.
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
trunk, `main`-only). *Controls the branch model.* Recommend from what the repo **is**, not a fixed default.
|
|
30
|
-
- **`project-type`** — e.g. `web-app`, `cli-tool`, `worker`, `desktop-app`, `desktop-game`, `mobile-app`, `content`. *Controls which Hub
|
|
31
|
-
services attach.*
|
|
32
|
-
- **`deploy-model`** — e.g. `tenant-container`, `none`, `content`. *Controls the deploy path.*
|
|
33
|
-
- **`release-track`** — `full` (development·rc·main) · `direct` (development·main, skips rc) · `trunk`
|
|
34
|
-
(`main` only). *The branch set follows the track, not just the class (#1097).*
|
|
23
|
+
A **deployable** repo also needs gate runtime (`node` default, `python` for a Python app), check command and working directory: `--var GATE_RUNTIME=`, `GATE_CMD=`, `GATE_WORKDIR=`, and `GATE_CACHE_DEP_PATH=` for a non-root Node lockfile.
|
|
35
24
|
|
|
25
|
+
**Content/trunk**: `main` only, no `rc`, no `gate.yml`, no product required-check ruleset, `projects.json` entry with `branch: main`.
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
the **working directory** — these feed the product gate (`--var GATE_RUNTIME=`, `--var GATE_CMD=`,
|
|
39
|
-
`--var GATE_WORKDIR=`, and `--var GATE_CACHE_DEP_PATH=` for a non-root Node lockfile; see Step 5 / the
|
|
40
|
-
"Product gate + required checks" note below). Default to `node` at the repo root; recommend `python` when the
|
|
41
|
-
repo's app is Python.
|
|
42
|
-
|
|
43
|
-
A **content/trunk** choice provisions: `main`-only (no `rc`), **no** `.github/workflows/gate.yml` and **no**
|
|
44
|
-
product required-check ruleset, and a `projects.json` entry with `branch: main` (which marks it a content-class
|
|
45
|
-
repo). A clean content repo then verifies green — `bootstrap verify --class content` no longer reports
|
|
46
|
-
the deployable gate checks as FAIL (#1450).
|
|
47
|
-
|
|
48
|
-
Record the confirmed axes; Step 0a runs `verify --class <confirmed>`, Step 0b creates the repo on the
|
|
49
|
-
track's default branch, and the apply flags (`--project-type` / `--deploy-model` / `--release-track`) carry
|
|
50
|
-
the confirmed values — no silent defaulting.
|
|
27
|
+
Apply flags carry the confirmed values; Step 0b creates the repo on the track's default branch.
|
|
51
28
|
|
|
52
29
|
## Step 0a — no-mutation verifier
|
|
53
30
|
|
|
54
|
-
Before mutating anything, run the verifier so the current gaps are concrete:
|
|
55
31
|
```bash
|
|
56
|
-
mmi-cli devops bootstrap verify "$OWNER/$REPO" --class deployable --json
|
|
57
|
-
# or for content repos:
|
|
58
|
-
mmi-cli devops bootstrap verify "$OWNER/$REPO" --class content --json
|
|
32
|
+
mmi-cli devops bootstrap verify "$OWNER/$REPO" --class deployable --json # or --class content
|
|
59
33
|
```
|
|
60
34
|
|
|
61
|
-
|
|
62
|
-
names an explicitly manual-only item that the master has accepted for that repo. For a deployable repo the
|
|
63
|
-
report ends with the train doctor verdict per lane (`release`; plus `rcand` on a full track) — the same
|
|
64
|
-
`mmi-cli devops train doctor` door `/release` and `/rcand` open (#6070); a `ready: false` there is an
|
|
65
|
-
unfinished repo, **with one expected exception**: a full track's two lanes start from different branches
|
|
66
|
-
(`release` from `rc`, `rcand` from `development`) and one checkout stands on one branch, so the lane you
|
|
67
|
-
are not standing on reports the never-healed `branch-mismatch` blocker (#6432). Verify is read-only and
|
|
68
|
-
does not check the other branch out: a lane whose ONLY finding is that mismatch is printed `NOT EVALUATED
|
|
69
|
-
from this branch` and does not fail the verify (#6677). That is the finished state, not a gap — run
|
|
70
|
-
`mmi-cli devops train doctor --lane <lane> --json` from that lane's own branch for its verdict. Any other
|
|
71
|
-
blocker in that lane, or an unread origin, still makes the report red.
|
|
72
|
-
|
|
73
|
-
**Two verify FAILs are un-run apply steps or API lag, not code bugs — diagnose them as such, but never as
|
|
74
|
-
acceptable end states (#2928):**
|
|
75
|
-
- `branch protection exists` / `push allowlist configured` — **`bootstrap apply --execute` applies the
|
|
76
|
-
train-branch push allowlist (Step 2b)**, so these FAIL until the live apply has run. They are security
|
|
77
|
-
controls and must go green (or be an explicitly master-accepted manual item per the rule above) before
|
|
78
|
-
the bootstrap is complete. A red branch-protection or push-allowlist check is an **unfinished repo**,
|
|
79
|
-
never a known-benign FAIL to sign off around.
|
|
80
|
-
- `README has Agent context section — README.md not readable via API` on a README that demonstrably has the
|
|
81
|
-
section — GitHub's contents API lags for a minute or so right after a merge. **Re-run before believing a
|
|
82
|
-
content-read failure**; it clears on its own.
|
|
83
|
-
|
|
84
|
-
For a new repo, board selection/creation, access, gate setup, or manual provisioning, read [reference.md](reference.md) Steps 0b–5 before applying; upgrades can use the apply path below.
|
|
35
|
+
Re-run after Step 7. Ready = all green, or a named manual-only item Jervaise accepted. A deployable report ends with the train doctor verdict per lane (`release`, plus `rcand` on full track); the lane you are not standing on reports `branch-mismatch`; if that is its ONLY finding, verify prints `NOT EVALUATED from this branch` and passes: run `mmi-cli devops train doctor --lane <lane> --json` from that lane's branch. Any other blocker, or an unread origin, is red.
|
|
85
36
|
|
|
86
|
-
|
|
37
|
+
Two FAILs are unrun steps or API lag, never acceptable end states:
|
|
38
|
+
- `branch protection exists` / `push allowlist configured` — `bootstrap apply --execute` applies the allowlist (Step 2b). Security controls: green, or an accepted manual item, before the bootstrap is complete.
|
|
39
|
+
- `README has Agent context section — README.md not readable via API` on a README that has it — API lag after a merge; re-run.
|
|
87
40
|
|
|
88
|
-
|
|
89
|
-
deploy, secret, and project state from the Hub registry at runtime.
|
|
41
|
+
For board selection/creation, access, gate setup or manual provisioning of a new repo, read [reference.md](reference.md) Steps 0b–5; upgrades use the apply path below.
|
|
90
42
|
|
|
91
|
-
|
|
43
|
+
## Step 6 — register Hub META
|
|
92
44
|
|
|
93
|
-
|
|
94
|
-
`mmi-cli oracle org project set` from the Hub or from the target project checkout:
|
|
45
|
+
No product repo control-plane file; `mmi-cli` resolves state from the Hub registry. For flag combinations or an MM-Work module, read [reference.md](reference.md) first. Apply with the board variables discovered earlier (or `mmi-cli oracle org project set`):
|
|
95
46
|
|
|
96
47
|
```bash
|
|
97
48
|
mmi-cli devops bootstrap apply "$OWNER/$REPO" --class deployable \
|
|
98
49
|
--project-type web-app --deploy-model tenant-container --execute \
|
|
99
|
-
--var PROJECT_OWNER="$PROJECT_OWNER" \
|
|
100
|
-
--var
|
|
101
|
-
--var
|
|
102
|
-
--var
|
|
103
|
-
--var STATUS_TODO="$STATUS_TODO" \
|
|
104
|
-
--var STATUS_IN_PROGRESS="$STATUS_IN_PROGRESS" \
|
|
105
|
-
--var STATUS_IN_REVIEW="$STATUS_IN_REVIEW" \
|
|
106
|
-
--var STATUS_DONE="$STATUS_DONE"
|
|
50
|
+
--var PROJECT_OWNER="$PROJECT_OWNER" --var PROJECT_NUMBER="$PROJECT_NUMBER" \
|
|
51
|
+
--var PROJECT_ID="$PROJECT_ID" --var STATUS_FIELD_ID="$STATUS_FIELD_ID" \
|
|
52
|
+
--var STATUS_TODO="$STATUS_TODO" --var STATUS_IN_PROGRESS="$STATUS_IN_PROGRESS" \
|
|
53
|
+
--var STATUS_IN_REVIEW="$STATUS_IN_REVIEW" --var STATUS_DONE="$STATUS_DONE"
|
|
107
54
|
```
|
|
108
55
|
|
|
109
|
-
|
|
110
|
-
archive; the train does not ship a prebuilt `dist/`. **Bootstrap seeds both files** for
|
|
111
|
-
`deployModel: tenant-container` from `skills/bootstrap/seeds/` (rendered from
|
|
112
|
-
the bootstrap seed Dockerfile and compose templates). The seeded compose is fileless: its service carries
|
|
113
|
-
`labels: { mmi.runtime-env: "true" }`, no `env_file`, and a loopback-only port; the deploy injects the stage's
|
|
114
|
-
vault values at runtime (`DEPLOY#<stage>.noEnvFile: true`) and the app reads plain env vars — it must **not** self-load SSM and must **not** ship a committed `.env`.
|
|
56
|
+
`tenant-container` repos need a `docker-compose.yml` and Dockerfile building from the shipped source archive (no prebuilt `dist/`); bootstrap seeds both from `skills/bootstrap/seeds/`. The seeded compose is fileless: label `mmi.runtime-env: "true"`, no `env_file`, loopback-only port; deploy injects the stage's vault values (`DEPLOY#<stage>.noEnvFile: true`), so the app reads plain env vars, never self-loads SSM, never ships a `.env`. For an MM-Work module or non-suite web-app with OAuth META, read [reference.md](reference.md) before the first CI/deploy or OAuth provisioning.
|
|
115
57
|
|
|
116
|
-
|
|
58
|
+
**Stage port block:** `tenant-container` and `solo-container` need Hub registry `portRange` (`bootstrap verify` fails without it). `bootstrap apply --execute` assigns it; for older META run `mmi-cli stage port-range <Repo>` (idempotent). Use `$STAGE_PORT` in `stage.up`/`healthUrl`.
|
|
117
59
|
|
|
118
|
-
|
|
119
|
-
`stage` block, but that file must not contain board, deploy, or secret registry facts.
|
|
60
|
+
## Step 7 — org-managed .gitignore block
|
|
120
61
|
|
|
121
|
-
|
|
122
|
-
(idempotently) the repo's local port block from the central registry. `tenant-container` and
|
|
123
|
-
`solo-container` **must** have Hub registry `portRange` — `mmi-cli devops bootstrap verify` fails without
|
|
124
|
-
it (#5539), and `mmi-cli stage` cannot derive a local preview until the block exists. `bootstrap apply
|
|
125
|
-
--execute` assigns the block automatically after DDB register for those models; for older META holes,
|
|
126
|
-
run `stage port-range` explicitly. Use `$STAGE_PORT` in `stage.up` / `healthUrl`; `/stage` then picks a
|
|
127
|
-
free port inside the block so a dev can run several projects/versions locally without collisions.
|
|
128
|
-
|
|
129
|
-
## Step 7 — seed the org-managed .gitignore block
|
|
130
|
-
|
|
131
|
-
The org-managed `.gitignore` block is delivered by the `managed-block` bootstrap seed (`skills/bootstrap/seeds/manifest.json`),
|
|
132
|
-
which merges the canonical block into the repo's `.gitignore` in place, preserving the repo's own ignore lines.
|
|
133
|
-
The independent CLI/user-settings resume path may run doctor thereafter. The block carries **only** org-universal ignores —
|
|
134
|
-
never agent guides or a spine. The fanout pipeline that used to push this block via App-token PRs is retired
|
|
135
|
-
(Hub#3010), and the whole-spine fanout was retired earlier (hub-v3 WS4.2 #2219).
|
|
62
|
+
The `managed-block` seed (`skills/bootstrap/seeds/manifest.json`) merges org-universal ignores into `.gitignore` in place, keeping the repo's own lines.
|
|
136
63
|
|
|
137
64
|
## Step 8 — report
|
|
138
65
|
|
|
139
|
-
Repo, default branch, ruleset
|
|
140
|
-
provisioned per track (plan-gated protections named in apply output), project attached/created
|
|
141
|
-
(+ info seeded, Status lanes and Labels field verified), secrets set (names only), developer access, plugin
|
|
142
|
-
installed, docs seeded, registry META written, issue templates committed, org App credentials registered,
|
|
143
|
-
org-managed `.gitignore` block seeded, the final `mmi-cli devops bootstrap verify "$OWNER/$REPO" --class ... --json` result,
|
|
144
|
-
and — for a deployable repo — the train door itself, run from the repo's own checkout on `development`:
|
|
66
|
+
Repo, default branch, ruleset, push allowlist, Environments per track, project (info, Status lanes, Labels field verified), secrets set (names only), access, plugin, docs, registry META, issue templates, org App credentials, `.gitignore` block, the final `bootstrap verify` result, and for a deployable repo the train door from the repo's checkout on `development`:
|
|
145
67
|
|
|
146
68
|
```bash
|
|
147
|
-
mmi-cli devops train doctor --lane release --repo "$OWNER/$REPO" --json
|
|
69
|
+
mmi-cli devops train doctor --lane release --repo "$OWNER/$REPO" --json # full track: also --lane rcand
|
|
148
70
|
```
|
|
149
71
|
|
|
150
|
-
`ready: true` is the
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
## Retro — one check before you finish
|
|
157
|
-
Before your final report, answer one question honestly: did **this skill's own instructions** misfire
|
|
158
|
-
this run — ambiguous wording, a misleading message, or an environment failure it should have warned
|
|
159
|
-
about? (Process only — never the user's code or task; e.g. an ambiguous seed, registry, or OIDC step, or
|
|
160
|
-
a guard that fired on a healthy repo.) If yes, file **one** lesson and move on; a clean run is silent
|
|
161
|
-
(hard cap: one per run). It lands on the owning board (deduped) and is fixed only via a reviewed PR — never
|
|
162
|
-
edit the skill live; the retro is advisory, so if the call fails, note it and continue. File through MMI:
|
|
72
|
+
`ready: true` is the train-readiness proof (findings: `docs/Guides/train-troubleshooting.md#<code>`). A `bootstrap-gap` finding names the missing apply row (blocker: train branch absent on origin; warning: stage with no required status check). Read warnings too: `ready: true` alone does not prove the product ruleset is active.
|
|
73
|
+
|
|
74
|
+
## Retro
|
|
75
|
+
|
|
76
|
+
If this skill's instructions misfired (process only), file one lesson (one per run; if the call fails, note it and continue):
|
|
163
77
|
`mmi-cli learning skill-lesson --skill bootstrap --title "<what misfired>" --body "<what; evidence; proposed amendment>"`
|
|
@@ -419,3 +419,68 @@ The keys are the one stageless pair `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET`
|
|
|
419
419
|
stage reads it (#2244/#2528). Never a staged `{dev,rc,main}/GOOGLE_*`, `GOOGLE_OAUTH_CLIENT_*`, or `prod/`
|
|
420
420
|
variant; the runtime reads only the canonical names and declare-first rejects the rest.
|
|
421
421
|
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
## Detail moved from SKILL.md (verbatim)
|
|
425
|
+
|
|
426
|
+
For a **deployable** repo, also capture the **gate runtime** (`node` | `python`), the **check command**, and
|
|
427
|
+
the **working directory** — these feed the product gate (`--var GATE_RUNTIME=`, `--var GATE_CMD=`,
|
|
428
|
+
`--var GATE_WORKDIR=`, and `--var GATE_CACHE_DEP_PATH=` for a non-root Node lockfile; see Step 5 / the
|
|
429
|
+
"Product gate + required checks" note below). Default to `node` at the repo root; recommend `python` when the
|
|
430
|
+
repo's app is Python.
|
|
431
|
+
|
|
432
|
+
A **content/trunk** choice provisions: `main`-only (no `rc`), **no** `.github/workflows/gate.yml` and **no**
|
|
433
|
+
product required-check ruleset, and a `projects.json` entry with `branch: main` (which marks it a content-class
|
|
434
|
+
repo). A clean content repo then verifies green — `bootstrap verify --class content` no longer reports
|
|
435
|
+
the deployable gate checks as FAIL (#1450).
|
|
436
|
+
|
|
437
|
+
Record the confirmed axes; Step 0a runs `verify --class <confirmed>`, Step 0b creates the repo on the
|
|
438
|
+
track's default branch, and the apply flags (`--project-type` / `--deploy-model` / `--release-track`) carry
|
|
439
|
+
the confirmed values — no silent defaulting.
|
|
440
|
+
|
|
441
|
+
Run it again after Step 7. A repo is not ready for real developers until every check is green, or the report
|
|
442
|
+
names an explicitly manual-only item that the master has accepted for that repo. For a deployable repo the
|
|
443
|
+
report ends with the train doctor verdict per lane (`release`; plus `rcand` on a full track) — the same
|
|
444
|
+
`mmi-cli devops train doctor` door `/release` and `/rcand` open (#6070); a `ready: false` there is an
|
|
445
|
+
unfinished repo, **with one expected exception**: a full track's two lanes start from different branches
|
|
446
|
+
(`release` from `rc`, `rcand` from `development`) and one checkout stands on one branch, so the lane you
|
|
447
|
+
are not standing on reports the never-healed `branch-mismatch` blocker (#6432). Verify is read-only and
|
|
448
|
+
does not check the other branch out: a lane whose ONLY finding is that mismatch is printed `NOT EVALUATED
|
|
449
|
+
from this branch` and does not fail the verify (#6677). That is the finished state, not a gap — run
|
|
450
|
+
`mmi-cli devops train doctor --lane <lane> --json` from that lane's own branch for its verdict. Any other
|
|
451
|
+
blocker in that lane, or an unread origin, still makes the report red.
|
|
452
|
+
|
|
453
|
+
Tenant-container repos must carry a `docker-compose.yml` and Dockerfile that build from the shipped source
|
|
454
|
+
archive; the train does not ship a prebuilt `dist/`. **Bootstrap seeds both files** for
|
|
455
|
+
`deployModel: tenant-container` from `skills/bootstrap/seeds/` (rendered from
|
|
456
|
+
the bootstrap seed Dockerfile and compose templates). The seeded compose is fileless: its service carries
|
|
457
|
+
`labels: { mmi.runtime-env: "true" }`, no `env_file`, and a loopback-only port; the deploy injects the stage's
|
|
458
|
+
vault values at runtime (`DEPLOY#<stage>.noEnvFile: true`) and the app reads plain env vars — it must **not** self-load SSM and must **not** ship a committed `.env`.
|
|
459
|
+
|
|
460
|
+
Local `/stage` is optional product-owned configuration. A repo that wants `/stage` may carry a local
|
|
461
|
+
`stage` block, but that file must not contain board, deploy, or secret registry facts.
|
|
462
|
+
|
|
463
|
+
**Stage port block (required for central-container):** run `mmi-cli stage port-range <Repo>` to assign
|
|
464
|
+
(idempotently) the repo's local port block from the central registry. `tenant-container` and
|
|
465
|
+
`solo-container` **must** have Hub registry `portRange` — `mmi-cli devops bootstrap verify` fails without
|
|
466
|
+
it (#5539), and `mmi-cli stage` cannot derive a local preview until the block exists. `bootstrap apply
|
|
467
|
+
--execute` assigns the block automatically after DDB register for those models; for older META holes,
|
|
468
|
+
run `stage port-range` explicitly. Use `$STAGE_PORT` in `stage.up` / `healthUrl`; `/stage` then picks a
|
|
469
|
+
free port inside the block so a dev can run several projects/versions locally without collisions.
|
|
470
|
+
|
|
471
|
+
Repo, default branch, ruleset applied, train branches locked (push allowlist), repository Environments
|
|
472
|
+
provisioned per track (plan-gated protections named in apply output), project attached/created
|
|
473
|
+
(+ info seeded, Status lanes and Labels field verified), secrets set (names only), developer access, plugin
|
|
474
|
+
installed, docs seeded, registry META written, issue templates committed, org App credentials registered,
|
|
475
|
+
org-managed `.gitignore` block seeded, the final `mmi-cli devops bootstrap verify "$OWNER/$REPO" --class ... --json` result,
|
|
476
|
+
and — for a deployable repo — the train door itself, run from the repo's own checkout on `development`:
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
mmi-cli devops train doctor --lane release --repo "$OWNER/$REPO" --json
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
`ready: true` is the bootstrap's train-readiness proof; every finding carries `code`, `severity`, `source`,
|
|
483
|
+
`remedy` and a `docs/Guides/train-troubleshooting.md#<code>` anchor. A full-track repo runs
|
|
484
|
+
`--lane rcand` as well. A `bootstrap-gap` finding names the apply row still missing — a blocker for a
|
|
485
|
+
train branch absent on origin, a warning for a stage with no required status check (#6136): read the
|
|
486
|
+
warnings too, `ready: true` alone does not prove the product ruleset is active.
|