@lifeaitools/rdc-skills 0.35.5 → 0.35.6

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rdc",
3
- "version": "0.35.5",
3
+ "version": "0.35.6",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code — plan, build, review, overnight unattended builds with work-item tracking and TDD enforcement.",
5
5
  "author": {
6
6
  "name": "LIFEAI",
package/commands/flow.md CHANGED
@@ -49,7 +49,7 @@ rdc:flow normal # clear — back to no flow declared
49
49
  ### 1. Read the current state
50
50
 
51
51
  ```bash
52
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-flow.mjs').then(m=>console.log(JSON.stringify(m.currentState(),null,2)))"
52
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-flow.mjs').href).then(m=>console.log(JSON.stringify(m.currentState(),null,2)))"
53
53
  ```
54
54
 
55
55
  `currentState()` reads BOTH axes at once — the declared flow AND any live `rdc-mode.mjs` hotfix/maintenance window — because a relaxed mode overrides a required flow (loosest state wins) and a status check that only showed flow would miss that override entirely. Report `flow` (or `null` if nothing declared — the fail-closed default), `flowReason`/`flowSetBy`/`flowSetAt` when set, and `mode` (`normal` unless a hotfix/maintenance window is open), with `modeReason`/`modeMinutesLeft` when it isn't.
@@ -57,7 +57,7 @@ node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-flow.mjs').then(m=>cons
57
57
  ### 2. Setting a plain work-shape flow — no reason required
58
58
 
59
59
  ```bash
60
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-flow.mjs').then(m=>console.log(JSON.stringify(m.setFlow(process.argv[1],{setBy:process.argv[2]}),null,2)))" "<flow>" "<session-id>"
60
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-flow.mjs').href).then(m=>console.log(JSON.stringify(m.setFlow(process.argv[1],{setBy:process.argv[2]}),null,2)))" "<flow>" "<session-id>"
61
61
  ```
62
62
 
63
63
  ### 3. Setting hotfix or maintenance — a reason is REQUIRED
@@ -65,7 +65,7 @@ node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-flow.mjs').then(m=>cons
65
65
  Refuse to proceed without one — `setFlow` throws on an empty reason for these two values, by design, same as `setMode` always did: an unexplained disarm is how a temporary state becomes permanent.
66
66
 
67
67
  ```bash
68
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-flow.mjs').then(m=>console.log(JSON.stringify(m.setFlow('hotfix',{reason:process.argv[1],setBy:process.argv[2]}),null,2)))" "<reason>" "<session-id>"
68
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-flow.mjs').href).then(m=>console.log(JSON.stringify(m.setFlow('hotfix',{reason:process.argv[1],setBy:process.argv[2]}),null,2)))" "<reason>" "<session-id>"
69
69
  ```
70
70
 
71
71
  Then state plainly, in the checklist: **which guards are now relaxed, that the safety set is still armed, and that this stays active until explicitly cleared (no TTL — active management, not a silent timer).**
@@ -73,7 +73,7 @@ Then state plainly, in the checklist: **which guards are now relaxed, that the s
73
73
  ### 4. Returning to normal
74
74
 
75
75
  ```bash
76
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-flow.mjs').then(m=>{m.clearFlow();console.log('cleared')})"
76
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-flow.mjs').href).then(m=>{m.clearFlow();console.log('cleared')})"
77
77
  ```
78
78
 
79
79
  Do this **as soon as the incident is over**, or the moment the declared work-shape changes.
package/commands/mode.md CHANGED
@@ -70,7 +70,7 @@ rdc:mode normal # close it early
70
70
  ### 1. Read the current mode
71
71
 
72
72
  ```bash
73
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-mode.mjs').then(m=>console.log(JSON.stringify(m.currentMode(),null,2)))"
73
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-mode.mjs').href).then(m=>console.log(JSON.stringify(m.currentMode(),null,2)))"
74
74
  ```
75
75
 
76
76
  Report `mode`, and when not normal also `reason`, `setBy`, and `minutesLeft`.
@@ -84,7 +84,7 @@ unexplained disarm is how a temporary state becomes permanent, and the reason is
84
84
  the entire content of the audit line.
85
85
 
86
86
  ```bash
87
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-mode.mjs').then(m=>console.log(JSON.stringify(m.setMode('hotfix',{reason:process.argv[1],minutes:Number(process.argv[2]||60),setBy:process.argv[3]}),null,2)))" "<reason>" "<minutes>" "<session-id>"
87
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-mode.mjs').href).then(m=>console.log(JSON.stringify(m.setMode('hotfix',{reason:process.argv[1],minutes:Number(process.argv[2]||60),setBy:process.argv[3]}),null,2)))" "<reason>" "<minutes>" "<session-id>"
88
88
  ```
89
89
 
90
90
  Then state plainly, in the checklist: **which guards are now off, that the safety
@@ -93,7 +93,7 @@ set is still armed, and the exact wall-clock time the window closes.**
93
93
  ### 3. Returning to normal
94
94
 
95
95
  ```bash
96
- node -e "import('file:///C:/Dev/lifeai-env/hooks/lib/rdc-mode.mjs').then(m=>{m.clearMode();console.log('normal')})"
96
+ node -e "import(require('url').pathToFileURL(process.env.LIFEAI_ENV + '/hooks/lib/rdc-mode.mjs').href).then(m=>{m.clearMode();console.log('normal')})"
97
97
  ```
98
98
 
99
99
  Do this **as soon as the incident is over**. The window expiring on its own is
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: open
3
+ description: >-
4
+ Usage `rdc:open [<slug>]` — orient before working. Answers where you are (repo, worktree, branch, dirty state) and what the target is (runtime, port, host, deploy path) from the registry, then names the harness shape to use. Run this first in any session that will change something.
5
+ ---
6
+
7
+ > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
8
+ > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
9
+
10
+ # rdc:open — you are here, this is the thing, use this shape
11
+
12
+ ## Why this exists
13
+
14
+ Orientation ran **3.4× production work** across a measured 36-hour window —
15
+ 47.6% of tool calls establishing position and identity, 14.1% actually changing
16
+ something. `git rev-parse` alone was 316 calls, 6% of everything.
17
+
18
+ Cross-session rediscovery was **1.4%**. That number is the point: agents are not
19
+ forgetting what they learned, they are working new ground almost every time and
20
+ nothing tells them where they are. This is a surfacing problem, not a memory
21
+ problem, so caching buys nothing and an opening statement buys everything.
22
+
23
+ ## When to Use
24
+
25
+ - **First call of any session that will change something.** Before the first
26
+ read, not after the third `git status`.
27
+ - When you are handed a slug and do not know its runtime, port, or host.
28
+ - After a compaction, when position facts have aged out of context.
29
+ - Before any deploy — `rdc:deploy` assumes you already know the target's shape.
30
+
31
+ Not needed for a pure conversation turn.
32
+
33
+ ## What it answers
34
+
35
+ | Question | Source | Never |
36
+ |---|---|---|
37
+ | which repo / worktree / branch am I in | `git rev-parse`, `git status` | assumed from a hardcoded path |
38
+ | is my tree clean, am I behind | `git status -sb` | inferred from elapsed time |
39
+ | what IS this slug | `get_deployment('<slug>')` | guessed from the directory name |
40
+ | runtime, port, PM2 name, host | the registry | inferred from files on disk |
41
+ | who depends on it | the registry | assumed to be nothing |
42
+
43
+ **Two guesses this replaces, both measured wrong in practice:** filesystem
44
+ inference said `node-build` where the registry says `ts-server`; and
45
+ directory-name-as-slug fails outright — `packages/codeflow` is `codeflow-mcp`,
46
+ `apps/admin` is `portal`.
47
+
48
+ ## Steps
49
+
50
+ 1. **Position.** `node scripts/orient.mjs` — repo, worktree, branch @ sha,
51
+ upstream, dirty count. Relative paths from here are correct by construction;
52
+ a hardcoded `C:/Dev/regen-root/...` from a lane points at a *different
53
+ checkout*.
54
+ 2. **Target.** `node scripts/orient.mjs <slug>` — resolves the slug through
55
+ `get_deployment`, printing runtime, port, host, deploy path and dependents.
56
+ `monorepo_path` NULL means a standalone repo, not in this tree.
57
+ 3. **Harness.** Name the shape the target's class implies:
58
+
59
+ | class | build | dev | prod |
60
+ |---|---|---|---|
61
+ | `apps/<name>` | `pnpm --filter @regen/<name> build` | PM2 @ Vultr | Coolify |
62
+ | `packages/<name>` | `pnpm --filter @regen/<name> build` | imported | `npm publish` |
63
+ | `sites/`, `models/` | static/vite | PM2 @ Vultr | Coolify |
64
+ | standalone | its own tooling | — | Coolify |
65
+
66
+ 4. **State the ground in one line** and start. Do not re-derive it later in the
67
+ turn.
68
+
69
+ ## Checklist
70
+
71
+ ```
72
+ [ ] position resolved — repo, worktree, branch, dirty count
73
+ [ ] target resolved from the registry (or: no slug given, position only)
74
+ [ ] harness shape named for the target's class
75
+ [ ] blockers noted — behind upstream, dirty tree, service down
76
+ ```
77
+
78
+ ## Related
79
+
80
+ - `rdc:flow` — declares what KIND of work this is. `rdc:open` says where you are;
81
+ `rdc:flow` says what you are doing. Both, in that order.
82
+ - `rdc:status` — open epics and queue. That is the work; this is the ground.
83
+ - `$LIFEAI_ENV/docs/GATES-GUARDS-DENIES.md` — when a guard stops you, that names
84
+ the shape that works.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.35.5",
3
+ "version": "0.35.6",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -230,7 +230,7 @@ most common failure and it fails at the guard layer, not the prompt layer.
230
230
  > version of this table said the opposite.** Managed identity is an 8-field record
231
231
  > (`lane, role, repoIdentity, ownerPid, ownerStartFingerprint, sessionId,
232
232
  > leaseEpoch, ownerToken`) built by `buildStartupIdentity()` in
233
- > [`pool/codex-topology.mjs`](file:///C:/Dev/lifeai-env/pool/codex-topology.mjs)
233
+ > [`pool/codex-topology.mjs`](file:///C:/Dev/lifeai/node_modules/@lifeai/lifeai-env/pool/codex-topology.mjs)
234
234
  > and minted **only by the interactive launcher**, which also claims the lease.
235
235
  > `codex exec` has no lane-claim path, so it cannot produce that record — which
236
236
  > means **a headless Codex peer cannot write in any lane, including its own**.
@@ -245,7 +245,7 @@ most common failure and it fails at the guard layer, not the prompt layer.
245
245
  > fires when there is **no lease at all** (`ownerMatchesLease` returns false for a
246
246
  > null lease), so it will send you hunting a conflicting owner that does not exist.
247
247
 
248
- file:///C:/Dev/lifeai-env/pool/codex-topology.mjs
248
+ file:///C:/Dev/lifeai/node_modules/@lifeai/lifeai-env/pool/codex-topology.mjs
249
249
  | **`local-llm`** | local endpoint per `.claude/context/clauth.md`; credential via `curl -s http://127.0.0.1:52437/v/<service>` | none (no repo attachment) | Small context windows: send the contract and the open points, never the whole document. Link paths instead of pasting files. |
250
250
  | **`claude-agent`** | `Agent` tool, or `claude -p --bare` / `claude --bg` | **`isolation: "worktree"` as an actual tool parameter** if it will commit — a prose claim of isolation is inert | Parallel agents on a shared checkout race on `git stash` and `.git/index`. See `.claude/rules/subagent-credentials.md`. |
251
251
  | **`claude-ai`** | chitchat MCP (`chitchat_send` / `chitchat_poll` / `chitchat_reply`) + SSE | session-scoped | Messages evaporate when the session stops — export durable decisions to TinTin. |
@@ -14,17 +14,39 @@ description: "Usage `rdc:env [status|install|repair|update]` — Manage the LIFE
14
14
  - After a reboot or GPU crash — verify everything came back up
15
15
  - Setting up a fresh box — install all tools and services
16
16
  - Something is broken — repair services, MCPs, CodeFlow
17
- - Routine update — pull latest env repo and run drift check
17
+ - Routine update — bring the harness current and run a drift check
18
18
  - "check the environment", "fix my setup", "install environment"
19
19
 
20
+ ## The harness arrives by one of two channels — find out which BEFORE acting
21
+
22
+ `$LIFEAI_ENV` is **not** necessarily a git repo, and on a normal box it is not.
23
+
24
+ | channel | what `$LIFEAI_ENV` is | who owns freshness |
25
+ |---|---|---|
26
+ | **npm** (the normal box) | an installed package, e.g. `C:/Dev/lifeai/node_modules/@lifeai/lifeai-env` | `npm` — `env-boot` installs into the owning prefix at session start |
27
+ | **git** (the publishing box) | a checkout of `LIFEAI/environment` | `land.mjs` → fetch → `env-install` |
28
+
29
+ Every `git` command in this skill applies to the **git** channel only. Against an
30
+ npm install they fail outright — `fatal: not a git repository` — because there is
31
+ no `.git` there at all. Ask first:
32
+
33
+ ```bash
34
+ node "$LIFEAI_ENV/machines/env-boot.mjs" check
35
+ ```
36
+
37
+ It reports the installed version, the published version, and which channel this
38
+ box is on, and changes nothing. Do not infer the channel from the path: the git
39
+ tree at `C:/Dev/lifeai-env` still exists on the publishing box alongside the npm
40
+ install, so a path that looks familiar proves nothing.
41
+
20
42
  ## Subcommands
21
43
 
22
44
  | Command | What it does |
23
45
  |---------|-------------|
24
- | `status` (default) | Read-only check: env repo version, tool versions, MCP health, shim integrity, CodeFlow brain |
25
- | `install` | Full provision: clone env repo if missing, set LIFEAI_ENV, install tools, configure MCPs |
46
+ | `status` (default) | Read-only check: channel + harness version, tool versions, MCP health, shim integrity, CodeFlow brain |
47
+ | `install` | Full provision: install the harness if missing, set LIFEAI_ENV, install tools, configure MCPs |
26
48
  | `repair` | Diagnose and fix: restart crashed services, rebuild stale dists, fix broken shims |
27
- | `update` | Pull latest env repo, re-run audit, report drift, refresh shims if new scripts added |
49
+ | `update` | Bring the harness current for its channel, re-run audit, report drift, refresh shims if new scripts added |
28
50
 
29
51
  ## Procedure
30
52
 
@@ -35,21 +57,42 @@ LIFEAI_ENV="${LIFEAI_ENV:-C:/Dev/lifeai-env}"
35
57
  ```
36
58
 
37
59
  If `$LIFEAI_ENV` is not set AND the default path doesn't exist:
38
- - For `install`: clone the repo and set the env var
39
- - For all others: STOP with `BLOCKED: environment repo not found. Run: rdc:env install`
60
+ - For `install`: install the harness (see the channel table above — npm on a
61
+ normal box) and set the env var. `provision.ps1` is self-locating
62
+ (`$EnvRoot = $PSScriptRoot`), so running it *from* an install is what points
63
+ `LIFEAI_ENV` at that install. Machine scope needs elevation; without it it
64
+ falls back to User scope and says so.
65
+ - For all others: STOP with `BLOCKED: environment harness not found. Run: rdc:env install`
40
66
 
41
67
  Read `$LIFEAI_ENV/manifest.json` — this is the harness inventory.
42
68
 
43
- ### Step 1: Environment repo state
69
+ ### Step 1: Harness state — channel first, then freshness
44
70
 
45
71
  ```bash
46
- git -C "$LIFEAI_ENV" fetch origin 2>/dev/null
47
- git -C "$LIFEAI_ENV" rev-list --count HEAD..origin/main
72
+ node "$LIFEAI_ENV/machines/env-boot.mjs" check
48
73
  ```
49
74
 
50
- Report: version from manifest.json, commits behind origin, last pull date.
75
+ One command, both channels, no mutation. It prints the installed version, the
76
+ published version, and — on an npm hub outside `npm root -g` — the prefix an
77
+ update would target.
78
+
79
+ Report: version from manifest.json, the channel, and how far behind it is.
80
+
81
+ **For `update` and `repair`, bring it current by its own channel:**
82
+
83
+ ```bash
84
+ # npm channel — env-boot derives the owning prefix itself. Do NOT hand-roll a
85
+ # prefix, and do NOT use a bare `npm install -g`: on a hub outside `npm root -g`
86
+ # that silently updates a DIFFERENT directory and the hub never moves.
87
+ node "$LIFEAI_ENV/machines/env-boot.mjs"
88
+
89
+ # git channel (publishing box only)
90
+ git -C "$LIFEAI_ENV" pull --ff-only origin main
91
+ ```
51
92
 
52
- For `update`: pull if behind. For `repair`: pull if behind (stale harness may be the cause).
93
+ > **Never report a version comparison as a freshness verdict without saying which
94
+ > channel produced it.** On a git hub `env-boot` deliberately does not ask npm at
95
+ > all — the two versions differing there is expected, not a broken publish.
53
96
 
54
97
  ### Step 2: Tool versions (audit)
55
98
 
@@ -124,8 +167,8 @@ This is the same check the startup guard runs. Zero blockers = environment healt
124
167
 
125
168
  | Check | Status | Detail |
126
169
  |-------|--------|--------|
127
- | Env repo | ✅ | v0.2.0, 0 behind origin |
128
- | LIFEAI_ENV | ✅ | C:/Dev/lifeai-env (Machine scope) |
170
+ | Harness | ✅ | v0.8.119, npm channel, current |
171
+ | LIFEAI_ENV | ✅ | C:/Dev/lifeai/node_modules/@lifeai/lifeai-env (Machine scope) |
129
172
  | Node | ✅ | v22.14.0 (min 22.0.0) |
130
173
  | pnpm | ✅ | 10.12.1 (min 10.0.0) |
131
174
  | clauth | ✅ | v1.30.2, unlocked |