@lifeaitools/rdc-skills 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/git-sha.json +1 -1
- package/package.json +1 -1
- package/skills/build/SKILL.md +94 -28
- package/skills/deploy/SKILL.md +19 -0
- package/skills/fs-mcp/SKILL.md +17 -0
- package/skills/overnight/SKILL.md +25 -4
- package/skills/plan/SKILL.md +40 -0
package/git-sha.json
CHANGED
package/package.json
CHANGED
package/skills/build/SKILL.md
CHANGED
|
@@ -163,6 +163,28 @@ Read the task title and description, then:
|
|
|
163
163
|
- DB/migration task: at least schema object, relationship/guard, policy/permission, seed/fixture or backfill, and smoke query.
|
|
164
164
|
- Editor/sidebar/CLI workflow: at least start, attach/open, enqueue action, observe result, timeout/error, and live refresh where applicable.
|
|
165
165
|
|
|
166
|
+
### ⛔ Deliverable / acceptance check-off table — show BEFORE any implementation
|
|
167
|
+
Before dispatching the first wave, render a deliverable/acceptance table and
|
|
168
|
+
keep it visible through the build (lesson 2026-06-16-build-poor-goal-execution-mdk-brain:
|
|
169
|
+
a build satisfied generic checklist rows — tsc clean, route 200 — while never
|
|
170
|
+
touching the surface the user actually named, because no row anchored the
|
|
171
|
+
user's TARGET SURFACE). The table MUST contain:
|
|
172
|
+
- **One mandatory row for the user-named TARGET SURFACE** — the exact screen,
|
|
173
|
+
endpoint, file, or behavior the user asked for, by name. Its acceptance check
|
|
174
|
+
is what proves THAT surface renders/works, not a proxy.
|
|
175
|
+
- **At least one NEGATIVE verifier row** — a check that proves the WRONG thing
|
|
176
|
+
does NOT happen (e.g. "mock data is NOT rendered", "old route returns 404",
|
|
177
|
+
"stub component is absent from the bundle"). A positive-only suite passes
|
|
178
|
+
even when the deliverable is wired to the wrong source.
|
|
179
|
+
|
|
180
|
+
| Deliverable | Target surface? | Acceptance check | Negative verifier | Status |
|
|
181
|
+
|---|---|---|---|---|
|
|
182
|
+
|
|
183
|
+
**Gating rule:** any work item whose deliverable maps to the TARGET SURFACE row
|
|
184
|
+
stays in `review` (never `done`) until that target-surface acceptance check
|
|
185
|
+
passes. Generic gates (tsc, route 200) clearing is NOT sufficient to advance
|
|
186
|
+
the target-surface item.
|
|
187
|
+
|
|
166
188
|
If the gate fails:
|
|
167
189
|
- Interactive: show the failing rows and invoke `rdc:plan <epic-id>` to repair the matrix before dispatch.
|
|
168
190
|
- Unattended: invoke `rdc:plan <epic-id> --unattended`, reload tasks, and run this gate once more.
|
|
@@ -192,24 +214,59 @@ Read the task title and description, then:
|
|
|
192
214
|
7. **For each wave — dispatch typed agents in parallel:**
|
|
193
215
|
|
|
194
216
|
### ⛔ Agent Dispatch Non-Negotiable Defaults
|
|
195
|
-
Every `Agent()` call MUST include these parameters
|
|
217
|
+
Every `Agent()` call MUST include these parameters:
|
|
196
218
|
```
|
|
197
219
|
model: <chosen per the routing table below>
|
|
198
220
|
max_turns: 70
|
|
199
|
-
isolation: "worktree"
|
|
200
221
|
```
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
222
|
+
`isolation` is chosen per the dispatch-mode rule below — it is NOT a blanket
|
|
223
|
+
default. Worktree isolation is reserved for true parallel MULTI-committer waves
|
|
224
|
+
in the same repo; doc-only and single-committer waves default to NON-isolated.
|
|
225
|
+
|
|
226
|
+
### ⛔ Dispatch mode — non-isolated is the default for single-committer / doc-only waves
|
|
227
|
+
Worktree isolation exists to protect a SHARED working tree from a git-index race
|
|
228
|
+
between MULTIPLE agents committing in parallel. When there is only ONE committer,
|
|
229
|
+
that race cannot occur, and the stale-base hazard of worktrees (see the HARD GATE
|
|
230
|
+
below — recurring across 2026-06-10/11/15/16/17/23) is pure downside. Pick the
|
|
231
|
+
dispatch mode by committer count, not by reflex:
|
|
232
|
+
|
|
233
|
+
| Wave shape | Dispatch mode | isolation |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| **Doc-only wave** (markdown/docs/plans, no code build) | NON-isolated, one committer on `develop` | omit `isolation` |
|
|
236
|
+
| **Single-committer wave** (only one agent commits, or work serializes to the supervisor) | NON-isolated, one committer on `develop` | omit `isolation` |
|
|
237
|
+
| **True parallel MULTI-committer wave** (2+ agents committing concurrently in the same repo, disjoint files) | worktree-isolated, supervisor merges | `isolation: "worktree"` |
|
|
238
|
+
|
|
239
|
+
- **Default = NON-isolated.** Only escalate to `isolation: "worktree"` when the
|
|
240
|
+
wave genuinely has 2+ concurrent committers in the same repo.
|
|
241
|
+
- A pure docs wave is single-committer by default: either dispatch ONE doc agent,
|
|
242
|
+
or have parallel doc agents return diffs/patches that the supervisor commits
|
|
243
|
+
serially. Do NOT fan out 2+ concurrent committers onto one shared `develop`
|
|
244
|
+
tree (lesson 2026-06-13-build-concurrent-agents-same-branch-git-race: three
|
|
245
|
+
parallel doc agents on one `develop` tree raced on the git index/stash — one
|
|
246
|
+
commit swept in another agent's staged-but-uncommitted files under the wrong
|
|
247
|
+
message, two agents reported the SAME SHA, a pre-commit `sync:docs` ref-lock
|
|
248
|
+
race misattributed authorship). The fix for that race is single-committer
|
|
249
|
+
serialization, NOT blanket worktree isolation.
|
|
250
|
+
- When you DO need a true MULTI-committer parallel wave, worktree isolation is
|
|
251
|
+
mandatory AND the HARD GATE below (base == develop HEAD) MUST pass before
|
|
252
|
+
dispatch — a stale-base worktree wave is a build failure, not a warning.
|
|
253
|
+
|
|
254
|
+
### ⛔ Foreign concurrent session guard — `git status` BEFORE the build
|
|
255
|
+
Worktree isolation protects against THIS build's own agents, not against a
|
|
256
|
+
DIFFERENT session (another cell, a Codex run, a human) already committing on
|
|
257
|
+
the same shared tree (lesson 2026-06-16-build-concurrent-session-shared-tree-commit-corruption:
|
|
258
|
+
a foreign session's staged-but-uncommitted files were swept into this build's
|
|
259
|
+
commit under the wrong message). Before dispatching any wave, run `git status`
|
|
260
|
+
to detect foreign-dirty files you did not create. If foreign-dirty files are
|
|
261
|
+
present: do NOT fan out concurrent committers — **serialize ALL committers to
|
|
262
|
+
the supervisor** (agents return diffs/patches; the supervisor stages and
|
|
263
|
+
commits each one alone). After every supervisor commit, assert the exact file
|
|
264
|
+
set landed and nothing foreign leaked in:
|
|
265
|
+
```bash
|
|
266
|
+
git show --stat <sha> # confirm ONLY the files this commit owns are listed
|
|
267
|
+
```
|
|
268
|
+
A `git show --stat` that lists a file the agent did not touch = a foreign file
|
|
269
|
+
leaked into the commit; reset and re-stage by explicit path.
|
|
213
270
|
|
|
214
271
|
**Agent model routing — pick per task, not per wave.** The supervisor session model does NOT cascade to agents; you must set `model` explicitly on every dispatch.
|
|
215
272
|
|
|
@@ -231,25 +288,34 @@ Read the task title and description, then:
|
|
|
231
288
|
Without `max_turns: 70`, agents hit the default turn cap mid-task and stop.
|
|
232
289
|
`isolation: "worktree"` gives each agent its own git worktree and branch — eliminates push race conditions and index lock contention when multiple agents commit in parallel. The supervisor merges worktree branches after each wave (Step 9).
|
|
233
290
|
|
|
234
|
-
### ⛔ Worktree base
|
|
291
|
+
### ⛔ HARD GATE — Worktree base MUST equal develop HEAD (blocking, not advisory)
|
|
235
292
|
The worktree-isolation harness has shipped worktrees pinned to a STALE base
|
|
236
|
-
commit (lessons 2026-06-10-build-worktree-stale-base, 2026-06-11-build-worktree-stale-base
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
293
|
+
commit (lessons 2026-06-10-build-worktree-stale-base, 2026-06-11-build-worktree-stale-base,
|
|
294
|
+
2026-06-15-build-worktree-stale-base, 2026-06-16-build-worktree-stale-base,
|
|
295
|
+
2026-06-17-build-worktree-stale-base, 2026-06-23-build-worktree-stale-base:
|
|
296
|
+
agents branched hundreds of commits / multiple days behind develop HEAD, on a
|
|
297
|
+
tree where the target app did not yet exist — their diffs would have silently
|
|
298
|
+
reverted merged work or operated on a deleted structure). This is a recurring
|
|
299
|
+
harness defect, so the check is a **HARD BLOCKING GATE, not a suggestion.**
|
|
300
|
+
|
|
301
|
+
**Before dispatching ANY `isolation:"worktree"` wave**, the supervisor MUST run
|
|
302
|
+
the base==HEAD assertion and MUST abort isolation on any mismatch — there is no
|
|
303
|
+
"proceed anyway" path:
|
|
242
304
|
```bash
|
|
243
305
|
DEV_HEAD=$(git rev-parse develop)
|
|
244
306
|
# After worktrees are created, for each agent worktree:
|
|
245
307
|
git worktree list # compare each agent worktree's SHA to $DEV_HEAD
|
|
246
|
-
# If
|
|
308
|
+
# If ANY worktree base != $DEV_HEAD (it is behind), the wave is UNSAFE — ABORT.
|
|
247
309
|
```
|
|
248
|
-
-
|
|
249
|
-
Do NOT merge stale worktree output.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
310
|
+
- **MANDATORY ABORT:** if ANY worktree base != `$DEV_HEAD`, you MUST abort
|
|
311
|
+
isolation for this wave. Do NOT merge stale worktree output. Do NOT "fast-forward
|
|
312
|
+
and continue". Do NOT proceed with the isolated wave under any circumstance.
|
|
313
|
+
Pivot to **sequential, non-isolated dispatch on a real `develop` checkout**
|
|
314
|
+
(one disjoint WP at a time to avoid `.git/index` races; the supervisor pushes) —
|
|
315
|
+
the same reason the validator runs non-isolated (it must see merged develop).
|
|
316
|
+
- This gate is blocking by design: an isolated wave dispatched on a stale base
|
|
317
|
+
is treated as a build failure, not a warning. Skipping or downgrading this
|
|
318
|
+
assertion to advisory is a contract violation.
|
|
253
319
|
- Also at every merge: `git show <branch>:<key-file> | grep -c <symbol-a-prior-wave-introduced>`
|
|
254
320
|
— a 0 where there should be ≥1 means the branch is stale or deleted a shared
|
|
255
321
|
export; resolve to `--ours` and re-apply that wave's real delta on current HEAD.
|
|
@@ -470,7 +536,7 @@ NEVER run pnpm build or pnpm turbo. Use npx vitest run only.
|
|
|
470
536
|
- Push after each wave, not just at the end
|
|
471
537
|
- Unattended: NEVER pause — continue automatically
|
|
472
538
|
- Unattended: max 2 retries per task before escalating to advisor
|
|
473
|
-
- Every Agent() dispatch: `model: <routed>` + `max_turns: 70`
|
|
539
|
+
- Every Agent() dispatch: `model: <routed>` + `max_turns: 70` — non-negotiable. `isolation` is per the dispatch-mode rule in Step 7: NON-isolated (omit `isolation`) for doc-only and single-committer waves; `isolation: "worktree"` ONLY for true parallel MULTI-committer waves, and only after the HARD GATE (worktree base == develop HEAD) passes — a stale-base isolated wave is a build failure. Model is chosen per task per the routing table in Step 7: Sonnet 4.6 for updates/edits, Opus 4.6 for harder coding, Opus 4.8 for design/innovative thought (CS 2.0, brand/UX, architecture). Supervisor logs `model=<chosen> reason=<phrase>` per agent. Exception: validator agent in Step 10 always omits isolation; validator model stays `claude-sonnet-4-6` (verification, not generation).
|
|
474
540
|
- Finding an existing file is NOT task completion — verify it satisfies the spec
|
|
475
541
|
|
|
476
542
|
## Capture lessons (exit step)
|
package/skills/deploy/SKILL.md
CHANGED
|
@@ -346,6 +346,25 @@ OG_IMG=$(echo "$HEAD" | grep -ioE 'property="og:image"[^>]*content="([^"]*)"' |
|
|
|
346
346
|
|
|
347
347
|
**Why this exists (2026-06-05):** life.ai deployed to production with zero social/SEO metadata — no description, no OG, no favicon, no sitemap. HTTP 200 + TLS + content passed; metadata was invisible to the existing gates. This audit catches that class of defect.
|
|
348
348
|
|
|
349
|
+
## Hotlink referer allowlist — new media.place.fund consumer domains
|
|
350
|
+
|
|
351
|
+
When onboarding a NEW brand domain that loads assets from `media.place.fund`, add
|
|
352
|
+
that domain to the hotlink-protection Worker's referer allowlist **before
|
|
353
|
+
go-live** (lesson 2026-06-14-deploy-issholiving-referer-hotlink-403: a new brand
|
|
354
|
+
domain served its own HTML fine but every `media.place.fund` image returned 403
|
|
355
|
+
because the hotlink Worker rejected the unknown `Referer`). The image 403 is
|
|
356
|
+
invisible to the HTTP-200 / TLS / metadata gates — they probe the HTML document,
|
|
357
|
+
not the cross-origin asset.
|
|
358
|
+
|
|
359
|
+
- Add the new origin (apex + `www`, dev + prod) to the Worker's referer allowlist
|
|
360
|
+
and redeploy the Worker before the brand domain goes live.
|
|
361
|
+
- Verify with an explicit `Referer` probe (NOT a bare curl — a missing Referer can
|
|
362
|
+
pass while the real browser Referer fails):
|
|
363
|
+
```bash
|
|
364
|
+
curl -s -o /dev/null -w "%{http_code}" -e "https://<new-brand-domain>/" \
|
|
365
|
+
"https://media.place.fund/<a-known-asset-path>" # expect 200, not 403
|
|
366
|
+
```
|
|
367
|
+
|
|
349
368
|
## PUBLISH.md Integration
|
|
350
369
|
|
|
351
370
|
Every deploy reads `PUBLISH.md` from the app's source root to derive `watch_paths` and to register surfaces in Studio `artifact_registry`.
|
package/skills/fs-mcp/SKILL.md
CHANGED
|
@@ -73,6 +73,23 @@ Use URL ingest when the file already exists in cloud storage:
|
|
|
73
73
|
fs_ingest_url url="https://..." path="docs/source/file.md" expected_sha256="<optional>"
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
### ⛔ Ingest discipline (lesson 2026-06-16-collab-claudeai-fs-ingest-race-and-preview-pollution)
|
|
77
|
+
|
|
78
|
+
- **Prefer synchronous `fs_write` over `fs_ingest_url` for commit-bound bytes.**
|
|
79
|
+
`fs_ingest_url` can return before the bytes have landed on disk; a `git add`
|
|
80
|
+
immediately after races the download and silently stages nothing. If you MUST
|
|
81
|
+
use `fs_ingest_url` for content you will commit, `fs_stat`-poll the target path
|
|
82
|
+
until size/hash is stable BEFORE staging or committing.
|
|
83
|
+
- **A silent `git add` skip is NOT gitignore.** If `git add <path>` adds nothing
|
|
84
|
+
and the file is not obviously ignored, do not assume `.gitignore` — confirm with
|
|
85
|
+
`git check-ignore -v <path>`. No output means it is NOT ignored, so the real
|
|
86
|
+
cause is a missing/empty/racing file, not an ignore rule.
|
|
87
|
+
- **Never ingest claude.ai preview / Artifacts URLs.** URLs like
|
|
88
|
+
`*.claude.ai/.../preview` or Artifact render endpoints serve a wrapped,
|
|
89
|
+
data-omelette-injected document (host chrome, sanitizer rewrites, injected
|
|
90
|
+
markers) — not the clean source bytes. Ingesting them pollutes the repo. Get
|
|
91
|
+
the durable source via the GitHub-branch import path (§4) instead.
|
|
92
|
+
|
|
76
93
|
Use guarded append when appending to a known file:
|
|
77
94
|
|
|
78
95
|
```text
|
|
@@ -42,17 +42,38 @@ If the sentinel file does not exist, the Stop hook will NOT block — which mean
|
|
|
42
42
|
|
|
43
43
|
Before touching any code, verify the environment is safe:
|
|
44
44
|
|
|
45
|
-
1. **Clauth daemon alive:**
|
|
45
|
+
1. **Clauth daemon alive AND unlocked:** `/ping` alive is NOT enough — a LOCKED
|
|
46
|
+
vault answers `/ping` but every `/v/<service>` returns nothing, so credentials
|
|
47
|
+
silently resolve empty and a long unattended run fails hours later
|
|
48
|
+
(lesson 2026-06-16-overnight-preflight-clauth-locked-and-shared-develop-cells).
|
|
49
|
+
Assert `locked:false` before proceeding:
|
|
46
50
|
```bash
|
|
47
51
|
curl -s http://127.0.0.1:52437/ping
|
|
52
|
+
curl -s http://127.0.0.1:52437/status | python3 -c "import sys,json; s=json.load(sys.stdin); print('locked:', s.get('locked')); sys.exit(1 if s.get('locked') else 0)"
|
|
48
53
|
```
|
|
49
|
-
If not responding: report `BLOCKED: credential daemon offline` and exit. Do not proceed.
|
|
54
|
+
If not responding OR `locked:true`: report `BLOCKED: credential daemon offline or locked` and exit. Do not proceed.
|
|
50
55
|
|
|
51
|
-
2. **Git state clean:**
|
|
56
|
+
2. **Git state clean AND no concurrent committer on shared develop:** Overnight
|
|
57
|
+
shares the `develop` working tree with other cells/sessions. A second session
|
|
58
|
+
committing concurrently can drop a just-committed file during a rebase
|
|
59
|
+
(lessons 2026-06-16-overnight-preflight-clauth-locked-and-shared-develop-cells,
|
|
60
|
+
2026-06-17-build-shared-develop-rebase-dropped-committed-file).
|
|
52
61
|
```bash
|
|
53
62
|
git status --short
|
|
63
|
+
git fetch -q origin && git log --oneline @..@{u} # any rows = origin moved under you
|
|
54
64
|
```
|
|
55
|
-
Must be on the development branch with no uncommitted changes. If dirty: commit
|
|
65
|
+
Must be on the development branch with no uncommitted changes. If dirty: commit
|
|
66
|
+
or stash first. If `origin/develop` is ahead of local at preflight, another
|
|
67
|
+
session is actively committing — enforce these rules for the whole run:
|
|
68
|
+
- **Atomic stage+commit by explicit path** — `git add <paths>` then immediate
|
|
69
|
+
`git commit`; never leave a wide `git add -A` window open while another
|
|
70
|
+
session may stage.
|
|
71
|
+
- **Post-push origin verification** — after every push, confirm each committed
|
|
72
|
+
file actually reached origin (a rebase can silently drop it):
|
|
73
|
+
```bash
|
|
74
|
+
git cat-file -e origin/develop:<path> && echo "OK: <path> on origin" || echo "DROPPED: <path> — re-apply and re-push"
|
|
75
|
+
```
|
|
76
|
+
A `DROPPED` result means re-apply the file on fresh `origin/develop` HEAD and push again.
|
|
56
77
|
|
|
57
78
|
3. **Baseline review:**
|
|
58
79
|
Run `rdc:review --unattended`. If `REVIEW_STATUS.verdict = "HAS_ISSUES"` and
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -39,12 +39,52 @@ description: "Usage `rdc:plan <topic>` — No epic exists and you need architect
|
|
|
39
39
|
- What tests exist?
|
|
40
40
|
- What's the dependency graph?
|
|
41
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
|
+
|
|
42
59
|
3. **Make design decisions** — for each major choice:
|
|
43
60
|
- State the decision clearly
|
|
44
61
|
- Document what was chosen and what was rejected
|
|
45
62
|
- Explain WHY (tradeoff rationale)
|
|
46
63
|
- Note consequences and reversibility
|
|
47
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
|
+
|
|
48
88
|
4. **Define work packages** — break into agent-dispatchable units:
|
|
49
89
|
- Each work package = one agent assignment
|
|
50
90
|
- No file overlap between packages
|