@lifeaitools/rdc-skills 0.25.5 → 0.25.10

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 (66) hide show
  1. package/.claude-plugin/plugin.json +1550 -1550
  2. package/.github/workflows/self-test.yml +34 -34
  3. package/CHANGELOG.md +319 -319
  4. package/MANIFEST.md +224 -224
  5. package/README.md +367 -367
  6. package/commands/build.md +181 -181
  7. package/commands/collab.md +180 -180
  8. package/commands/deploy.md +148 -148
  9. package/commands/fixit.md +150 -150
  10. package/commands/handoff.md +173 -173
  11. package/commands/overnight.md +220 -220
  12. package/commands/plan.md +158 -158
  13. package/commands/preplan.md +131 -131
  14. package/commands/prototype.md +145 -145
  15. package/commands/report.md +99 -99
  16. package/commands/review.md +120 -120
  17. package/commands/status.md +86 -86
  18. package/commands/workitems.md +127 -127
  19. package/git-sha.json +1 -1
  20. package/guides/agent-bootstrap.md +195 -195
  21. package/guides/agents/backend.md +102 -102
  22. package/guides/agents/content.md +94 -94
  23. package/guides/agents/cs2.md +56 -56
  24. package/guides/agents/data.md +86 -86
  25. package/guides/agents/design.md +77 -77
  26. package/guides/agents/frontend.md +91 -91
  27. package/guides/agents/infrastructure.md +81 -81
  28. package/guides/agents/setup.md +272 -272
  29. package/guides/agents/verify.md +119 -119
  30. package/guides/agents/viz.md +106 -106
  31. package/hooks/check-rdc-environment.js +378 -164
  32. package/hooks/lib/box-lock.js +207 -0
  33. package/package.json +1 -1
  34. package/scripts/install-rdc-skills.js +97 -8
  35. package/scripts/local-install-with-stop.sh +41 -0
  36. package/scripts/probe-box-lock.mjs +179 -0
  37. package/scripts/probe-installed-hooks.mjs +60 -0
  38. package/scripts/probe-lock-holders.mjs +36 -0
  39. package/scripts/self-test.mjs +1459 -1459
  40. package/scripts/validate-publish-manifests.js +502 -502
  41. package/skills/build/SKILL.md +578 -578
  42. package/skills/channel-formatter/SKILL.md +538 -538
  43. package/skills/collab/SKILL.md +239 -239
  44. package/skills/convert/SKILL.md +138 -138
  45. package/skills/deploy/SKILL.md +541 -541
  46. package/skills/design/SKILL.md +205 -205
  47. package/skills/env/SKILL.md +139 -139
  48. package/skills/fixit/SKILL.md +203 -203
  49. package/skills/handoff/SKILL.md +236 -236
  50. package/skills/housekeeping/SKILL.md +189 -189
  51. package/skills/onramp/SKILL.md +1459 -1459
  52. package/skills/overnight/SKILL.md +251 -251
  53. package/skills/plan/SKILL.md +345 -345
  54. package/skills/preplan/SKILL.md +90 -90
  55. package/skills/prototype/SKILL.md +150 -150
  56. package/skills/regen-media/SKILL.md +94 -94
  57. package/skills/release/SKILL.md +140 -140
  58. package/skills/report/SKILL.md +100 -100
  59. package/skills/review/SKILL.md +151 -151
  60. package/skills/self-test/SKILL.md +108 -108
  61. package/skills/status/SKILL.md +99 -99
  62. package/skills/tests/MATRIX.md +55 -55
  63. package/skills/tests/onramp.test.json +87 -87
  64. package/skills/tests/rdc-regen-media.test.json +29 -29
  65. package/skills/watch/SKILL.md +84 -84
  66. package/skills/workitems/SKILL.md +151 -151
@@ -1,345 +1,345 @@
1
- ---
2
- name: rdc:plan
3
- description: "Usage `rdc:plan <topic>` — No epic exists and you need architecture + task breakdown. Produces design decisions, tradeoffs, and Supabase epics/tasks with DoD checklists that feed rdc:build. Use after rdc:preplan or when given clear architectural direction."
4
- ---
5
-
6
- > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
- > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
- > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
9
-
10
- > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md`).
11
-
12
- > **Sandbox contract:** This skill honors `RDC_TEST=1` per `guides/agent-bootstrap.md` § RDC_TEST Sandbox Contract. Destructive external calls short-circuit under the flag. Supabase epic/task writes and git push are skipped under `RDC_TEST=1`.
13
-
14
-
15
- # rdc:plan — Architecture & Work Packages
16
-
17
- ## When to Use
18
- - After `/rdc:preplan` produced research findings
19
- - Project lead gives architectural direction ("build X with Y approach")
20
- - An epic exists but needs breakdown into implementable tasks
21
- - Before any large build session
22
- - Called by `rdc:overnight` when an epic has no child tasks
23
-
24
- ## Arguments
25
- - `rdc:plan <topic>` — interactive planning session
26
- - `rdc:plan <epic-id> --unattended` — silent mode for overnight builds
27
-
28
- ## Procedure
29
-
30
- 1. **Gather inputs:**
31
- - Research doc from preplan (if exists): `.rdc/research/<topic>.md` (fallback: `.rdc/research/<topic>.md`)
32
- - Project lead's architectural direction from conversation
33
- - Relevant CLAUDE.md files from affected packages
34
- - Existing Supabase epics: `SELECT get_open_epics()`
35
-
36
- 2. **Read the codebase** — understand current state:
37
- - What packages are affected?
38
- - What types/interfaces already exist?
39
- - What tests exist?
40
- - What's the dependency graph?
41
-
42
- ### ⛔ Before planning "wire fetchers into an existing view" — prove the view can render real data
43
- When a work package wires real data into a view that already renders, do NOT
44
- assume the view is fetch-ready (lesson 2026-06-16-build-verify-view-prop-api-before-wiring:
45
- a view imported its rows from a module-level `../mock/` constant with no data
46
- prop, so wiring an API fetcher changed nothing the user saw — and `tsc` + a
47
- route-200 probe both passed because they never prove real data renders). Before
48
- writing the WP, grep the target view for module-level `../mock/` (or `mockData`,
49
- `fixtures/`, hard-coded seed arrays) imports AND confirm a real data prop /
50
- loader seam exists:
51
- ```bash
52
- grep -nE "from ['\"].*/(mock|fixtures)" <target-view-file>
53
- ```
54
- If the view binds to a module-level mock and exposes no data prop, the WP MUST
55
- include removing the mock import and threading a real prop — not just adding a
56
- fetcher. "tsc + route 200" is NOT acceptance for "real data renders"; require a
57
- negative verifier (mock value is absent from the rendered output).
58
-
59
- 3. **Make design decisions** — for each major choice:
60
- - State the decision clearly
61
- - Document what was chosen and what was rejected
62
- - Explain WHY (tradeoff rationale)
63
- - Note consequences and reversibility
64
-
65
- ### Ops / runtime / observability surfaces — ask cloud-DB vs locally-observable, do NOT default to Supabase-SSOT
66
- For any ops, runtime, monitoring, or observability surface (process state, log
67
- tails, deploy health, queue depth, session liveness, local daemon status),
68
- surface the **data-source tradeoff as an explicit AskUserQuestion** rather than
69
- reaching for Supabase-as-single-source-of-truth by reflex (lesson
70
- 2026-06-20-plan-cloud-vs-local-source-tradeoff). Some of this data is only
71
- truthfully observable LOCALLY (the process/host itself) and a cloud-DB mirror
72
- is stale or lossy; other data genuinely belongs in Supabase. In interactive
73
- mode ask which source; in unattended mode escalate via advisor. Record the
74
- chosen source and its staleness window as a Design Decision.
75
-
76
- ### New shared `@regen/*` package — force an explicit consume-strategy Design Decision
77
- When the plan introduces a NEW shared `@regen/*` package, check who consumes it.
78
- If ANY consumer is a non-Next / CJS context (a Node CLI, a PM2 script, a Jest
79
- suite, an MCP server, a `.cjs` tool) — not just Next.js apps that transpile ESM
80
- workspace packages — the plan MUST contain an explicit **consume-strategy Design
81
- Decision** (lesson 2026-06-20-plan-shared-lib-cjs-esm-dist-gap: an ESM-only
82
- `dist` shipped fine to Next consumers but `require()` from a CJS consumer threw
83
- `ERR_REQUIRE_ESM` at runtime). The decision picks ONE: emit a CJS (or dual
84
- ESM+CJS) `dist`, OR have the CJS consumer install a TS/ESM loader (e.g.
85
- `tsx`/`ts-node`). Name the consumers and the chosen strategy; do not leave the
86
- module format implicit.
87
-
88
- 4. **Define work packages** — break into agent-dispatchable units:
89
- - Each work package = one agent assignment
90
- - No file overlap between packages
91
- - Each package has: scope, files to create/modify, test plan
92
- - Assign an agent type to each work package from the typed dispatch table in rdc:build. Include the guide file path (from `.rdc/guides/`, fallback `.rdc/guides/`) in each work package description.
93
- - Estimate: small (1 agent, <500 LOC), medium (1 agent, 500-1500 LOC), large (needs splitting)
94
-
95
- 4b. **Build the checklist decomposition matrix (MANDATORY PRE-BUILD GATE):**
96
-
97
- Before writing Supabase work items, create a `## Checklist Decomposition Matrix`
98
- in the plan doc. This matrix is the source of truth for task checklists and
99
- build verification.
100
-
101
- Required columns:
102
- - Work item ID or placeholder
103
- - Atomic deliverable
104
- - Surface type: `screen`, `state`, `action`, `api`, `db`, `migration`, `component`, `asset`, `tool`, `test`, `doc`
105
- - Route or file path
106
- - Preconditions / fixture data
107
- - User or agent action
108
- - Expected UI/API/DB result
109
- - Verification artifact: test name, route probe, Playwright screenshot, SQL query, API response, type-check, migration proof, or CLI transcript
110
- - Owner work package
111
- - Status
112
-
113
- Atomicity rubric:
114
- - One observable behavior per row.
115
- - Each row names a concrete route or file path.
116
- - Each row names one concrete verification artifact.
117
- - Each row can independently pass or fail.
118
- - Each row is small enough for a worker to implement and tick without hidden intent.
119
-
120
- Required decomposition by surface:
121
- - UI screens: list empty, loading, loaded, error, create, edit, detail, delete/archive guard, mobile, and auth states where applicable.
122
- - UI actions: open, search, filter, select, duplicate, save, assign, activate, archive, delete, import, apply, cancel where applicable.
123
- - API routes: successful read/write, validation failure, unauthorized/forbidden, and side-effect verification where applicable.
124
- - DB/migrations: table/column/index/policy/trigger/function, FK/guard, rollback or smoke query, and type exposure.
125
- - CLI/sidebar/local tools: start, attach, enqueue, poll, reply, timeout/not-found, and live refresh where applicable.
126
- - Visual work: each named screenshot and visual checkpoint gets its own row.
127
- - Cross-system workflows: each handoff boundary gets its own row.
128
-
129
- Per-surface completeness floors — ATTESTED BY SURFACE AREA (not a flat minimum):
130
- A checklist MUST carry at minimum one attested `decomp-*` row for EACH applicable item
131
- below. This is a COMPLETENESS requirement measured against the surfaces the WP touches —
132
- decompose the whole surface area; do not stop at a token few rows.
133
- - UI screen (per screen the WP renders): a row for EACH applicable state — loaded, empty,
134
- loading, error, detail — plus mobile and auth-gate where applicable. Floor: >= 6 rows PER screen.
135
- - UI actions (per interactive surface): one row for EACH action that exists — open, search,
136
- filter, select, create, edit, duplicate, save, assign, activate, archive, delete, import,
137
- apply, cancel.
138
- - API route (per route): success-read, success-write, validation-failure (4xx),
139
- unauthorized/forbidden, and side-effect verification. Floor: >= 4 rows per route.
140
- - DB / migration: ONE row per database object — per table, per non-trivial column-group, per
141
- index, per RLS policy, per trigger, per function/RPC, per FK/guard — plus rollback/smoke and
142
- type-exposure. A 10-table WP therefore carries ~15-20 rows, not 5.
143
- - CLI / sidebar / local tool: start, attach, enqueue, poll, reply, timeout/not-found,
144
- live-refresh. Floor: >= 6 rows.
145
- - Visual: one row per named screenshot/checkpoint. Cross-system: one row per handoff boundary.
146
-
147
- HARD FLOORS — reject the checklist (do NOT create work items) if any is violated:
148
- - Every implementation task carries >= 10 attested `decomp-*`/`test-*` rows.
149
- - A MULTI-SURFACE WP (two or more of screen/api/db/tool) carries the SUM of its per-surface
150
- floors — typically 12-20 rows. A flat 5-6-row checklist for a real feature WP is a REJECT,
151
- not a pass.
152
- - COVERAGE: the checklist covers EVERY surface the WP declares. A WP touching screen+api+db
153
- that lists only db rows FAILS the coverage gate.
154
- - ATTESTATION: every row names its surface + ONE concrete verification artifact (test name,
155
- route probe, Playwright screenshot, SQL query, migration proof, CLI transcript). A row with
156
- no attestation artifact is a REJECT.
157
- - If a WP genuinely has < 10 observable behaviors, SPLIT it or justify the low count explicitly
158
- in the Quality Gate `deferred:` note — never silently ship a thin checklist.
159
-
160
- Reject these checklist items as too coarse:
161
- - "theme management works"
162
- - "build all screens"
163
- - "verify UI"
164
- - "integration complete"
165
- - "tests pass"
166
-
167
- Replace them with rows like:
168
- - `decomp-ui-theme-manager-loaded: /brands/[id]/theme shows owned theme rows with status, project usage, and actions; evidence: Playwright screenshot`
169
- - `decomp-action-duplicate-theme: duplicate submits source brand_theme_id and creates a new editable brand-owned copy; evidence: vitest + DB query`
170
- - `decomp-api-import-validation: POST /api/tools/theme-import rejects missing source URL with 400 JSON error; evidence: route probe`
171
-
172
- Add a `## Checklist Quality Gate` section with:
173
- - `verdict: PASS` only when EVERY row passes the rubric AND every WP meets the per-surface
174
- completeness floors above (each declared surface covered; >= 10 attested rows; multi-surface =
175
- sum of surface floors) AND every row carries a verification artifact.
176
- - `per_wp_row_counts:` list each WP and its attested row count so a reviewer sees at a glance
177
- that no feature WP is under-decomposed (no 5-6-row feature WP).
178
- - `coverage:` per WP, list the surfaces it declares and confirm each is covered by >= its floor.
179
- - `failures:` list any coarse, under-decomposed, uncovered-surface, missing, duplicate, or
180
- unattested rows.
181
- - `deferred:` list any explicit out-of-scope rows (with the reason a low count is justified).
182
-
183
- Do not create build-ready work items unless this gate is `PASS`. A `PASS` with any feature WP
184
- under 10 attested rows, or any declared surface left uncovered, is invalid.
185
-
186
- 5. **Write a test plan for each work package (MANDATORY):**
187
-
188
- Every work package MUST have a `test_plan` section with specific, concrete test items. Each item has a type:
189
-
190
- | Type | What it proves | How agent verifies | Example |
191
- |------|---------------|-------------------|---------|
192
- | `assert` | Logic is correct | Write a vitest test — input → expected output | `extractCode("```tsx\nfoo\n```") returns "foo"` |
193
- | `smoke` | It runs without crashing | Run command, check exit code / HTTP status | `tsc --noEmit passes`, `GET /api/layout/scan returns 200` |
194
- | `visual` | It looks right | Delegate to UI audit tool with specific checkpoints | `"/layout page renders container tree, not login screen"` |
195
- | `contract` | Interface matches spec | Check exports, prop types, response shape | `ScanResult has { roots: ContainerNode[] }` |
196
-
197
- **Rules for writing test plan items:**
198
- - Every item must be a specific, falsifiable assertion — not "write tests" or "verify it works"
199
- - Every item must map to one or more rows in the Checklist Decomposition Matrix.
200
- - A test plan item may summarize multiple checks only when the matrix still keeps those checks as separate atomic rows.
201
- - New functions/modules MUST have at least one `assert` item
202
- - API routes MUST have at least one `smoke` item
203
- - UI pages MUST have at least one `visual` item
204
- - New exports/types MUST have at least one `contract` item
205
- - `assert` and `smoke` are mandatory for every work package. `visual` and `contract` when applicable.
206
-
207
- **Example test plan in a plan doc:**
208
- ```markdown
209
- ### WP-2: AST Scanner
210
- **Test plan:**
211
- - assert: `scanFile` returns only Window/Frame/Pane/SubPane nodes, not Badge/Button
212
- - assert: SubPane nested directly in root produces a warning
213
- - assert: Valid Window > Frame > Pane > SubPane nesting produces no warnings
214
- - smoke: `GET /api/layout/scan?dir=apps/studio/src` returns 200 with JSON body
215
- - smoke: `npx tsc --noEmit` exits 0
216
- - contract: `ScanResult` has shape `{ filePath: string, roots: ContainerNode[], warnings: ScanWarning[] }`
217
- ```
218
-
219
- 6. **Write plan doc** to `.rdc/plans/<topic-slug>.md` (fallback: `.rdc/plans/<topic-slug>.md` if `.rdc/` does not exist):
220
- ```markdown
221
- # Plan: <Topic>
222
- > Generated: <date> | Epic: <id if exists>
223
-
224
- ## Goal
225
- ## Design Decisions
226
- ## Work Packages (each with test plan)
227
- ## Checklist Decomposition Matrix
228
- ## Checklist Quality Gate
229
- ## Sequencing (what can parallelize, what depends on what)
230
- ## Risks & Mitigations
231
- ```
232
-
233
- 7. **Create Supabase epic + child tasks:**
234
- - Epic via `insert_work_item(p_item_type := 'epic', p_definition_of_done := '[...]'::jsonb, ...)`
235
- - Epic DoD MUST include: `{"id":"test-plan-verified","text":"All test plan items implemented and passing","required":true,"checked":false}`
236
- - Set `p_definition_of_done` on the epic — child tasks inserted under it will auto-inherit it as their checklist
237
- - One task per work package via `insert_work_item(p_parent_id := <epic_id>, ...)` — checklist auto-hydrated from epic's DoD
238
- - **Additionally, write decomposition rows as checklist items** on each task, using id format `decomp-<surface>-<slug>`.
239
- The task checklist MUST include both the atomic `decomp-*` rows and the `test-*` verification rows.
240
- The `decomp-*` row text must include the route/file, action, expected result, and evidence artifact.
241
- - **Write test plan items as checklist items** on each task, using id format `test-<type>-<slug>`:
242
- ```sql
243
- SELECT insert_work_item(
244
- p_parent_id := '<epic_id>',
245
- p_title := 'WP-2: AST Scanner',
246
- p_checklist := '[
247
- {"id":"decomp-api-scan-success","text":"api: GET /api/layout/scan?dir=apps/studio/src returns 200 JSON with roots[] and warnings[]; evidence: route probe output","required":true,"checked":false},
248
- {"id":"test-assert-scanner-filters","text":"assert: scanFile returns only container components","required":true,"checked":false},
249
- {"id":"test-assert-nesting-warn","text":"assert: invalid nesting produces warnings","required":true,"checked":false},
250
- {"id":"test-smoke-scan-api","text":"smoke: GET /api/layout/scan returns 200","required":true,"checked":false},
251
- {"id":"test-contract-scanresult","text":"contract: ScanResult shape matches spec","required":true,"checked":false},
252
- {"id":"tsc-clean","text":"npx tsc --noEmit passes","required":true,"checked":false}
253
- ]'::jsonb
254
- );
255
- ```
256
- - Agents MUST tick each `decomp-*` and `test-*` checklist item as they implement/verify it via `update_checklist_item(..., p_actor_session_id := '<agent-session-id>', p_actor_role := 'agent')`
257
- - Agents submit `implementation_report.codeflow_post`, then move work to `review`; validators close `done`
258
- - `update_work_item_status('done', ..., p_actor_role := 'validator')` rejects missing reports, unchecked required items, and supervisor/validator re-ticks
259
- - Set priorities: urgent/high/normal based on sequencing
260
-
261
- 7. **Report results:**
262
- - Interactive: present the plan for approval before building
263
- - Unattended: skip approval, proceed immediately, emit status block:
264
- ```
265
- PLAN_STATUS: { epic_id, task_count, doc_path, waves }
266
- ```
267
-
268
- ## Unattended Escalation
269
-
270
- When `--unattended` and genuine architectural ambiguity is detected — meaning multiple
271
- valid approaches exist with significantly different tradeoffs (not just minor style choices)
272
- — escalate via the advisor tool. Provide: the decision point, the options with tradeoffs,
273
- and the project context. Resume with advisor's recommendation. If advisor is unavailable,
274
- choose the most conservative/reversible approach and document the decision.
275
-
276
- ## Rules
277
- - Interactive: ALWAYS get approval before proceeding to build
278
- - Unattended: proceed immediately without approval
279
- - Plan doc goes in `.rdc/plans/` (fallback: `.rdc/plans/` if `.rdc/` does not exist) — not `.planning/`
280
- - Each work package must be independently executable by an agent
281
- - No file overlap between work packages
282
- - Include test requirements in every work package
283
- - Reference affected CLAUDE.md files in each work package description
284
- - Reference the relevant guide file from `.rdc/guides/` (fallback: `.rdc/guides/`) for agent context
285
- - **If a work package involves creating a new deployed app:** the task description MUST say "Use `rdc:deploy new <slug>` — do NOT create the Coolify app manually. Read `docs/runbooks/coolify-app-templates.json` first." Assign it to an `infra` agent. This is a hard rule — manually created apps have consistently been misconfigured.
286
-
287
- ## New App Q&A (mandatory before writing any infra task that creates a Coolify app)
288
-
289
- If the plan includes deploying a new app, these questions MUST be answered — in interactive mode, ask the user; in unattended mode, escalate via advisor. Do NOT write the infra task until all answers are locked in. Record answers in the plan doc and embed them directly in the task description.
290
-
291
- **Never guess. Wrong project = delete and recreate. There is no move operation in Coolify.**
292
-
293
- ```
294
- Q1. Which Coolify project does this app belong to?
295
- → Read docs/runbooks/coolify-app-templates.json → _infrastructure.projects
296
- → Match by area: design-system / prt / rdc / rdc-marketing / zoen / lifeai / place-fund / infrastructure / ai-platform
297
- → If unsure: ASK. Do not infer from app name alone.
298
- → Record: project_uuid + environment_uuid (staging or production)
299
-
300
- Q2. What is the domain?
301
- → staging wildcard subdomain? (staging / internal tools)
302
- → Custom subdomain on an existing zone? (e.g. app.regendevcorp.com)
303
- → Apex domain? (e.g. place.fund itself)
304
- → Domain on a different zone entirely? (e.g. skymesasouth.com)
305
-
306
- Q3. Is this domain already in our Cloudflare account?
307
- → Yes, zone exists → which zone?
308
- → No → who controls the nameservers? Does the registrar point NS to Cloudflare?
309
- → If NS not delegated to Cloudflare: A record in Cloudflare does nothing — must go to registrar
310
-
311
- Q4. Does this app need Cloudflare proxy (orange cloud)?
312
- → Traefik/Let's Encrypt HTTP-01 staging wildcards are often safest unproxied; verify your platform's DNS requirements.
313
- → Custom domain needing DDoS/CDN: proxy OK only if SSL mode = Full (strict) + origin cert provisioned
314
- → Any doubt: start unproxied, add proxy after confirming SSL works
315
-
316
- Q5. What SSL path?
317
- → Traefik + Let's Encrypt (default for all unproxied): automatic, no action needed
318
- → Cloudflare proxy + Full (strict): need origin cert from Cloudflare dashboard first
319
- → Nixpacks build pack: DO NOT USE for any app that needs custom SSL setup — nixpacks
320
- containers have incompatible SSL configuration requirements. Use dockerfile build pack only.
321
- ```
322
-
323
- Embed all five answers into the infra task description verbatim before handing to the agent.
324
-
325
- ## MCP / infra plans — mirror the closest sibling deployment FIRST
326
-
327
- Before writing any plan that stands up an MCP server or infra service, read how the
328
- **closest existing sibling** is actually deployed (`.mcp.json` + its PM2/tunnel or
329
- Coolify/Docker config) and **cite it in the plan**. Two MCP topologies coexist and
330
- applying the wrong reference over-engineers the design (lesson
331
- 2026-06-10-plan-mirror-sibling-mcp-pattern: a first MCP plan proposed
332
- Docker + Coolify + a Cloudflare-proxied origin + runtime GitHub-pull when the real
333
- pattern was a local Node process + clauth-managed tunnel, exactly like codeflow-mcp):
334
-
335
- - **LOCAL-MCP reference = `codeflow-mcp`** — local Node process (`:3109`) + clauth-managed
336
- tunnel ingress. Mirror this for MCPs that live on Dave's box.
337
- - **REMOTE-MCP reference = `web-research` / `regen-media`** — Coolify/Docker, Cloudflare-proxied
338
- origin (`.claude/rules/mcp-endpoint-design.md` covers the REMOTE class only).
339
-
340
- Decide which class applies and name the sibling in the plan's Design Decisions before
341
- designing topology. Do not reach for the REMOTE rule by default.
342
-
343
- ## Capture lessons (exit step)
344
-
345
- Before the final verdict line, follow `.rdc/guides/lessons-learned-spec.md` § Capture procedure. If this run taught something non-obvious — a first root-cause theory that turned out wrong, the documented/standard path not working, a missing gate or check that cost a round, or a surprising tool/infra behavior — write one `.rdc/lessons/<YYYY-MM-DD>-plan-<short-slug>.md` per lesson using the schema in that spec. Set `scope` (`simple` | `architectural`) and `status` (`open`, or `applied` if you shipped the fix in this same run, with the commit linked). Commit the lesson file(s) on `develop` alongside the run's other commits, and note "N lessons captured" in your verdict/summary. A run that taught nothing writes nothing — absence is the default.
1
+ ---
2
+ name: rdc:plan
3
+ description: "Usage `rdc:plan <topic>` — No epic exists and you need architecture + task breakdown. Produces design decisions, tradeoffs, and Supabase epics/tasks with DoD checklists that feed rdc:build. Use after rdc:preplan or when given clear architectural direction."
4
+ ---
5
+
6
+ > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
+ > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
+ > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
9
+
10
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md`).
11
+
12
+ > **Sandbox contract:** This skill honors `RDC_TEST=1` per `guides/agent-bootstrap.md` § RDC_TEST Sandbox Contract. Destructive external calls short-circuit under the flag. Supabase epic/task writes and git push are skipped under `RDC_TEST=1`.
13
+
14
+
15
+ # rdc:plan — Architecture & Work Packages
16
+
17
+ ## When to Use
18
+ - After `/rdc:preplan` produced research findings
19
+ - Project lead gives architectural direction ("build X with Y approach")
20
+ - An epic exists but needs breakdown into implementable tasks
21
+ - Before any large build session
22
+ - Called by `rdc:overnight` when an epic has no child tasks
23
+
24
+ ## Arguments
25
+ - `rdc:plan <topic>` — interactive planning session
26
+ - `rdc:plan <epic-id> --unattended` — silent mode for overnight builds
27
+
28
+ ## Procedure
29
+
30
+ 1. **Gather inputs:**
31
+ - Research doc from preplan (if exists): `.rdc/research/<topic>.md` (fallback: `.rdc/research/<topic>.md`)
32
+ - Project lead's architectural direction from conversation
33
+ - Relevant CLAUDE.md files from affected packages
34
+ - Existing Supabase epics: `SELECT get_open_epics()`
35
+
36
+ 2. **Read the codebase** — understand current state:
37
+ - What packages are affected?
38
+ - What types/interfaces already exist?
39
+ - What tests exist?
40
+ - What's the dependency graph?
41
+
42
+ ### ⛔ Before planning "wire fetchers into an existing view" — prove the view can render real data
43
+ When a work package wires real data into a view that already renders, do NOT
44
+ assume the view is fetch-ready (lesson 2026-06-16-build-verify-view-prop-api-before-wiring:
45
+ a view imported its rows from a module-level `../mock/` constant with no data
46
+ prop, so wiring an API fetcher changed nothing the user saw — and `tsc` + a
47
+ route-200 probe both passed because they never prove real data renders). Before
48
+ writing the WP, grep the target view for module-level `../mock/` (or `mockData`,
49
+ `fixtures/`, hard-coded seed arrays) imports AND confirm a real data prop /
50
+ loader seam exists:
51
+ ```bash
52
+ grep -nE "from ['\"].*/(mock|fixtures)" <target-view-file>
53
+ ```
54
+ If the view binds to a module-level mock and exposes no data prop, the WP MUST
55
+ include removing the mock import and threading a real prop — not just adding a
56
+ fetcher. "tsc + route 200" is NOT acceptance for "real data renders"; require a
57
+ negative verifier (mock value is absent from the rendered output).
58
+
59
+ 3. **Make design decisions** — for each major choice:
60
+ - State the decision clearly
61
+ - Document what was chosen and what was rejected
62
+ - Explain WHY (tradeoff rationale)
63
+ - Note consequences and reversibility
64
+
65
+ ### Ops / runtime / observability surfaces — ask cloud-DB vs locally-observable, do NOT default to Supabase-SSOT
66
+ For any ops, runtime, monitoring, or observability surface (process state, log
67
+ tails, deploy health, queue depth, session liveness, local daemon status),
68
+ surface the **data-source tradeoff as an explicit AskUserQuestion** rather than
69
+ reaching for Supabase-as-single-source-of-truth by reflex (lesson
70
+ 2026-06-20-plan-cloud-vs-local-source-tradeoff). Some of this data is only
71
+ truthfully observable LOCALLY (the process/host itself) and a cloud-DB mirror
72
+ is stale or lossy; other data genuinely belongs in Supabase. In interactive
73
+ mode ask which source; in unattended mode escalate via advisor. Record the
74
+ chosen source and its staleness window as a Design Decision.
75
+
76
+ ### New shared `@regen/*` package — force an explicit consume-strategy Design Decision
77
+ When the plan introduces a NEW shared `@regen/*` package, check who consumes it.
78
+ If ANY consumer is a non-Next / CJS context (a Node CLI, a PM2 script, a Jest
79
+ suite, an MCP server, a `.cjs` tool) — not just Next.js apps that transpile ESM
80
+ workspace packages — the plan MUST contain an explicit **consume-strategy Design
81
+ Decision** (lesson 2026-06-20-plan-shared-lib-cjs-esm-dist-gap: an ESM-only
82
+ `dist` shipped fine to Next consumers but `require()` from a CJS consumer threw
83
+ `ERR_REQUIRE_ESM` at runtime). The decision picks ONE: emit a CJS (or dual
84
+ ESM+CJS) `dist`, OR have the CJS consumer install a TS/ESM loader (e.g.
85
+ `tsx`/`ts-node`). Name the consumers and the chosen strategy; do not leave the
86
+ module format implicit.
87
+
88
+ 4. **Define work packages** — break into agent-dispatchable units:
89
+ - Each work package = one agent assignment
90
+ - No file overlap between packages
91
+ - Each package has: scope, files to create/modify, test plan
92
+ - Assign an agent type to each work package from the typed dispatch table in rdc:build. Include the guide file path (from `.rdc/guides/`, fallback `.rdc/guides/`) in each work package description.
93
+ - Estimate: small (1 agent, <500 LOC), medium (1 agent, 500-1500 LOC), large (needs splitting)
94
+
95
+ 4b. **Build the checklist decomposition matrix (MANDATORY PRE-BUILD GATE):**
96
+
97
+ Before writing Supabase work items, create a `## Checklist Decomposition Matrix`
98
+ in the plan doc. This matrix is the source of truth for task checklists and
99
+ build verification.
100
+
101
+ Required columns:
102
+ - Work item ID or placeholder
103
+ - Atomic deliverable
104
+ - Surface type: `screen`, `state`, `action`, `api`, `db`, `migration`, `component`, `asset`, `tool`, `test`, `doc`
105
+ - Route or file path
106
+ - Preconditions / fixture data
107
+ - User or agent action
108
+ - Expected UI/API/DB result
109
+ - Verification artifact: test name, route probe, Playwright screenshot, SQL query, API response, type-check, migration proof, or CLI transcript
110
+ - Owner work package
111
+ - Status
112
+
113
+ Atomicity rubric:
114
+ - One observable behavior per row.
115
+ - Each row names a concrete route or file path.
116
+ - Each row names one concrete verification artifact.
117
+ - Each row can independently pass or fail.
118
+ - Each row is small enough for a worker to implement and tick without hidden intent.
119
+
120
+ Required decomposition by surface:
121
+ - UI screens: list empty, loading, loaded, error, create, edit, detail, delete/archive guard, mobile, and auth states where applicable.
122
+ - UI actions: open, search, filter, select, duplicate, save, assign, activate, archive, delete, import, apply, cancel where applicable.
123
+ - API routes: successful read/write, validation failure, unauthorized/forbidden, and side-effect verification where applicable.
124
+ - DB/migrations: table/column/index/policy/trigger/function, FK/guard, rollback or smoke query, and type exposure.
125
+ - CLI/sidebar/local tools: start, attach, enqueue, poll, reply, timeout/not-found, and live refresh where applicable.
126
+ - Visual work: each named screenshot and visual checkpoint gets its own row.
127
+ - Cross-system workflows: each handoff boundary gets its own row.
128
+
129
+ Per-surface completeness floors — ATTESTED BY SURFACE AREA (not a flat minimum):
130
+ A checklist MUST carry at minimum one attested `decomp-*` row for EACH applicable item
131
+ below. This is a COMPLETENESS requirement measured against the surfaces the WP touches —
132
+ decompose the whole surface area; do not stop at a token few rows.
133
+ - UI screen (per screen the WP renders): a row for EACH applicable state — loaded, empty,
134
+ loading, error, detail — plus mobile and auth-gate where applicable. Floor: >= 6 rows PER screen.
135
+ - UI actions (per interactive surface): one row for EACH action that exists — open, search,
136
+ filter, select, create, edit, duplicate, save, assign, activate, archive, delete, import,
137
+ apply, cancel.
138
+ - API route (per route): success-read, success-write, validation-failure (4xx),
139
+ unauthorized/forbidden, and side-effect verification. Floor: >= 4 rows per route.
140
+ - DB / migration: ONE row per database object — per table, per non-trivial column-group, per
141
+ index, per RLS policy, per trigger, per function/RPC, per FK/guard — plus rollback/smoke and
142
+ type-exposure. A 10-table WP therefore carries ~15-20 rows, not 5.
143
+ - CLI / sidebar / local tool: start, attach, enqueue, poll, reply, timeout/not-found,
144
+ live-refresh. Floor: >= 6 rows.
145
+ - Visual: one row per named screenshot/checkpoint. Cross-system: one row per handoff boundary.
146
+
147
+ HARD FLOORS — reject the checklist (do NOT create work items) if any is violated:
148
+ - Every implementation task carries >= 10 attested `decomp-*`/`test-*` rows.
149
+ - A MULTI-SURFACE WP (two or more of screen/api/db/tool) carries the SUM of its per-surface
150
+ floors — typically 12-20 rows. A flat 5-6-row checklist for a real feature WP is a REJECT,
151
+ not a pass.
152
+ - COVERAGE: the checklist covers EVERY surface the WP declares. A WP touching screen+api+db
153
+ that lists only db rows FAILS the coverage gate.
154
+ - ATTESTATION: every row names its surface + ONE concrete verification artifact (test name,
155
+ route probe, Playwright screenshot, SQL query, migration proof, CLI transcript). A row with
156
+ no attestation artifact is a REJECT.
157
+ - If a WP genuinely has < 10 observable behaviors, SPLIT it or justify the low count explicitly
158
+ in the Quality Gate `deferred:` note — never silently ship a thin checklist.
159
+
160
+ Reject these checklist items as too coarse:
161
+ - "theme management works"
162
+ - "build all screens"
163
+ - "verify UI"
164
+ - "integration complete"
165
+ - "tests pass"
166
+
167
+ Replace them with rows like:
168
+ - `decomp-ui-theme-manager-loaded: /brands/[id]/theme shows owned theme rows with status, project usage, and actions; evidence: Playwright screenshot`
169
+ - `decomp-action-duplicate-theme: duplicate submits source brand_theme_id and creates a new editable brand-owned copy; evidence: vitest + DB query`
170
+ - `decomp-api-import-validation: POST /api/tools/theme-import rejects missing source URL with 400 JSON error; evidence: route probe`
171
+
172
+ Add a `## Checklist Quality Gate` section with:
173
+ - `verdict: PASS` only when EVERY row passes the rubric AND every WP meets the per-surface
174
+ completeness floors above (each declared surface covered; >= 10 attested rows; multi-surface =
175
+ sum of surface floors) AND every row carries a verification artifact.
176
+ - `per_wp_row_counts:` list each WP and its attested row count so a reviewer sees at a glance
177
+ that no feature WP is under-decomposed (no 5-6-row feature WP).
178
+ - `coverage:` per WP, list the surfaces it declares and confirm each is covered by >= its floor.
179
+ - `failures:` list any coarse, under-decomposed, uncovered-surface, missing, duplicate, or
180
+ unattested rows.
181
+ - `deferred:` list any explicit out-of-scope rows (with the reason a low count is justified).
182
+
183
+ Do not create build-ready work items unless this gate is `PASS`. A `PASS` with any feature WP
184
+ under 10 attested rows, or any declared surface left uncovered, is invalid.
185
+
186
+ 5. **Write a test plan for each work package (MANDATORY):**
187
+
188
+ Every work package MUST have a `test_plan` section with specific, concrete test items. Each item has a type:
189
+
190
+ | Type | What it proves | How agent verifies | Example |
191
+ |------|---------------|-------------------|---------|
192
+ | `assert` | Logic is correct | Write a vitest test — input → expected output | `extractCode("```tsx\nfoo\n```") returns "foo"` |
193
+ | `smoke` | It runs without crashing | Run command, check exit code / HTTP status | `tsc --noEmit passes`, `GET /api/layout/scan returns 200` |
194
+ | `visual` | It looks right | Delegate to UI audit tool with specific checkpoints | `"/layout page renders container tree, not login screen"` |
195
+ | `contract` | Interface matches spec | Check exports, prop types, response shape | `ScanResult has { roots: ContainerNode[] }` |
196
+
197
+ **Rules for writing test plan items:**
198
+ - Every item must be a specific, falsifiable assertion — not "write tests" or "verify it works"
199
+ - Every item must map to one or more rows in the Checklist Decomposition Matrix.
200
+ - A test plan item may summarize multiple checks only when the matrix still keeps those checks as separate atomic rows.
201
+ - New functions/modules MUST have at least one `assert` item
202
+ - API routes MUST have at least one `smoke` item
203
+ - UI pages MUST have at least one `visual` item
204
+ - New exports/types MUST have at least one `contract` item
205
+ - `assert` and `smoke` are mandatory for every work package. `visual` and `contract` when applicable.
206
+
207
+ **Example test plan in a plan doc:**
208
+ ```markdown
209
+ ### WP-2: AST Scanner
210
+ **Test plan:**
211
+ - assert: `scanFile` returns only Window/Frame/Pane/SubPane nodes, not Badge/Button
212
+ - assert: SubPane nested directly in root produces a warning
213
+ - assert: Valid Window > Frame > Pane > SubPane nesting produces no warnings
214
+ - smoke: `GET /api/layout/scan?dir=apps/studio/src` returns 200 with JSON body
215
+ - smoke: `npx tsc --noEmit` exits 0
216
+ - contract: `ScanResult` has shape `{ filePath: string, roots: ContainerNode[], warnings: ScanWarning[] }`
217
+ ```
218
+
219
+ 6. **Write plan doc** to `.rdc/plans/<topic-slug>.md` (fallback: `.rdc/plans/<topic-slug>.md` if `.rdc/` does not exist):
220
+ ```markdown
221
+ # Plan: <Topic>
222
+ > Generated: <date> | Epic: <id if exists>
223
+
224
+ ## Goal
225
+ ## Design Decisions
226
+ ## Work Packages (each with test plan)
227
+ ## Checklist Decomposition Matrix
228
+ ## Checklist Quality Gate
229
+ ## Sequencing (what can parallelize, what depends on what)
230
+ ## Risks & Mitigations
231
+ ```
232
+
233
+ 7. **Create Supabase epic + child tasks:**
234
+ - Epic via `insert_work_item(p_item_type := 'epic', p_definition_of_done := '[...]'::jsonb, ...)`
235
+ - Epic DoD MUST include: `{"id":"test-plan-verified","text":"All test plan items implemented and passing","required":true,"checked":false}`
236
+ - Set `p_definition_of_done` on the epic — child tasks inserted under it will auto-inherit it as their checklist
237
+ - One task per work package via `insert_work_item(p_parent_id := <epic_id>, ...)` — checklist auto-hydrated from epic's DoD
238
+ - **Additionally, write decomposition rows as checklist items** on each task, using id format `decomp-<surface>-<slug>`.
239
+ The task checklist MUST include both the atomic `decomp-*` rows and the `test-*` verification rows.
240
+ The `decomp-*` row text must include the route/file, action, expected result, and evidence artifact.
241
+ - **Write test plan items as checklist items** on each task, using id format `test-<type>-<slug>`:
242
+ ```sql
243
+ SELECT insert_work_item(
244
+ p_parent_id := '<epic_id>',
245
+ p_title := 'WP-2: AST Scanner',
246
+ p_checklist := '[
247
+ {"id":"decomp-api-scan-success","text":"api: GET /api/layout/scan?dir=apps/studio/src returns 200 JSON with roots[] and warnings[]; evidence: route probe output","required":true,"checked":false},
248
+ {"id":"test-assert-scanner-filters","text":"assert: scanFile returns only container components","required":true,"checked":false},
249
+ {"id":"test-assert-nesting-warn","text":"assert: invalid nesting produces warnings","required":true,"checked":false},
250
+ {"id":"test-smoke-scan-api","text":"smoke: GET /api/layout/scan returns 200","required":true,"checked":false},
251
+ {"id":"test-contract-scanresult","text":"contract: ScanResult shape matches spec","required":true,"checked":false},
252
+ {"id":"tsc-clean","text":"npx tsc --noEmit passes","required":true,"checked":false}
253
+ ]'::jsonb
254
+ );
255
+ ```
256
+ - Agents MUST tick each `decomp-*` and `test-*` checklist item as they implement/verify it via `update_checklist_item(..., p_actor_session_id := '<agent-session-id>', p_actor_role := 'agent')`
257
+ - Agents submit `implementation_report.codeflow_post`, then move work to `review`; validators close `done`
258
+ - `update_work_item_status('done', ..., p_actor_role := 'validator')` rejects missing reports, unchecked required items, and supervisor/validator re-ticks
259
+ - Set priorities: urgent/high/normal based on sequencing
260
+
261
+ 7. **Report results:**
262
+ - Interactive: present the plan for approval before building
263
+ - Unattended: skip approval, proceed immediately, emit status block:
264
+ ```
265
+ PLAN_STATUS: { epic_id, task_count, doc_path, waves }
266
+ ```
267
+
268
+ ## Unattended Escalation
269
+
270
+ When `--unattended` and genuine architectural ambiguity is detected — meaning multiple
271
+ valid approaches exist with significantly different tradeoffs (not just minor style choices)
272
+ — escalate via the advisor tool. Provide: the decision point, the options with tradeoffs,
273
+ and the project context. Resume with advisor's recommendation. If advisor is unavailable,
274
+ choose the most conservative/reversible approach and document the decision.
275
+
276
+ ## Rules
277
+ - Interactive: ALWAYS get approval before proceeding to build
278
+ - Unattended: proceed immediately without approval
279
+ - Plan doc goes in `.rdc/plans/` (fallback: `.rdc/plans/` if `.rdc/` does not exist) — not `.planning/`
280
+ - Each work package must be independently executable by an agent
281
+ - No file overlap between work packages
282
+ - Include test requirements in every work package
283
+ - Reference affected CLAUDE.md files in each work package description
284
+ - Reference the relevant guide file from `.rdc/guides/` (fallback: `.rdc/guides/`) for agent context
285
+ - **If a work package involves creating a new deployed app:** the task description MUST say "Use `rdc:deploy new <slug>` — do NOT create the Coolify app manually. Read `docs/runbooks/coolify-app-templates.json` first." Assign it to an `infra` agent. This is a hard rule — manually created apps have consistently been misconfigured.
286
+
287
+ ## New App Q&A (mandatory before writing any infra task that creates a Coolify app)
288
+
289
+ If the plan includes deploying a new app, these questions MUST be answered — in interactive mode, ask the user; in unattended mode, escalate via advisor. Do NOT write the infra task until all answers are locked in. Record answers in the plan doc and embed them directly in the task description.
290
+
291
+ **Never guess. Wrong project = delete and recreate. There is no move operation in Coolify.**
292
+
293
+ ```
294
+ Q1. Which Coolify project does this app belong to?
295
+ → Read docs/runbooks/coolify-app-templates.json → _infrastructure.projects
296
+ → Match by area: design-system / prt / rdc / rdc-marketing / zoen / lifeai / place-fund / infrastructure / ai-platform
297
+ → If unsure: ASK. Do not infer from app name alone.
298
+ → Record: project_uuid + environment_uuid (staging or production)
299
+
300
+ Q2. What is the domain?
301
+ → staging wildcard subdomain? (staging / internal tools)
302
+ → Custom subdomain on an existing zone? (e.g. app.regendevcorp.com)
303
+ → Apex domain? (e.g. place.fund itself)
304
+ → Domain on a different zone entirely? (e.g. skymesasouth.com)
305
+
306
+ Q3. Is this domain already in our Cloudflare account?
307
+ → Yes, zone exists → which zone?
308
+ → No → who controls the nameservers? Does the registrar point NS to Cloudflare?
309
+ → If NS not delegated to Cloudflare: A record in Cloudflare does nothing — must go to registrar
310
+
311
+ Q4. Does this app need Cloudflare proxy (orange cloud)?
312
+ → Traefik/Let's Encrypt HTTP-01 staging wildcards are often safest unproxied; verify your platform's DNS requirements.
313
+ → Custom domain needing DDoS/CDN: proxy OK only if SSL mode = Full (strict) + origin cert provisioned
314
+ → Any doubt: start unproxied, add proxy after confirming SSL works
315
+
316
+ Q5. What SSL path?
317
+ → Traefik + Let's Encrypt (default for all unproxied): automatic, no action needed
318
+ → Cloudflare proxy + Full (strict): need origin cert from Cloudflare dashboard first
319
+ → Nixpacks build pack: DO NOT USE for any app that needs custom SSL setup — nixpacks
320
+ containers have incompatible SSL configuration requirements. Use dockerfile build pack only.
321
+ ```
322
+
323
+ Embed all five answers into the infra task description verbatim before handing to the agent.
324
+
325
+ ## MCP / infra plans — mirror the closest sibling deployment FIRST
326
+
327
+ Before writing any plan that stands up an MCP server or infra service, read how the
328
+ **closest existing sibling** is actually deployed (`.mcp.json` + its PM2/tunnel or
329
+ Coolify/Docker config) and **cite it in the plan**. Two MCP topologies coexist and
330
+ applying the wrong reference over-engineers the design (lesson
331
+ 2026-06-10-plan-mirror-sibling-mcp-pattern: a first MCP plan proposed
332
+ Docker + Coolify + a Cloudflare-proxied origin + runtime GitHub-pull when the real
333
+ pattern was a local Node process + clauth-managed tunnel, exactly like codeflow-mcp):
334
+
335
+ - **LOCAL-MCP reference = `codeflow-mcp`** — local Node process (`:3109`) + clauth-managed
336
+ tunnel ingress. Mirror this for MCPs that live on Dave's box.
337
+ - **REMOTE-MCP reference = `web-research` / `regen-media`** — Coolify/Docker, Cloudflare-proxied
338
+ origin (`.claude/rules/mcp-endpoint-design.md` covers the REMOTE class only).
339
+
340
+ Decide which class applies and name the sibling in the plan's Design Decisions before
341
+ designing topology. Do not reach for the REMOTE rule by default.
342
+
343
+ ## Capture lessons (exit step)
344
+
345
+ Before the final verdict line, follow `.rdc/guides/lessons-learned-spec.md` § Capture procedure. If this run taught something non-obvious — a first root-cause theory that turned out wrong, the documented/standard path not working, a missing gate or check that cost a round, or a surprising tool/infra behavior — write one `.rdc/lessons/<YYYY-MM-DD>-plan-<short-slug>.md` per lesson using the schema in that spec. Set `scope` (`simple` | `architectural`) and `status` (`open`, or `applied` if you shipped the fix in this same run, with the commit linked). Commit the lesson file(s) on `develop` alongside the run's other commits, and note "N lessons captured" in your verdict/summary. A run that taught nothing writes nothing — absence is the default.