@lifeaitools/rdc-skills 0.35.3 → 0.35.5

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 (36) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/commands/build.md +19 -0
  4. package/commands/deploy.md +20 -1
  5. package/commands/fixit.md +17 -0
  6. package/commands/flow.md +94 -0
  7. package/commands/mode.md +6 -0
  8. package/commands/release.md +11 -0
  9. package/guides/agent-bootstrap.md +248 -204
  10. package/hooks/foreground-process-gate.js +22 -64
  11. package/package.json +2 -2
  12. package/scripts/install-rdc-skills.js +11 -3
  13. package/skills/architecture-reviewer/SKILL.md +1 -0
  14. package/skills/behavior-audit/SKILL.md +1 -0
  15. package/skills/brochure/SKILL.md +1 -0
  16. package/skills/brochurify/SKILL.md +1 -0
  17. package/skills/clean-code-analyzer/SKILL.md +1 -0
  18. package/skills/convert/SKILL.md +1 -0
  19. package/skills/edit/SKILL.md +12 -0
  20. package/skills/env/SKILL.md +1 -0
  21. package/skills/extract-verifier-rules/SKILL.md +1 -0
  22. package/skills/fs-mcp/SKILL.md +1 -0
  23. package/skills/help/SKILL.md +1 -0
  24. package/skills/lifeai-brochure-author/SKILL.md +1 -0
  25. package/skills/new-model/SKILL.md +1 -0
  26. package/skills/package-design/SKILL.md +1 -0
  27. package/skills/pattern-advisor/SKILL.md +1 -0
  28. package/skills/pattern-refactoring-guide/SKILL.md +1 -0
  29. package/skills/refactor/SKILL.md +1 -0
  30. package/skills/regen-media/SKILL.md +1 -0
  31. package/skills/solid-validator/SKILL.md +1 -0
  32. package/skills/terminal-config/SKILL.md +1 -0
  33. package/skills/testing-strategy/SKILL.md +1 -0
  34. package/tests/foreground-process-gate.test.mjs +114 -0
  35. package/tests/harness-gates.test.mjs +9 -27
  36. package/tests/install-rdc-skills.test.mjs +91 -1
@@ -1,11 +1,11 @@
1
- # Agent Bootstrap — Read This First
2
- > Every dispatched agent reads this before their role-specific guide.
3
- > Base guide for rdc-skills — provides credential, git, and reporting patterns across projects.
4
-
5
- ---
6
-
7
- ## Who You Are
8
-
1
+ # Agent Bootstrap — Read This First
2
+ > Every dispatched agent reads this before their role-specific guide.
3
+ > Base guide for rdc-skills — provides credential, git, and reporting patterns across projects.
4
+
5
+ ---
6
+
7
+ ## Who You Are
8
+
9
9
  You are a subagent dispatched by the rdc:build supervisor. You have a specific
10
10
  scope (files, package, feature) that will be in your prompt. Stay in that scope.
11
11
  NEVER modify files outside it.
@@ -15,198 +15,242 @@ RDC implementation posture for assumptions, minimal changes, surgical scope,
15
15
  verification evidence, and escalation.
16
16
 
17
17
  ---
18
-
19
- ## Credentials — Daemon Access Pattern
20
-
21
- You do NOT have access to cloud MCP connectors. Instead, all credentials
22
- come from a daemon running locally (typically on localhost:52437).
23
-
24
- **Ping first to confirm availability:**
25
- ```bash
26
- curl -s http://127.0.0.1:52437/ping
27
- ```
28
- If it doesn't respond — report BLOCKED, do not proceed.
29
-
30
- **Get a credential:**
31
- ```bash
32
- curl -s http://127.0.0.1:52437/get/<service>
33
- ```
34
-
35
- **Pattern for extracting key/value without printing:**
36
- ```bash
37
- # Correct pattern — never echo the key
38
- KEY=$(curl -s http://127.0.0.1:52437/get/<service> | python3 -c "import sys,json; print(json.load(sys.stdin)['key'])")
39
- curl -s -H "Authorization: Bearer $KEY" https://api.example.com/...
40
- ```
41
-
42
- **Never print credentials to stdout.** Capture to a variable, use inline, discard.
43
-
44
- ---
45
-
46
- ## Project Directory Convention
47
-
48
- This plugin uses the `.rdc/` directory convention. Check for it first:
49
-
50
- ```bash
51
- # Check if .rdc/ exists at project root
52
- ls {PROJECT_ROOT}/.rdc/config.json 2>/dev/null && echo "using .rdc/" || echo "using docs/ fallback"
53
- ```
54
-
55
- **Path resolution rule:**
56
- - Guides: `{PROJECT_ROOT}/.rdc/guides/` → fallback: `{PROJECT_ROOT}/docs/guides/`
57
- - Plans: `{PROJECT_ROOT}/.rdc/plans/` → fallback: `{PROJECT_ROOT}/docs/plans/`
58
- - Reports: `{PROJECT_ROOT}/.rdc/reports/` → fallback: `{PROJECT_ROOT}/docs/reports/`
59
- - Research: `{PROJECT_ROOT}/.rdc/research/` → fallback: `{PROJECT_ROOT}/docs/research/`
60
-
61
- If `.rdc/config.json` exists, read it for project metadata (name, description, conventions).
62
-
63
- ---
64
-
65
- ## Database Access — Check Project Overlay
66
-
67
- The project overlay guide will specify:
68
- - Database project reference / instance name
69
- - Whether to use MCP connectors or daemon
70
- - Available RPC functions
71
- - Work item management patterns
72
-
73
- Read the project-specific agent-bootstrap.md overlay for exact connection details.
74
-
75
- ---
76
-
77
- ## Git Rules
78
-
79
- - Branch: Always use the project's primary development branch (typically `develop` or `main`)
80
- - Auto-commit after completing your scope — no confirmation needed
81
- - Commit message must use conventional format: `feat/fix/chore/refactor(<scope>): description`
82
- - Push to origin after committing
83
- - NEVER force-push
84
-
85
- ---
86
-
18
+
19
+ ## Credentials — Daemon Access Pattern
20
+
21
+ You do NOT have access to cloud MCP connectors. Instead, all credentials
22
+ come from a daemon running locally (typically on localhost:52437).
23
+
24
+ **Ping first to confirm availability:**
25
+ ```bash
26
+ curl -s http://127.0.0.1:52437/ping
27
+ ```
28
+ If it doesn't respond — report BLOCKED, do not proceed.
29
+
30
+ **Get a credential:**
31
+ ```bash
32
+ curl -s http://127.0.0.1:52437/get/<service>
33
+ ```
34
+
35
+ **Pattern for extracting key/value without printing:**
36
+ ```bash
37
+ # Correct pattern — never echo the key
38
+ KEY=$(curl -s http://127.0.0.1:52437/get/<service> | python3 -c "import sys,json; print(json.load(sys.stdin)['key'])")
39
+ curl -s -H "Authorization: Bearer $KEY" https://api.example.com/...
40
+ ```
41
+
42
+ **Never print credentials to stdout.** Capture to a variable, use inline, discard.
43
+
44
+ ---
45
+
46
+ ## Project Directory Convention
47
+
48
+ This plugin uses the `.rdc/` directory convention. Check for it first:
49
+
50
+ ```bash
51
+ # Check if .rdc/ exists at project root
52
+ ls {PROJECT_ROOT}/.rdc/config.json 2>/dev/null && echo "using .rdc/" || echo "using docs/ fallback"
53
+ ```
54
+
55
+ **Path resolution rule:**
56
+ - Guides: `{PROJECT_ROOT}/.rdc/guides/` → fallback: `{PROJECT_ROOT}/docs/guides/`
57
+ - Plans: `{PROJECT_ROOT}/.rdc/plans/` → fallback: `{PROJECT_ROOT}/docs/plans/`
58
+ - Reports: `{PROJECT_ROOT}/.rdc/reports/` → fallback: `{PROJECT_ROOT}/docs/reports/`
59
+ - Research: `{PROJECT_ROOT}/.rdc/research/` → fallback: `{PROJECT_ROOT}/docs/research/`
60
+
61
+ If `.rdc/config.json` exists, read it for project metadata (name, description, conventions).
62
+
63
+ ---
64
+
65
+ ## Database Access — Check Project Overlay
66
+
67
+ The project overlay guide will specify:
68
+ - Database project reference / instance name
69
+ - Whether to use MCP connectors or daemon
70
+ - Available RPC functions
71
+ - Work item management patterns
72
+
73
+ Read the project-specific agent-bootstrap.md overlay for exact connection details.
74
+
75
+ ---
76
+
77
+ ## Git Rules
78
+
79
+ - Branch: Always use the project's primary development branch (typically `develop` or `main`)
80
+ - Auto-commit after completing your scope — no confirmation needed
81
+ - Commit message must use conventional format: `feat/fix/chore/refactor(<scope>): description`
82
+ - Push to origin after committing
83
+ - NEVER force-push
84
+
85
+ ---
86
+
87
87
  ## Build Rules
88
88
 
89
89
  Never run `pnpm build` or equivalent full builds locally — they consume excessive memory.
90
90
  Type-check only: `npx tsc --noEmit --project <path>/tsconfig.json`
91
91
  Run tests only for modified packages: modify tests in isolation, not whole suite.
92
92
 
93
- ### No Foreground Windows
93
+ ### Terminal/process launches — caller-logged, not hard-blocked
94
94
 
95
- Agent-launched processes must not steal focus. This is a hard local-operator
96
- rule, not a preference.
95
+ **Narrowed 2026-08-26** (epic 688ad6da, lifeai-env; direct operator
96
+ instruction: "remove the PreToolUse foreground-window guard entirely...
97
+ replace it with caller-logging for traceability"). The old hard block on
98
+ every raw `Start-Process`/`cmd /c start`/window-focus API/bare `.ps1` launch
99
+ is retired — `foreground-process-gate.js` (rdc-skills) no longer enforces any
100
+ of it. The replacement isn't a weaker rule; it's a different mechanism:
101
+ lifeai-env's `lib/TermLaunch.psm1` (`Invoke-TermLaunchHidden` /
102
+ `Invoke-TermLaunchInteractive`) logs every caller (script + line + argv) to
103
+ `C:/Dev/.logs` **before** spawning, for every launch — which answers "who
104
+ launched this and with what" for every case, not just the ones a regex
105
+ pattern happened to catch.
97
106
 
98
- - Playwright must run headless. Do not use `--headed`, `--ui`, `codegen`, `open`, `show-report`, or `PWDEBUG=1` in agent sessions.
99
- - Use list/dot/json reporters and saved trace/report artifacts instead of opening the Playwright UI.
100
- - PowerShell helpers must use `-WindowStyle Hidden -NonInteractive`, or a hidden wrapper.
101
- - `Start-Process` must include `-WindowStyle Hidden` or `-WindowStyle Minimized`.
102
- - `cmd /c start` must use `/min` for intentionally visible tools or `/b` for background work.
103
- - Node/cmd/ps1 helpers launched by hooks must go through the RDC hidden hook runner.
107
+ - Use `Invoke-TermLaunchHidden -Command <cmd> [-Arguments][-WorkingDirectory]`
108
+ for a background/no-window process, and `Invoke-TermLaunchInteractive
109
+ [-Title]` for a visible new terminal tab never a raw `Start-Process`/
110
+ `wt.exe` call. Neither primitive accepts an arbitrary inline multi-line
111
+ command string, only a flat command + argument array or a `-File <script>`
112
+ path this structurally prevents the `wt.exe -Command` argv-mangling bug
113
+ class, which no amount of pattern-blocking ever fully closed.
114
+ - Node/cmd/ps1 helpers launched by hooks must still go through the RDC hidden
115
+ hook runner (`hooks/run-bash-hidden.ps1` and its RdcRun contract) — that
116
+ convention is unchanged.
117
+
118
+ **One safety property survives, unrelated to the above and never retired:**
119
+ Playwright must still run headless in agent sessions. Do not use `--headed`,
120
+ `--ui`, `codegen`, `open`, `show-report`, or `PWDEBUG=1`. Use list/dot/json
121
+ reporters and saved trace/report artifacts instead of opening the Playwright
122
+ UI. `foreground-process-gate.js` still hard-blocks this — it was never a
123
+ terminal-launch-primitive question, so narrowing the launch rules above never
124
+ touched it.
104
125
 
105
126
  Check the project overlay for specific language, package manager, and build constraints.
106
-
107
- ---
108
-
109
- ## RDC_TEST Sandbox Contract
110
-
111
- When `RDC_TEST=1` is set, the skill is running inside the Tier 2 sandbox harness. Short-circuit all destructive external side effects.
112
-
113
- **How to detect:** `process.env.RDC_TEST === '1'` (Node/JS) or `[ "$RDC_TEST" = "1" ]` (bash). The Tier 2 runner sets this before invoking `claude --print`.
114
-
115
- **Allowed under RDC_TEST** run normally, no guard:
116
-
117
- | Operation | Why |
118
- |-----------|-----|
119
- | Local git commits | Commit to the worktree branch; never pushed |
120
- | Local filesystem writes | Inside the sandbox worktree |
121
- | Supabase reads | Assertions read prod DB; no writes |
122
- | Service reads | Coolify status, CF DNS lookup, GitHub read — all safe |
123
- | `clauth` credential reads | Read-only against the daemon |
124
-
125
- **Short-circuit under RDC_TEST** must be wrapped in a guard:
126
-
127
- - Supabase INSERT/UPDATE/DELETE (work items, prototype_registry, design_context, etc.) — runner uses main-db mode, no test branch
128
- - Coolify app deploys / restarts / config writes
129
- - Cloudflare DNS writes / cache purges
130
- - R2 object writes / deletes
131
- - `git push` to any remote
132
- - `gh pr create`, `gh release create`, tag pushes
133
- - `npm publish`
134
- - Any webhook fire, email send, Slack post
135
- - MCP connector tools that mutate external state (e.g. `mcp__coolify__deploy`)
136
-
137
- **Bash pattern:**
138
- ```bash
139
- if [ "$RDC_TEST" != "1" ]; then
127
+
128
+ ### Harness Use — Global Policy (applies to every rdc:* skill)
129
+
130
+ If ANY step of the skill you are executing — regardless of which skill —
131
+ needs to materialize a real product shape, open a signed edit session, run a
132
+ target's own declared build gates, or deploy to dev-PM2/npm-registry, you
133
+ MUST use the real, tested `rdc-harness` CLI instead of hand-rolled bash/curl:
134
+
135
+ ```bash
136
+ node C:/Dev/rdc-harness/bin/rdc-harness.mjs <create|open|edit|build|deploy> <slug> --monorepo-root <your own worktree, never the shared checkout>
137
+ ```
138
+
139
+ One JSON receipt per call, exit 0/1 — use it as evidence for whatever
140
+ checklist/commit step it satisfies. This is a genuinely FORCED requirement,
141
+ not a suggestion: a skill that hand-rolls its own create/open/build/deploy
142
+ logic when this applies is doing exactly the duplicated, unproven work this
143
+ policy exists to stop.
144
+
145
+ This does NOT apply to a skill with no create/open/build/deploy step at all
146
+ (status/report/help/analysis/media/conversation skills)do not invent one.
147
+ `open`/`edit` require `RDC_HARNESS_ISSUER_SECRET` set explicitly, no default.
148
+ `deploy` has zero Coolify awareness (Coolify stays `rdc:deploy`'s own path)
149
+ and no live co-editing surface outside `site-html`/`site-ts` targets.
150
+
151
+ ---
152
+
153
+ ## RDC_TEST Sandbox Contract
154
+
155
+ When `RDC_TEST=1` is set, the skill is running inside the Tier 2 sandbox harness. Short-circuit all destructive external side effects.
156
+
157
+ **How to detect:** `process.env.RDC_TEST === '1'` (Node/JS) or `[ "$RDC_TEST" = "1" ]` (bash). The Tier 2 runner sets this before invoking `claude --print`.
158
+
159
+ **Allowed under RDC_TEST** — run normally, no guard:
160
+
161
+ | Operation | Why |
162
+ |-----------|-----|
163
+ | Local git commits | Commit to the worktree branch; never pushed |
164
+ | Local filesystem writes | Inside the sandbox worktree |
165
+ | Supabase reads | Assertions read prod DB; no writes |
166
+ | Service reads | Coolify status, CF DNS lookup, GitHub read — all safe |
167
+ | `clauth` credential reads | Read-only against the daemon |
168
+
169
+ **Short-circuit under RDC_TEST** — must be wrapped in a guard:
170
+
171
+ - Supabase INSERT/UPDATE/DELETE (work items, prototype_registry, design_context, etc.) — runner uses main-db mode, no test branch
172
+ - Coolify app deploys / restarts / config writes
173
+ - Cloudflare DNS writes / cache purges
174
+ - R2 object writes / deletes
175
+ - `git push` to any remote
176
+ - `gh pr create`, `gh release create`, tag pushes
177
+ - `npm publish`
178
+ - Any webhook fire, email send, Slack post
179
+ - MCP connector tools that mutate external state (e.g. `mcp__coolify__deploy`)
180
+
181
+ **Bash pattern:**
182
+ ```bash
183
+ if [ "$RDC_TEST" != "1" ]; then
140
184
  curl -X POST "$DEPLOY_API_BASE/api/v1/applications/$UUID/deploy" ...
141
- else
142
- echo "[RDC_TEST] skipping Coolify deploy"
143
- fi
144
- ```
145
-
146
- **Node/JS pattern:**
147
- ```js
148
- if (process.env.RDC_TEST !== '1') {
149
- await deployToCoolify(...);
150
- } else {
151
- console.log('[RDC_TEST] skipping Coolify deploy');
152
- }
153
- ```
154
-
155
- **Why this matters:** Tier 2 runs every skill in a throwaway sandbox. If your skill fires a real deploy or DNS change under `RDC_TEST`, the test isn't a test — it's a production incident.
156
-
157
- **New-skill contract:** every new `rdc:*` skill MUST honor `RDC_TEST` before shipping. Tier 2 manifests will fail any skill that writes to external state under the flag.
158
-
185
+ else
186
+ echo "[RDC_TEST] skipping Coolify deploy"
187
+ fi
188
+ ```
189
+
190
+ **Node/JS pattern:**
191
+ ```js
192
+ if (process.env.RDC_TEST !== '1') {
193
+ await deployToCoolify(...);
194
+ } else {
195
+ console.log('[RDC_TEST] skipping Coolify deploy');
196
+ }
197
+ ```
198
+
199
+ **Why this matters:** Tier 2 runs every skill in a throwaway sandbox. If your skill fires a real deploy or DNS change under `RDC_TEST`, the test isn't a test — it's a production incident.
200
+
201
+ **New-skill contract:** every new `rdc:*` skill MUST honor `RDC_TEST` before shipping. Tier 2 manifests will fail any skill that writes to external state under the flag.
202
+
159
203
  **Known blocker:** Project-specific cwd hooks must check `process.env.RDC_TEST === '1'` and call `process.exit(0)` early to allow Tier 2 sandbox runs. Without this bypass, headless self-test invocations can fail before the skill loads. File: `~/.claude/hooks/check-cwd.js`.
160
-
161
- ---
162
-
163
- ## Completion Report
164
-
165
- When your scope is done, return a structured report to the supervisor:
166
-
167
- ```
168
- AGENT_COMPLETE: {
169
- scope: "<what you were assigned>",
170
- files_changed: ["path/to/file", ...],
171
- work_item_id: "<id if you had one>",
172
- commits: ["<hash> <message>"],
173
- blockers: ["<anything that needs supervisor attention>"]
174
- }
175
- ```
176
-
177
- If you hit a blocker mid-task: stop, report it, do not guess or work around it.
178
-
179
- ---
180
-
181
- ## Self-Check Rules — Prevent Getting Lost
182
-
183
- ### 10-Minute Rule
184
- If you have been working on a **single step** for more than 10 minutes without measurable progress (no new files changed, no successful tool calls, no forward movement), **stop immediately**. Do not keep trying variations. Report it as a blocker.
185
-
186
- ### 2-Retry Rule
187
- If the **same command or approach fails twice**, stop. Do not attempt a third variation or creative workaround. Report the failure with the exact error output.
188
-
189
- ### Scope Drift Rule
190
- If you discover that fixing your assigned task would also require changing files **outside your scope**, stop. Do not fix them. Add them to `blockers` in your AGENT_COMPLETE report. The supervisor assigns them separately.
191
-
192
- ### What "measurable progress" means
193
- - A file was created or modified ✅
194
- - A tool call succeeded and returned useful data ✅
195
- - A command ran without error ✅
196
- - Trying the same thing with slightly different parameters ❌
197
- - Reading the same file again hoping for different insight ❌
198
- - Rephrasing a failing query ❌
199
-
200
- ---
201
-
204
+
205
+ ---
206
+
207
+ ## Completion Report
208
+
209
+ When your scope is done, return a structured report to the supervisor:
210
+
211
+ ```
212
+ AGENT_COMPLETE: {
213
+ scope: "<what you were assigned>",
214
+ files_changed: ["path/to/file", ...],
215
+ work_item_id: "<id if you had one>",
216
+ commits: ["<hash> <message>"],
217
+ blockers: ["<anything that needs supervisor attention>"]
218
+ }
219
+ ```
220
+
221
+ If you hit a blocker mid-task: stop, report it, do not guess or work around it.
222
+
223
+ ---
224
+
225
+ ## Self-Check Rules — Prevent Getting Lost
226
+
227
+ ### 10-Minute Rule
228
+ If you have been working on a **single step** for more than 10 minutes without measurable progress (no new files changed, no successful tool calls, no forward movement), **stop immediately**. Do not keep trying variations. Report it as a blocker.
229
+
230
+ ### 2-Retry Rule
231
+ If the **same command or approach fails twice**, stop. Do not attempt a third variation or creative workaround. Report the failure with the exact error output.
232
+
233
+ ### Scope Drift Rule
234
+ If you discover that fixing your assigned task would also require changing files **outside your scope**, stop. Do not fix them. Add them to `blockers` in your AGENT_COMPLETE report. The supervisor assigns them separately.
235
+
236
+ ### What "measurable progress" means
237
+ - A file was created or modified ✅
238
+ - A tool call succeeded and returned useful data ✅
239
+ - A command ran without error ✅
240
+ - Trying the same thing with slightly different parameters ❌
241
+ - Reading the same file again hoping for different insight ❌
242
+ - Rephrasing a failing query ❌
243
+
244
+ ---
245
+
202
246
  ## ⛔ Implementation Report + CodeFlow Exit Contract
203
247
 
204
248
  Every implementation agent MUST follow this protocol before moving a work item
205
249
  to `review`. Agents do not close non-epic work as `done`; validators close it
206
250
  after fresh verification.
207
-
208
- ### Step 1 — Tick checklist items as you complete them
209
-
251
+
252
+ ### Step 1 — Tick checklist items as you complete them
253
+
210
254
  ```sql
211
255
  SELECT update_checklist_item(
212
256
  '<work-item-id>'::uuid,
@@ -221,10 +265,10 @@ SELECT update_checklist_item(
221
265
  Call this for each item AS you complete it — not all at once at the end. The
222
266
  database records every tick in `work_item_checklist_events`. Supervisor and
223
267
  validator re-ticks are rejected by the exit gate.
224
-
225
- ### Step 2 — Submit implementation report BEFORE marking done
226
-
227
- ```sql
268
+
269
+ ### Step 2 — Submit implementation report BEFORE marking done
270
+
271
+ ```sql
228
272
  SELECT submit_implementation_report(
229
273
  '<work-item-id>'::uuid,
230
274
  '{
@@ -276,20 +320,20 @@ SELECT update_work_item_status(
276
320
  If any `required: true` checklist item is still unchecked, was re-ticked by a
277
321
  supervisor/validator, or was ticked by a different session than the originating
278
322
  agent, the DB and PreToolUse hook reject the close.
279
-
280
- ### Supervisor workflow
281
-
282
- - All zeros → clean run, proceed
283
- - `flags_count > 0` or `deviations_count > 0` → pull full report:
284
- ```sql
285
- SELECT implementation_report FROM work_items WHERE id = '<id>';
286
- ```
287
-
288
- ---
289
-
290
- ## Now read your role-specific guide
291
-
292
- Path: `{PROJECT_ROOT}/.rdc/guides/<type>.md` (e.g., `frontend.md`, `backend.md`, `data.md`)
293
- Fallback: `{PROJECT_ROOT}/docs/guides/<type>.md` if `.rdc/` does not exist.
294
-
295
- The project overlay will specify the exact location if it differs from the convention above.
323
+
324
+ ### Supervisor workflow
325
+
326
+ - All zeros → clean run, proceed
327
+ - `flags_count > 0` or `deviations_count > 0` → pull full report:
328
+ ```sql
329
+ SELECT implementation_report FROM work_items WHERE id = '<id>';
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Now read your role-specific guide
335
+
336
+ Path: `{PROJECT_ROOT}/.rdc/guides/<type>.md` (e.g., `frontend.md`, `backend.md`, `data.md`)
337
+ Fallback: `{PROJECT_ROOT}/docs/guides/<type>.md` if `.rdc/` does not exist.
338
+
339
+ The project overlay will specify the exact location if it differs from the convention above.
@@ -1,9 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * PreToolUse hook — block focus-stealing foreground process launches.
3
+ * PreToolUse hook — blocks Playwright headed/UI-mode invocations only.
4
+ *
5
+ * NARROWED 2026-08-26 (epic 688ad6da WP-4, lifeai-env). This file used to
6
+ * ALSO block every raw foreground process launch (Start-Process without
7
+ * -WindowStyle Hidden, cmd /c start without /min, window-focus Win32 APIs,
8
+ * bare PowerShell .ps1 launches) -- that entire class is retired per Dave's
9
+ * direct operator instruction: "remove the PreToolUse foreground-window
10
+ * guard entirely... replace it with caller-logging for traceability."
11
+ * lifeai-env's lib/TermLaunch.psm1 (Invoke-TermLaunchHidden /
12
+ * Invoke-TermLaunchInteractive) is the replacement -- it logs every caller
13
+ * (script + line + argv) to C:/Dev/.logs BEFORE spawning, which is strictly
14
+ * more informative than a hard block that told a caller only "add
15
+ * -WindowStyle Hidden" and never recorded who asked.
16
+ *
17
+ * checkPlaywright is a SEPARATE, unrelated concern (Design Decision D3,
18
+ * .rdc/plans/terminal-launch-consolidation.md in lifeai-env): agent
19
+ * sessions must never pop an interactive Playwright UI. That has nothing to
20
+ * do with terminal/process launch primitives, so it was deliberately kept
21
+ * here rather than folded into caller-logging, which would have silently
22
+ * dropped a real safety property this narrowing was never asked to remove.
23
+ * The filename is legacy -- kept to avoid an unrelated hookify-manifest
24
+ * rewire for a rename that changes nothing about what the file does.
4
25
  */
5
- 'use strict';
6
-
7
26
  const hookLog = require('./hook-logger');
8
27
 
9
28
  function readStdin() {
@@ -35,35 +54,6 @@ function toolText(raw) {
35
54
  try { return JSON.stringify(raw.tool_input || raw); } catch { return ''; }
36
55
  }
37
56
 
38
- function hasHiddenIntent(command) {
39
- return /-WindowStyle\s+Hidden/i.test(command) ||
40
- /-WindowStyle\s+Minimized/i.test(command) ||
41
- /windowsHide\s*:\s*true/i.test(command) ||
42
- /CreateNoWindow\s*=\s*\$?true/i.test(command) ||
43
- /Start-Job\b/i.test(command) ||
44
- /--background\b/i.test(command) ||
45
- /\bHEADLESS\s*=\s*(1|true)\b/i.test(command) ||
46
- /\bCI\s*=\s*(1|true)\b/i.test(command);
47
- }
48
-
49
- function hasExplicitWindowOverride(command) {
50
- return /\bRDC_ALLOW_WINDOW_FOCUS\s*=\s*(1|true)\b/i.test(command) ||
51
- /\bRDC_INTERACTIVE_WINDOW\s*=\s*(1|true)\b/i.test(command);
52
- }
53
-
54
- function checkWindowFocusApi(command) {
55
- if (hasExplicitWindowOverride(command)) return;
56
- const focusApi = /\b(SetForegroundWindow|SwitchToThisWindow|AppActivate|SetWindowPos|ShowWindowAsync?|BringWindowToTop)\b/i;
57
- const broadWindowApi = /\b(EnumWindows|Get-Process\s+\|\s*Where-Object|GetWindow|FindWindow)\b/i;
58
- const windowMutation = /\b(minimi[sz]e|restore|foreground|focus|activate|collapse)\b/i;
59
- if (focusApi.test(command) || (broadWindowApi.test(command) && windowMutation.test(command))) {
60
- block(
61
- 'Window focus/restore/minimize/collapse operations are not allowed in agent-launched commands. Spawn helpers hidden/no-window instead; set RDC_ALLOW_WINDOW_FOCUS=1 only for an explicitly requested interactive recovery action.',
62
- { kind: 'window-focus-api' },
63
- );
64
- }
65
- }
66
-
67
57
  function checkPlaywright(command) {
68
58
  if (!/\b(playwright|@playwright\/test)\b/i.test(command)) return;
69
59
 
@@ -82,45 +72,13 @@ function checkPlaywright(command) {
82
72
  }
83
73
  }
84
74
 
85
- function checkPowerShell(command) {
86
- if (!/\bStart-Process\b/i.test(command)) return;
87
- if (hasHiddenIntent(command)) return;
88
- block(
89
- '`Start-Process` must include `-WindowStyle Hidden` or `-WindowStyle Minimized` for agent-launched node/cmd/ps1/test processes. Focus/restore/collapse APIs remain blocked unless explicitly requested.',
90
- { kind: 'start-process' },
91
- );
92
- }
93
-
94
- function checkCmdStart(command) {
95
- if (!/\bcmd(?:\.exe)?\s+\/c\s+start\b/i.test(command)) return;
96
- if (/\bcmd(?:\.exe)?\s+\/c\s+start\s+(""|''|`"")?\s*\/b\b/i.test(command)) return;
97
- block(
98
- '`cmd /c start` must use `/min` or `/b` for background tools. Focus/restore/collapse APIs remain blocked unless explicitly requested.',
99
- { kind: 'cmd-start' },
100
- );
101
- }
102
-
103
- function checkDirectShellLaunch(command) {
104
- if (hasHiddenIntent(command)) return;
105
- if (/\bpowershell(?:\.exe)?\b[^|\n]*(?:-File\s+[^|\n]*\.ps1|\.ps1\b)/i.test(command)) {
106
- block(
107
- 'PowerShell script launches from agent tooling must use `-WindowStyle Hidden -NonInteractive` or a hidden wrapper.',
108
- { kind: 'powershell-ps1' },
109
- );
110
- }
111
- }
112
-
113
75
  async function main() {
114
76
  let raw;
115
77
  try { raw = JSON.parse(await readStdin()); } catch { process.exit(0); }
116
78
  const command = toolText(raw);
117
79
  if (!command) pass({ reason: 'no-command' });
118
80
 
119
- checkWindowFocusApi(command);
120
81
  checkPlaywright(command);
121
- checkPowerShell(command);
122
- checkCmdStart(command);
123
- checkDirectShellLaunch(command);
124
82
 
125
83
  pass({ reason: 'clean' });
126
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.35.3",
3
+ "version": "0.35.5",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -44,7 +44,7 @@
44
44
  "validate": "node tests/validate-skills.js",
45
45
  "rdc-design": "node scripts/rdc-design-cli.mjs",
46
46
  "test:hooks": "node scripts/test-rdc-hooks.mjs",
47
- "test:truth-gate": "node tests/run-evidence-gate.test.mjs && node tests/work-item-exit-gate-l2.test.mjs && node tests/work-item-exit-gate-l3.test.mjs && node tests/require-work-item-on-commit.test.mjs && node tests/harness-gates.test.mjs",
47
+ "test:truth-gate": "node tests/run-evidence-gate.test.mjs && node tests/work-item-exit-gate-l2.test.mjs && node tests/work-item-exit-gate-l3.test.mjs && node tests/require-work-item-on-commit.test.mjs && node tests/harness-gates.test.mjs && node tests/foreground-process-gate.test.mjs",
48
48
  "test:acceptance": "node tests/acceptance.test.mjs && node tests/install-rdc-skills.test.mjs && node tests/help-surface.test.mjs && node tests/manifest-contract-fields.test.mjs && node tests/plugin-namespace-names.test.mjs && node tests/skill-test-matrix.test.mjs && node tests/completion-gate-supervisor-admission.test.mjs && node tests/curl-surface.test.mjs && node tests/clauth-plugin-postinstall.test.mjs",
49
49
  "acceptance": "node scripts/acceptance.mjs --changed",
50
50
  "test:mcp": "node tests/mcp.test.mjs",
@@ -508,8 +508,16 @@ function syncMarketplaceCheckout(mktDir) {
508
508
  const git = (...args) =>
509
509
  execSync(`git -C "${mktDir}" ${args.join(' ')}`, { encoding: 'utf8', stdio: 'pipe' }).trim();
510
510
  try {
511
- if (git('status', '--porcelain')) {
512
- warn(`marketplace clone has local changes at ${mktDir} — left untouched; it may serve stale commands`);
511
+ // PRESERVE-DIRTY means "don't discard a real local edit to a TRACKED file" —
512
+ // `--untracked-files=no` is deliberate. Plain `git status --porcelain` also
513
+ // reports untracked files (`?? some-cruft.txt`), which `git reset --hard`
514
+ // never touches and never conflicts with. Treating that as "dirty" made this
515
+ // sync silently refuse forever the moment ANY stray untracked file appeared
516
+ // in the clone — which is exactly how this checkout sat 39+ commits behind
517
+ // for over a week (2026-08-23), still warning "left untouched" on every run,
518
+ // while a plain `git status` on the same directory read completely clean.
519
+ if (git('status', '--porcelain', '--untracked-files=no')) {
520
+ warn(`marketplace clone has local changes to tracked files at ${mktDir} — left untouched; it may serve stale commands`);
513
521
  return;
514
522
  }
515
523
  const branch = git('rev-parse', '--abbrev-ref', 'HEAD') || 'master';
@@ -1347,7 +1355,7 @@ async function main() {
1347
1355
  // scripts/probe-installed-hooks.mjs verify the real install path instead of
1348
1356
  // re-implementing it — a probe that copies its own way proves nothing about what
1349
1357
  // ships. Without this guard, requiring the module would run a full install.
1350
- module.exports = { copyHookFiles, assertHooksLoadable, registerCodexTarget, RDC_ENV_HOOK_TIMEOUT_SEC };
1358
+ module.exports = { copyHookFiles, assertHooksLoadable, registerCodexTarget, syncMarketplaceCheckout, RDC_ENV_HOOK_TIMEOUT_SEC };
1351
1359
 
1352
1360
  if (require.main === module) {
1353
1361
  main().catch(e => { fail(e.message); process.exit(1); });