@lifeaitools/rdc-skills 0.25.0 → 0.25.1

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.
@@ -1334,6 +1334,45 @@
1334
1334
  "enabled_default": true,
1335
1335
  "codeflow_required": false
1336
1336
  },
1337
+ "env": {
1338
+ "name": "env",
1339
+ "slash": "rdc:env",
1340
+ "category": "infra",
1341
+ "usage": "rdc:env [status|install|repair|update]",
1342
+ "args": {
1343
+ "positional": [
1344
+ {
1345
+ "name": "action",
1346
+ "required": false,
1347
+ "default": "status",
1348
+ "values": ["status", "install", "repair", "update"]
1349
+ }
1350
+ ],
1351
+ "flags": []
1352
+ },
1353
+ "requires": [
1354
+ "clauth"
1355
+ ],
1356
+ "produces": [],
1357
+ "default_model": "sonnet",
1358
+ "triggers": [
1359
+ "check environment",
1360
+ "install environment",
1361
+ "repair environment",
1362
+ "update environment",
1363
+ "setup env",
1364
+ "fix env",
1365
+ "env status",
1366
+ "after reboot",
1367
+ "GPU crash"
1368
+ ],
1369
+ "follows": [],
1370
+ "leads_to": ["status"],
1371
+ "sandbox_aware": false,
1372
+ "output_contract": "guides/output-contract.md",
1373
+ "enabled_default": true,
1374
+ "codeflow_required": false
1375
+ },
1337
1376
  "terminal-config": {
1338
1377
  "name": "terminal-config",
1339
1378
  "slash": "rdc:terminal-config",
@@ -1436,7 +1475,7 @@
1436
1475
  "name": "onramp",
1437
1476
  "slash": "rdc:onramp",
1438
1477
  "category": "infra",
1439
- "usage": "rdc:onramp <slug> --name \"<Display Name>\" [--location <json>] [--archetype <archetype>] [--owner place-fund|rdc|jv|client] [--history] [--dry-run]",
1478
+ "usage": "rdc:onramp <slug> --name \"<Display Name>\" [--location <json>] [--archetype <archetype>] [--owner place-fund|rdc|jv|client] [--history] [--skip-to <phase>] [--no-gate] [--dry-run]",
1440
1479
  "args": {
1441
1480
  "positional": [
1442
1481
  {
@@ -1494,7 +1533,10 @@
1494
1533
  ],
1495
1534
  "produces": [
1496
1535
  "work_items",
1497
- "supabase_writes"
1536
+ "supabase_writes",
1537
+ "git_commits",
1538
+ "git_pushes",
1539
+ "deploys"
1498
1540
  ],
1499
1541
  "default_model": "opus",
1500
1542
  "triggers": [
@@ -1503,12 +1545,12 @@
1503
1545
  "lay the infra for",
1504
1546
  "enroll this project",
1505
1547
  "start a new place fund project",
1506
- "run enrollment for"
1548
+ "run enrollment for",
1549
+ "run the full pipeline for",
1550
+ "build a place from scratch"
1507
1551
  ],
1508
1552
  "follows": [],
1509
- "leads_to": [
1510
- "design"
1511
- ],
1553
+ "leads_to": [],
1512
1554
  "sandbox_aware": true,
1513
1555
  "output_contract": "guides/output-contract.md",
1514
1556
  "enabled_default": true,
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## v0.25.0 — rdc:onramp Phase-1 enrollment skill
11
+
12
+ ### Added
13
+ - `rdc:onramp` — Phase-1 enrollment infrastructure orchestrator for new Place
14
+ Fund projects. It gates the existing `enroll_place` RPC, `insert_work_item`
15
+ enrollment epic, and `onramp-scaffold-place.mjs` disk scaffolder in strict
16
+ order, with fresh/already-enrolled/spine-ahead/disk-ahead drift handling.
17
+ - Tier-2 onramp test manifest coverage for the `_context.md` absence invariant,
18
+ deterministic door contracts, and four-state drift behavior.
19
+
20
+ ---
21
+
10
22
  ## v0.21.0 — channel-formatter skill
11
23
 
12
24
  ### Added
package/MANIFEST.md CHANGED
@@ -3,7 +3,7 @@
3
3
  **Created:** 2026-04-13
4
4
  **Last updated:** 2026-05-01
5
5
  **Source:** Regen Root project `.claude/skills/user/`
6
- **Files:** 18+ skill files, 10 agent guides, command mirrors, and support scripts
6
+ **Files:** 31 skill files, 10 agent guides, command mirrors, and support scripts
7
7
  **Size:** ~480K
8
8
 
9
9
  ## Generic Conversion Summary
@@ -54,6 +54,7 @@ All skills have been converted from project-specific to generic/portable:
54
54
  ├── workitems/SKILL.md
55
55
  ├── design/SKILL.md [RDC/Studio design, Palette Library, Rampa CLI]
56
56
  ├── help/SKILL.md
57
+ ├── regen-media/SKILL.md [primary image generation + Regen Media upload]
57
58
  ├── deploy/SKILL.md [Coolify deployment ops]
58
59
  ├── release/SKILL.md [atomic version release]
59
60
  ├── self-test/SKILL.md [static lint + tier2 smoke tests]
@@ -113,6 +114,8 @@ All skills have been converted from project-specific to generic/portable:
113
114
  - rdc:channel-formatter — channel-native formatting and content repurposing,
114
115
  including article-to-post, social-pack, campaign-pack, exec-pack, and
115
116
  launch-pack outputs
117
+ - rdc:regen-media — primary image generation and Regen Media upload workflow,
118
+ defaulting to local keyless Codex `gpt-image-2` via built-in `image_gen`
116
119
 
117
120
  ### Bridge (3)
118
121
  - rdc:handoff — planning → work items
package/README.md CHANGED
@@ -13,7 +13,7 @@ From any Claude Code session:
13
13
  /plugin install rdc-skills
14
14
  ```
15
15
 
16
- The full catalog is available through the MCP as 30 skills. Nineteen common
16
+ The full catalog is available through the MCP as 31 skills. Nineteen common
17
17
  workflows also ship as `/rdc:*` command shorthands. Agent playbooks in
18
18
  `guides/agents/` are dispatched internally by `rdc:build` and are not
19
19
  user-invocable.
@@ -181,7 +181,7 @@ Throughout the skills, the following substitutions have been made to make them p
181
181
 
182
182
  ## Skills Overview
183
183
 
184
- 30 MCP skills organized into 8 manifest categories. Nineteen of these also have
184
+ 31 MCP skills organized into 8 manifest categories. Nineteen of these also have
185
185
  `/rdc:*` command shorthands for Claude Code/plugin callers.
186
186
 
187
187
  Use `rdc_skill_list` for the authoritative live catalog, including names,
@@ -216,6 +216,7 @@ Located in `guides/agents/` — plain markdown playbooks spawned as sub-agents:
216
216
  - lifeai-brochure-author — JSX authoring contract for Brochurify inputs
217
217
  - rdc:convert — Office/Markdown conversion via build-corpus (work in Markdown, materialize `.docx`/`.pptx` at the end; round-trips losslessly — see build-corpus `AGENTS.md`)
218
218
  - rdc:fs-mcp — File System MCP bridge guidance for live repo reads/writes
219
+ - rdc:regen-media — primary image generation and Regen Media upload workflow; defaults to local keyless Codex `gpt-image-2` via built-in `image_gen`
219
220
  - rdc:extract-verifier-rules — verifier-rule extraction from enhancement logs
220
221
  - rdc:rpms-filemap — generated RPMS file-map guidance
221
222
  - rdc:workitems — manual work item CRUD
@@ -313,6 +314,7 @@ skills/
313
314
  edit/SKILL.md (local website editor launcher)
314
315
  fixit/SKILL.md (quick-fix bypass)
315
316
  fs-mcp/SKILL.md (File System MCP bridge guidance)
317
+ regen-media/SKILL.md (primary image generation + Regen Media upload)
316
318
  handoff/SKILL.md (planning → work items)
317
319
  help/SKILL.md (manifest-driven skill index)
318
320
  housekeeping/SKILL.md (weekly maintenance audit)
@@ -73,7 +73,7 @@ Determine which epics to work:
73
73
  - `status IN ('todo', 'in_progress')`
74
74
  - Order: urgent first, then high, then by `created_at`
75
75
 
76
- Log the epic queue at the start of `.rdc/reports/overnight-<YYYY-MM-DD>.md` (fallback: `.rdc/reports/overnight-<YYYY-MM-DD>.md` if `.rdc/` does not exist).
76
+ Log the epic queue at the start of `.rdc/overnights/overnight-<YYYY-MM-DD>.md` (fallback: `.rdc/overnights/overnight-<YYYY-MM-DD>.md` if `.rdc/` does not exist).
77
77
 
78
78
  ## Phase 3 — Epic Loop
79
79
 
@@ -145,7 +145,7 @@ After all epics are processed:
145
145
 
146
146
  1. Run `rdc:report --unattended`
147
147
 
148
- 2. Write session summary to `.rdc/reports/overnight-<YYYY-MM-DD>.md` (fallback: `.rdc/reports/overnight-<YYYY-MM-DD>.md`):
148
+ 2. Write session summary to `.rdc/overnights/overnight-<YYYY-MM-DD>.md` (fallback: `.rdc/overnights/overnight-<YYYY-MM-DD>.md`):
149
149
  ```markdown
150
150
  # Overnight Session — YYYY-MM-DD
151
151
 
package/git-sha.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "sha": "d6605a5c16373e540f31b046c1a5687170893d0e"
2
+ "sha": "bf46e3a7c1b60f99831e4e087c53007083eac436"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.25.0",
3
+ "version": "0.25.1",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -30,6 +30,8 @@ const fs = require('fs');
30
30
  const path = require('path');
31
31
  const os = require('os');
32
32
  const readline = require('readline');
33
+ const http = require('http');
34
+ const crypto = require('crypto');
33
35
  const { execSync } = require('child_process');
34
36
 
35
37
  // ── Args ──────────────────────────────────────────────────────────────────────
@@ -102,6 +104,12 @@ function run(cmd, options = {}) {
102
104
  return execSync(cmd, { encoding: 'utf8', stdio: 'pipe', ...options }).trim();
103
105
  }
104
106
 
107
+ function shellQuote(s) {
108
+ const raw = String(s);
109
+ if (process.platform === 'win32') return `"${raw.replace(/"/g, '\\"')}"`;
110
+ return `'${raw.replace(/'/g, `'\\''`)}'`;
111
+ }
112
+
105
113
  function updateCodexMcpToml(toml, mcpUrl) {
106
114
  const blockRe = /(^|\n)(\[mcp_servers\.rdc-skills\]\n)([\s\S]*?)(?=\n\[|\s*$)/;
107
115
  const desiredLine = `url = '${mcpUrl}'`;
@@ -322,6 +330,35 @@ function readInstalledPackageVersion(scriptPath) {
322
330
  return readJson(path.join(packageRoot, 'package.json'), {}).version || null;
323
331
  }
324
332
 
333
+ function collectFilesRecursive(baseDir, rel, out) {
334
+ const full = path.join(baseDir, rel);
335
+ if (!fs.existsSync(full)) return;
336
+ const stat = fs.statSync(full);
337
+ if (stat.isDirectory()) {
338
+ for (const entry of fs.readdirSync(full).sort()) {
339
+ collectFilesRecursive(baseDir, path.join(rel, entry), out);
340
+ }
341
+ return;
342
+ }
343
+ if (stat.isFile()) out.push(rel.replace(/\\/g, '/'));
344
+ }
345
+
346
+ function hashInstallSurface(root) {
347
+ if (!root || !fs.existsSync(root)) return null;
348
+ const rels = [];
349
+ for (const rel of ['.claude-plugin', 'commands', 'guides', 'skills', 'package.json', 'README.md']) {
350
+ collectFilesRecursive(root, rel, rels);
351
+ }
352
+ const hash = crypto.createHash('sha256');
353
+ for (const rel of rels.sort()) {
354
+ hash.update(rel);
355
+ hash.update('\0');
356
+ hash.update(fs.readFileSync(path.join(root, rel)));
357
+ hash.update('\0');
358
+ }
359
+ return hash.digest('hex');
360
+ }
361
+
325
362
  function syncGlobalMcpInstall(version) {
326
363
  const proc = getPm2Process(MCP_NAME);
327
364
  if (!proc) {
@@ -336,18 +373,22 @@ function syncGlobalMcpInstall(version) {
336
373
  }
337
374
 
338
375
  const installedVersion = readInstalledPackageVersion(scriptPath);
339
- if (installedVersion === version) {
340
- ok(`[2.9] MCP pkg — global ${NPM_PACKAGE}@${version} already installed`);
376
+ const packageRoot = packageRootFromMcpScript(scriptPath);
377
+ const sourceHash = hashInstallSurface(repoRoot);
378
+ const installedHash = hashInstallSurface(packageRoot);
379
+ if (installedVersion === version && sourceHash && installedHash && sourceHash === installedHash) {
380
+ ok(`[2.9] MCP pkg — global ${NPM_PACKAGE}@${version} already matches source`);
341
381
  return;
342
382
  }
343
383
 
344
384
  let stopped = false;
345
385
  let installed = false;
346
386
  try {
347
- info(`[2.9] MCP pkg — updating global ${NPM_PACKAGE} ${installedVersion || '?'} → ${version}`);
387
+ const reason = installedVersion === version ? 'same version, source changed' : `${installedVersion || '?'} → ${version}`;
388
+ info(`[2.9] MCP pkg — updating global ${NPM_PACKAGE} (${reason}) from local source`);
348
389
  run(`pm2 stop ${MCP_NAME}`);
349
390
  stopped = true;
350
- run(`npm install -g ${NPM_PACKAGE}@${version}`);
391
+ run(`npm install -g ${shellQuote(repoRoot)}`);
351
392
  installed = true;
352
393
  ok(`[2.9] MCP pkg — installed global ${NPM_PACKAGE}@${version}`);
353
394
  } catch (e) {
@@ -367,6 +408,71 @@ function syncGlobalMcpInstall(version) {
367
408
  }
368
409
  }
369
410
 
411
+ function callLocalMcpTool(name, args = {}) {
412
+ return new Promise((resolve, reject) => {
413
+ const payload = JSON.stringify({
414
+ jsonrpc: '2.0',
415
+ id: 1,
416
+ method: 'tools/call',
417
+ params: { name, arguments: args },
418
+ });
419
+ const req = http.request({
420
+ hostname: '127.0.0.1',
421
+ port: Number(MCP_PORT),
422
+ path: '/mcp',
423
+ method: 'POST',
424
+ headers: {
425
+ 'Content-Type': 'application/json',
426
+ 'Accept': 'application/json, text/event-stream',
427
+ 'Content-Length': Buffer.byteLength(payload),
428
+ },
429
+ timeout: 10000,
430
+ }, (res) => {
431
+ let body = '';
432
+ res.setEncoding('utf8');
433
+ res.on('data', (chunk) => { body += chunk; });
434
+ res.on('end', () => {
435
+ try {
436
+ const dataLine = body.split(/\r?\n/).find((line) => line.startsWith('data: '));
437
+ const envelope = JSON.parse(dataLine ? dataLine.slice(6) : body);
438
+ const text = envelope?.result?.content?.[0]?.text;
439
+ resolve(text ? JSON.parse(text) : envelope);
440
+ } catch (e) {
441
+ reject(new Error(`invalid MCP response: ${e.message}`));
442
+ }
443
+ });
444
+ });
445
+ req.on('timeout', () => req.destroy(new Error('MCP request timed out')));
446
+ req.on('error', reject);
447
+ req.write(payload);
448
+ req.end();
449
+ });
450
+ }
451
+
452
+ async function verifyLiveMcpCatalogFresh() {
453
+ const proc = getPm2Process(MCP_NAME);
454
+ if (!proc) {
455
+ warn('[7.5] MCP catalog — skipped (PM2 process not registered)');
456
+ return;
457
+ }
458
+ const sourceSkills = fs.readdirSync(path.join(repoRoot, 'skills'), { withFileTypes: true })
459
+ .filter((entry) => entry.isDirectory() && fs.existsSync(path.join(repoRoot, 'skills', entry.name, 'SKILL.md')))
460
+ .map((entry) => entry.name)
461
+ .sort();
462
+ const catalog = await callLocalMcpTool('rdc_skill_list', {});
463
+ const rows = Array.isArray(catalog)
464
+ ? catalog
465
+ : Array.isArray(catalog?.skills) ? catalog.skills
466
+ : Array.isArray(catalog?.results) ? catalog.results
467
+ : [];
468
+ const liveNames = new Set(rows.map((row) => row.name));
469
+ const missing = sourceSkills.filter((name) => !liveNames.has(name));
470
+ if (missing.length > 0 || rows.length < sourceSkills.length) {
471
+ throw new Error(`live MCP catalog stale: source=${sourceSkills.length}, live=${rows.length}, missing=${missing.join(', ') || '(count mismatch)'}`);
472
+ }
473
+ ok(`[7.5] MCP catalog — ${rows.length} live skill(s), source catalog fresh`);
474
+ }
475
+
370
476
  // ── User-skills cleanup ───────────────────────────────────────────────────────
371
477
  // Older installer versions wrote skill files directly to ~/.claude/skills/user/.
372
478
  // Claude Code loads that directory AND the plugin cache, so any rdc skills left
@@ -1260,6 +1366,12 @@ async function main() {
1260
1366
  console.log('');
1261
1367
  console.log(' \x1b[36mMCP server:\x1b[0m');
1262
1368
  try { registerMcpServer(); } catch (e) { warn(`[7/7] MCP server — unexpected error (${e.message})`); }
1369
+ try {
1370
+ await verifyLiveMcpCatalogFresh();
1371
+ } catch (e) {
1372
+ fail(`[7.5] MCP catalog — ${e.message}`);
1373
+ process.exit(2);
1374
+ }
1263
1375
 
1264
1376
  // Done
1265
1377
  console.log('');
@@ -425,6 +425,17 @@ Read the task title and description, then:
425
425
  and run it green before the item leaves `review`. Agent prompt line: *"This
426
426
  task is not done until a committed test in the same commit exercises every
427
427
  surface; for collections, loop all items and assert output == source."*
428
+ - **Durable workflow E2E gate (hard):** A task that creates a queue/job,
429
+ background worker, storage hand-off, retry/lease, webhook, or other async
430
+ cross-process workflow MUST ship a committed `test:e2e` (or equivalent)
431
+ harness. Before the task leaves `review`, run it against the deploy-equivalent
432
+ container plus real disposable dependencies (or an isolated mirror) and
433
+ retain its receipt. The harness MUST exercise the public ingress, assert the
434
+ full state transition, assert every persisted output, and clean up fixture
435
+ rows/objects in `finally`; unit tests, mocks, a migration check, Docker
436
+ construction, or a `/health` probe cannot substitute. If no safe disposable
437
+ environment exists, create one within the work package; do not waive this
438
+ gate or mark the item reviewable.
428
439
 
429
440
  8. **Post-wave test gate (mandatory):**
430
441
  After all agents in a wave complete, before proceeding:
@@ -514,6 +525,10 @@ Read the task title and description, then:
514
525
  - Runs `npx tsc --noEmit` for every touched app/package
515
526
  - Starts the dev server and probes every modified route (expects HTTP 200, not 500)
516
527
  - Runs vitest for every touched package
528
+ - For every durable workflow, runs the committed E2E harness and rejects the
529
+ item unless its receipt proves public ingress -> queued/running -> terminal
530
+ state, persisted outputs, and fixture cleanup on the deploy-equivalent
531
+ runtime; an absent harness is a hard rejection.
517
532
  - **Verifies checklist decomposition quality per work item before functional validation:**
518
533
  - Every implementation work item has >= 10 attested `decomp-*`/`test-*` items, meets the per-surface completeness floors (each declared surface covered), and no feature WP ships a 5-6-row checklist
519
534
  - Every `decomp-*` item includes route/file, action, expected result, and evidence artifact
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: rdc:env
3
+ description: "Usage `rdc:env [status|install|repair|update]` — Manage the LIFEAI environment harness: check status, install on a fresh box, repair broken services, or pull updates. Reads $LIFEAI_ENV/manifest.json as the source of truth. Use when: 'check the environment', 'install environment', 'repair environment', 'update environment', 'setup env', 'fix env', 'env status', or after a reboot/GPU crash."
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
+ # rdc:env — Environment Harness Manager
11
+
12
+ ## When to Use
13
+ - After a reboot or GPU crash — verify everything came back up
14
+ - Setting up a fresh box — install all tools and services
15
+ - Something is broken — repair services, MCPs, CodeFlow
16
+ - Routine update — pull latest env repo and run drift check
17
+ - "check the environment", "fix my setup", "install environment"
18
+
19
+ ## Subcommands
20
+
21
+ | Command | What it does |
22
+ |---------|-------------|
23
+ | `status` (default) | Read-only check: env repo version, tool versions, MCP health, shim integrity, CodeFlow brain |
24
+ | `install` | Full provision: clone env repo if missing, set LIFEAI_ENV, install tools, configure MCPs |
25
+ | `repair` | Diagnose and fix: restart crashed services, rebuild stale dists, fix broken shims |
26
+ | `update` | Pull latest env repo, re-run audit, report drift, refresh shims if new scripts added |
27
+
28
+ ## Procedure
29
+
30
+ ### Step 0: Resolve environment root
31
+
32
+ ```bash
33
+ LIFEAI_ENV="${LIFEAI_ENV:-C:/Dev/lifeai-env}"
34
+ ```
35
+
36
+ If `$LIFEAI_ENV` is not set AND the default path doesn't exist:
37
+ - For `install`: clone the repo and set the env var
38
+ - For all others: STOP with `BLOCKED: environment repo not found. Run: rdc:env install`
39
+
40
+ Read `$LIFEAI_ENV/manifest.json` — this is the harness inventory.
41
+
42
+ ### Step 1: Environment repo state
43
+
44
+ ```bash
45
+ git -C "$LIFEAI_ENV" fetch origin 2>/dev/null
46
+ git -C "$LIFEAI_ENV" rev-list --count HEAD..origin/main
47
+ ```
48
+
49
+ Report: version from manifest.json, commits behind origin, last pull date.
50
+
51
+ For `update`: pull if behind. For `repair`: pull if behind (stale harness may be the cause).
52
+
53
+ ### Step 2: Tool versions (audit)
54
+
55
+ Run the audit script:
56
+ ```bash
57
+ pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "$LIFEAI_ENV/audit/audit.ps1" -ProjectRoot "$PROJECT_ROOT"
58
+ ```
59
+
60
+ Or read `$PROJECT_ROOT/environment.lock.json` and check each tool:
61
+
62
+ | Tool | Check | Min Version |
63
+ |------|-------|-------------|
64
+ | node | `node --version` | 22.0.0 |
65
+ | pnpm | `pnpm --version` | 10.0.0 |
66
+ | pm2 | `pm2 --version` | 5.0.0 |
67
+ | clauth | `curl -s http://127.0.0.1:52437/ping` | 1.30.0 |
68
+ | rdc-skills | `npm list -g @lifeai/rdc-skills` | 0.25.0 |
69
+ | gh | `gh --version` | 2.0.0 |
70
+
71
+ For `install` and `repair`: install or upgrade any tool below min_version using the `install` command from the lock file. This includes rdc-skills itself — the environment repo is the orchestrator that keeps all tools current, including its own skill set. A `repair` or `install` that bumps rdc-skills will also restart the rdc-skills-mcp PM2 process so the new version is live immediately.
72
+
73
+ ### Step 3: Service health
74
+
75
+ Check each service:
76
+
77
+ | Service | Health Check | Repair |
78
+ |---------|-------------|--------|
79
+ | clauth daemon | `curl -s http://127.0.0.1:52437/ping` | `$LIFEAI_ENV/services/restart-clauth.bat` |
80
+ | CodeFlow gateway | `curl -s http://127.0.0.1:3109/health` | `node $PROJECT_ROOT/scripts/codeflow-up.mjs` |
81
+ | CodeFlow brain | `/health` → `health.state` should be `operational` | `node $PROJECT_ROOT/scripts/codeflow-up.mjs --restart` |
82
+ | rdc-skills MCP | `pm2 list` shows rdc-skills-mcp online | `pm2 restart rdc-skills-mcp` |
83
+ | PM2 daemon | `pm2 ping` | `pm2 resurrect` |
84
+ | Docker | `docker info` | Start Docker Desktop |
85
+ | Neo4j | `docker inspect codeflow-neo4j` | `docker compose -f $LIFEAI_ENV/services/codeflow/docker-compose.yml up -d` |
86
+
87
+ For `status`: report only. For `repair`: fix each failing service in order (clauth first, then CodeFlow, then MCPs).
88
+
89
+ ### Step 4: MCP server verification
90
+
91
+ Run the MCP checker:
92
+ ```bash
93
+ pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "$LIFEAI_ENV/services/install-mcps.ps1" -ProjectRoot "$PROJECT_ROOT"
94
+ ```
95
+
96
+ For `repair`: add `-Fix` flag to auto-start missing local MCPs.
97
+
98
+ ### Step 5: Shim integrity
99
+
100
+ Check that all monorepo shims point at valid targets:
101
+ ```bash
102
+ pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "$LIFEAI_ENV/provision.ps1" -ProjectRoot "$PROJECT_ROOT" -SkipTools -DryRun
103
+ ```
104
+
105
+ Look for "broken shim" warnings. For `repair`: re-run provision.ps1 live.
106
+
107
+ ### Step 6: Agent readiness (final gate)
108
+
109
+ ```bash
110
+ pnpm --filter @regen/codeflow startup:readiness
111
+ ```
112
+
113
+ This is the same check the startup guard runs. Zero blockers = environment healthy.
114
+
115
+ ## Output Format
116
+
117
+ ```
118
+ ## rdc:env <command> — Environment Health
119
+
120
+ | Check | Status | Detail |
121
+ |-------|--------|--------|
122
+ | Env repo | ✅ | v0.2.0, 0 behind origin |
123
+ | LIFEAI_ENV | ✅ | C:/Dev/lifeai-env (Machine scope) |
124
+ | Node | ✅ | v22.14.0 (min 22.0.0) |
125
+ | pnpm | ✅ | 10.12.1 (min 10.0.0) |
126
+ | clauth | ✅ | v1.30.2, unlocked |
127
+ | CodeFlow | ✅ | v0.33.11, brain=dev, operational |
128
+ | rdc-skills MCP | ✅ | v0.25.0, online |
129
+ | Shims | ✅ | 47/47 valid |
130
+ | Agent readiness | ✅ | 0 blockers |
131
+
132
+ **Verdict: environment healthy (9/9 checks pass)**
133
+ ```
134
+
135
+ For `repair`, append:
136
+ ```
137
+ ## Repairs Applied
138
+ - [x] Restarted clauth daemon
139
+ - [x] Rebuilt CodeFlow dist + restarted gateway
140
+ - [ ] rdc-skills: already running
141
+ ```
@@ -123,7 +123,42 @@ fs_import_git_files remote="origin" ref="claude-ai/docs-upload-123" paths=["docs
123
123
 
124
124
  This tool must fetch only, restore only named paths, optionally commit only those paths, and never push.
125
125
 
126
- ### 5. Safety rules
126
+ ### 5. `fs_exec` — always use `shell: false` (the default)
127
+
128
+ `fs_exec` supports an allowlisted set of commands: `git`, `pnpm`, `npx`,
129
+ `node`, `python3`, `rclone`, `bash`, `cat`, `grep`, `find`, `wc`,
130
+ `sha256sum`, `tsc`, `eslint`.
131
+
132
+ **Always use `shell: false`** (the default). Pass commands as arrays:
133
+
134
+ ```text
135
+ fs_exec command=["git", "add", ".rdc/plans/my-file.md"]
136
+ fs_exec command=["git", "status", "--porcelain"]
137
+ fs_exec command=["git", "diff", "--cached", "--name-only"]
138
+ fs_exec command=["git", "commit", "-m", "docs(plans): add my-file"]
139
+ ```
140
+
141
+ **Never set `shell: true`** unless you specifically need pipes/redirects.
142
+ `shell: true` spawns the host shell (`pwsh.exe` on Windows), which may not
143
+ be resolvable in the FS MCP server's process context (Store-installed
144
+ PowerShell uses a `WindowsApps` shim path that breaks across process
145
+ contexts). `shell: false` spawns the command directly — `git`, `node`, etc.
146
+ are on stable PATH locations and resolve reliably.
147
+
148
+ **On `fs_exec` failure with `spawn pwsh.exe ENOENT`:** this means the host
149
+ lacks a stable PowerShell 7 install. Fix: install PowerShell 7 via MSI
150
+ (`winget install --id Microsoft.PowerShell --scope machine --force`). But
151
+ the immediate workaround is always `shell: false` — the allowlisted commands
152
+ don't need a shell to execute.
153
+
154
+ **Before writing governed files** (`.rdc/plans/`, `.claude/rules/`, any path
155
+ with MDK validation hooks): read an existing exemplar in the same directory
156
+ via `fs_read` to learn the required frontmatter schema. Write complete,
157
+ correct content on the FIRST `fs_write`. A two-stage write creates a stale
158
+ index blob; use `fs_exec command=["git", "add", "<path>"]` to re-stage if
159
+ needed.
160
+
161
+ ### 6. Safety rules
127
162
 
128
163
  - Never run or request `git pull` for the dirty monorepo.
129
164
  - Never checkout a whole branch into the local worktree.
@@ -134,7 +169,7 @@ This tool must fetch only, restore only named paths, optionally commit only thos
134
169
  - Stage only imported paths when committing.
135
170
  - Never push from FS import unless the user explicitly asks for a push-capable workflow.
136
171
 
137
- ### 6. Completion report
172
+ ### 7. Completion report
138
173
 
139
174
  Report:
140
175
 
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: new-model
3
+ description: >
4
+ Register a new Reference Model completely — the yes/no gate that prevents half-registered models.
5
+ A reference model is DEFINED as registered in all four homes: (1) RPMS project_nodes row
6
+ (node_type=reference_model), (2) apps/vlas route group /models/<slug>, (3) apps/vlas
7
+ src/data/models/<slug> definitions, (4) global-corpus Drive directory. If ANY of the four is
8
+ missing, the model does not exist yet — run this skill.
9
+ TRIGGER: 'rdc:new-model', 'rdc new model', 'create model', 'new reference model', 'add a model',
10
+ 'register model', 'new model for', 'model for conservation easements', 'is this model registered',
11
+ 'model registration check'.
12
+ ---
13
+
14
+ # rdc:new-model — Reference Model Registration (complete or not at all)
15
+
16
+ ## When to run
17
+ - Creating any new reference model (conservation easement, regen data center, etc.)
18
+ - ANY time a model page/idea exists but you cannot confirm all four homes below
19
+ - Asked "is <model> registered?" → run the CHECK phase, report yes/no per home, offer to complete
20
+
21
+ ## The four homes (a model exists ONLY when all four do)
22
+ 1. **RPMS node** — `project_nodes` row: `node_type='reference_model'`, slug matches route slug exactly, status active, non-null description, metadata JSONB `{model_kind, capitals_profile, pathway_version, catalog_version, tabs}` when known.
23
+ 2. **Routes** — `apps/vlas/src/app/models/<slug>/` (or `(library)/<slug>/` for library-page models) + entry on the models library index.
24
+ 3. **Definitions** — `apps/vlas/src/data/models/<slug>/` (engine/constants/prompts as applicable; may start minimal).
25
+ 4. **Corpus** — Google Drive `global-corpus/VLAS/models/<slug>/` with subdirs `_working, _archive, _originals, diagrams, docs`. Drive models root folder ID: `1ua4zXohgZeYsZZTb1kUdnPqfN4eQAHuU`; copy structure from `_template` (`1ZVeq7iycg-dzG_iAKXrbTqIFYa6E26bQ`). Access Drive ONLY via the Google Drive connector (claude.ai) — H:\My Drive is NOT under any FS mount. From the CLI, the local sync path `H:\My Drive\global-corpus\VLAS\models\` may be used directly.
26
+
27
+ ## Procedure
28
+ ### Phase 0 — CHECK (always first; idempotent)
29
+ For the given slug, verify each home. Output a 4-line yes/no table. If all yes → report "registered" and stop.
30
+ ### Phase 1 — REGISTER (only the missing homes; never duplicate)
31
+ - RPMS: INSERT project_nodes with ON CONFLICT (slug) DO NOTHING; RETURNING id. Slug is kebab-case, matches route.
32
+ - Routes/definitions: scaffold minimal `/models/<slug>/page.tsx` + `src/data/models/<slug>/index.ts` if absent (full build is a separate plan/epic — this skill registers, it does not build the site).
33
+ - Corpus: create `<slug>/` + the five subdirs under the models root.
34
+ ### Phase 2 — RECORD
35
+ - Add the model to the library index page if missing.
36
+ - If created from claude.ai: note node id + Drive folder id in the session; if a related epic exists, add a note via update_work_item_status.
37
+ - Commit any repo changes on develop with a Work-Item trailer.
38
+
39
+ ## Rules
40
+ - NEVER create a model in fewer than four homes. Partial registration is the failure mode this skill exists to kill (it happened twice: regen-data-center shipped with a bare node; regenerative-development-and-design shipped with no node and no corpus dir).
41
+ - Slug is identical everywhere. No spaces, no case variants.
42
+ - Models NEVER live on place.fund, PRT, TPF, or RDC surfaces — VLAS only (models are teaching instruments of the standard).
43
+ - Catalog scoping: if the model needs interventions, decide model_slug scoping on stewardship_interventions BEFORE seeding (see library-conventions epic ba1b5d5d).
44
+
45
+ ## Done means
46
+ - [ ] Four-home check table all YES
47
+ - [ ] Node id + Drive folder id reported
48
+ - [ ] Library index lists the model
49
+ - [ ] Repo changes committed (develop, trailer)