@lifeaitools/rdc-skills 0.35.4 → 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.
@@ -12,6 +12,7 @@ triggers:
12
12
  - monkey_dispatch payload with skill="brochurify"
13
13
  ---
14
14
 
15
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
15
16
  # rdc:brochurify Orchestrator
16
17
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
17
18
  > Report brochure job state, artifacts, and blockers directly; do not dump raw tool logs.
@@ -8,6 +8,7 @@ description: >-
8
8
  mechanical AST checks, not LLM judgment — see `scripts/clean-code-score.mjs`.
9
9
  ---
10
10
 
11
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
11
12
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
12
13
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
13
14
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -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. |
@@ -3,6 +3,7 @@ name: convert
3
3
  description: "Usage `rdc:convert <input> [--out <dir>] [--to markdown|word] [--images assets|base64|s3]` — Convert .docx/.pptx/.ppt → Markdown (Word OMML equations as KaTeX TeX, tables, images) or Markdown → Word via the build-corpus CLI from npm `regen.mde`. Portable: runs in any session that can reach npm — Claude Code CLI, Codex, and claude.ai can fetch + run it. Use whenever the user asks to convert an Office document, build a Markdown corpus from .docx/.pptx, turn Markdown into a .docx, or open the report in the regen-mde editor on Windows."
4
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  # rdc:convert — Office ↔ Markdown conversion (build-corpus) + regen-mde editor
7
8
 
8
9
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
@@ -14,6 +14,18 @@ description: "Usage `rdc:edit <site|brand|route|file>` — open the local websit
14
14
 
15
15
  # rdc:edit — Local Website Editor Launcher
16
16
 
17
+ **This skill is the designated handler `rdc-harness` dispatches to.**
18
+ `packages/work/src/editors.mjs`'s `BY_CLASS` table maps `site-html`/`site-ts`
19
+ product classes to editor id `'rdc:edit'` — when an agent calls
20
+ `node C:/Dev/rdc-harness/bin/rdc-harness.mjs edit <slug>` against a website
21
+ target, its receipt names `editorId: 'rdc:edit'` and an `editableBoundary`.
22
+ This skill IS that handler: resolve the same target, launch/reuse the editor
23
+ host, use the harness's `editableBoundary` as the save boundary if the call
24
+ originated from a harness `edit` receipt. Every other product class
25
+ (`app`/`package`/`mcp`/`model`/`artifact`) maps to editor id `'source'` — a
26
+ boundary-checked file save with no live/co-editing surface at all; that gap
27
+ is real and unbuilt, not something this skill covers.
28
+
17
29
  ## When to Use
18
30
  - The user wants to open a site, brand, route, or file in the local editor app
19
31
  - The user says "open this in the editor" or asks for the editor-host workflow
@@ -3,6 +3,7 @@ name: env
3
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
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
8
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
9
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -13,17 +14,39 @@ description: "Usage `rdc:env [status|install|repair|update]` — Manage the LIFE
13
14
  - After a reboot or GPU crash — verify everything came back up
14
15
  - Setting up a fresh box — install all tools and services
15
16
  - Something is broken — repair services, MCPs, CodeFlow
16
- - Routine update — pull latest env repo and run drift check
17
+ - Routine update — bring the harness current and run a drift check
17
18
  - "check the environment", "fix my setup", "install environment"
18
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
+
19
42
  ## Subcommands
20
43
 
21
44
  | Command | What it does |
22
45
  |---------|-------------|
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 |
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 |
25
48
  | `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 |
49
+ | `update` | Bring the harness current for its channel, re-run audit, report drift, refresh shims if new scripts added |
27
50
 
28
51
  ## Procedure
29
52
 
@@ -34,21 +57,42 @@ LIFEAI_ENV="${LIFEAI_ENV:-C:/Dev/lifeai-env}"
34
57
  ```
35
58
 
36
59
  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`
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`
39
66
 
40
67
  Read `$LIFEAI_ENV/manifest.json` — this is the harness inventory.
41
68
 
42
- ### Step 1: Environment repo state
69
+ ### Step 1: Harness state — channel first, then freshness
43
70
 
44
71
  ```bash
45
- git -C "$LIFEAI_ENV" fetch origin 2>/dev/null
46
- git -C "$LIFEAI_ENV" rev-list --count HEAD..origin/main
72
+ node "$LIFEAI_ENV/machines/env-boot.mjs" check
47
73
  ```
48
74
 
49
- 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
+ ```
50
92
 
51
- 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.
52
96
 
53
97
  ### Step 2: Tool versions (audit)
54
98
 
@@ -123,8 +167,8 @@ This is the same check the startup guard runs. Zero blockers = environment healt
123
167
 
124
168
  | Check | Status | Detail |
125
169
  |-------|--------|--------|
126
- | Env repo | ✅ | v0.2.0, 0 behind origin |
127
- | 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) |
128
172
  | Node | ✅ | v22.14.0 (min 22.0.0) |
129
173
  | pnpm | ✅ | 10.12.1 (min 10.0.0) |
130
174
  | clauth | ✅ | v1.30.2, unlocked |
@@ -12,6 +12,7 @@ triggers:
12
12
  - nightly cron at 3:00 AM PT
13
13
  ---
14
14
 
15
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
15
16
  # rdc:extract-verifier-rules
16
17
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
17
18
  > Return candidate rules, evidence, and PR status directly; do not dump raw tool logs.
@@ -3,6 +3,7 @@ name: fs-mcp
3
3
  description: "Usage `rdc:fs-mcp <task>` — Use the File System MCP bridge for live repo reads, safe writes, cloud-to-local ingest, and GitHub-branch imports into a dirty local monorepo. Use when Claude.ai, Cowork, or CLI agents need fs_read/fs_write/fs_import_git_files guidance."
4
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
8
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
9
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -3,6 +3,7 @@ name: help
3
3
  description: "Usage `rdc:help` — Show all MCP skills with usage, requirements, slash forms, and codeflow status. Reads `.claude-plugin/plugin.json` skills_meta (single source of truth). Call when unsure which skill to use or what args it takes."
4
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
8
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
9
 
@@ -20,6 +20,7 @@ required_validators:
20
20
  blocking: true
21
21
  ---
22
22
 
23
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
23
24
  # LIFEAI Brochure Authoring Contract
24
25
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
25
26
  > Return the authored JSX guidance or verification result directly; do not dump raw tool logs.
@@ -18,6 +18,7 @@ description: >
18
18
  Trigger when asked to create, register, or check whether a reference model exists.
19
19
  ---
20
20
 
21
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
21
22
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
22
23
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
23
24
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -6,6 +6,7 @@ description: >-
6
6
  and sit at the right size.
7
7
  ---
8
8
 
9
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
9
10
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
10
11
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
11
12
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -8,6 +8,7 @@ description: >-
8
8
  only; never rewrites code itself.
9
9
  ---
10
10
 
11
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
11
12
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
12
13
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
13
14
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -6,6 +6,7 @@ description: >-
6
6
  concrete before/after refactor plan. Produces a plan, does not apply it.
7
7
  ---
8
8
 
9
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
9
10
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
10
11
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
11
12
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -3,6 +3,7 @@ name: refactor
3
3
  description: "Usage `rdc:refactor <epic-id|topic> --takeover <reason>` — Governed consolidation and implementation of a cross-cutting refactor. Authorizes an explicit takeover, preserves evidence, re-parents relevant work through the consolidation RPC, isolates every writer, and uses the same review, validator, landing, and delivery gates as rdc:build."
4
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  > **OUTPUT CONTRACT:** `guides/output-contract.md`
7
8
 
8
9
  # rdc:refactor
@@ -3,6 +3,7 @@ name: regen-media
3
3
  description: "Usage `rdc:regen-media <generate|edit|upscale|upload> <brief-or-path>` - Primary image-generation and Regen Media asset workflow. Use for image generation, image editing/upscaling, GPT Image/gpt-image-2 requests, Codex built-in image_gen, and uploading finished images to regen-media/R2. The default path is keyless local Codex gpt-image-2 via the built-in image_gen tool; server-side regen-media MCP/API generation is fallback only."
4
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
8
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
9
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -8,6 +8,7 @@ description: >-
8
8
  `scripts/solid-score.mjs` for the mechanism.
9
9
  ---
10
10
 
11
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
11
12
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
12
13
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
13
14
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -3,6 +3,7 @@ name: terminal-config
3
3
  description: "Usage `rdc:terminal-config <task>` — read and safely modify Windows Terminal settings, shell profiles, and agent startup sequencing without relying on machine-specific paths."
4
4
  ---
5
5
 
6
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
6
7
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
7
8
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
8
9
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -8,6 +8,7 @@ description: >-
8
8
  covers whether a surface's behavior is actually provable, and how.
9
9
  ---
10
10
 
11
+ > If dispatching subagents or running as a subagent: read `{PROJECT_ROOT}/.rdc/guides/agent-bootstrap.md` first (fallback: `.rdc/guides/agent-bootstrap.md`) — this is also where the global rdc-harness-use policy for create/open/build/deploy work lives.
11
12
  > **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
12
13
  > Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
13
14
  > One checklist upfront, updated in place, shown again at end with a 1-line verdict.
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * foreground-process-gate.js — narrowed to Playwright headed/UI-mode only
4
+ * (epic 688ad6da WP-4, lifeai-env). Four window-focus/process-launch checks
5
+ * (checkWindowFocusApi, checkPowerShell, checkCmdStart, checkDirectShellLaunch)
6
+ * were removed; the replacement is lifeai-env's lib/TermLaunch.psm1 caller-
7
+ * logging, which lives in a different repo and is not this file's job to
8
+ * re-implement or re-check.
9
+ *
10
+ * This file's job is now to prove two things stay true going forward:
11
+ * 1. The four retired checks no longer block anything -- a real regression
12
+ * here would silently reintroduce ceremony an operator explicitly
13
+ * retired, with no other test anywhere positioned to catch it.
14
+ * 2. checkPlaywright survives untouched (Design Decision D3) -- this is a
15
+ * SEPARATE safety property, not part of the terminal-launch
16
+ * consolidation, and narrowing the file must never have narrowed this.
17
+ *
18
+ * Run: node tests/foreground-process-gate.test.mjs
19
+ */
20
+ import { dirname, join, resolve } from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+ import { spawnSync } from 'node:child_process';
23
+
24
+ const __dirname = dirname(fileURLToPath(import.meta.url));
25
+ const REPO_ROOT = resolve(__dirname, '..');
26
+ const HOOK = join(REPO_ROOT, 'hooks', 'foreground-process-gate.js');
27
+
28
+ const failures = [];
29
+ function assert(name, condition, detail = '') {
30
+ if (!condition) failures.push(`${name}${detail ? `: ${detail}` : ''}`);
31
+ else process.stdout.write(` ok ${name}\n`);
32
+ }
33
+
34
+ function runGate(command) {
35
+ const res = spawnSync(process.execPath, [HOOK], {
36
+ input: JSON.stringify({ tool_name: 'Bash', tool_input: { command } }),
37
+ encoding: 'utf8',
38
+ });
39
+ const blocked = res.status === 1;
40
+ return { blocked, stdout: res.stdout, status: res.status };
41
+ }
42
+
43
+ // ===========================================================================
44
+ // 1. The four retired checks no longer block anything.
45
+ // ===========================================================================
46
+
47
+ {
48
+ const r = runGate('Start-Process -FilePath node.exe -ArgumentList "server.js"');
49
+ assert('Start-Process with no -WindowStyle Hidden no longer blocks (checkPowerShell retired)',
50
+ r.blocked === false, `status=${r.status} stdout=${r.stdout}`);
51
+ }
52
+
53
+ {
54
+ const r = runGate('cmd /c start node.exe server.js');
55
+ assert('cmd /c start without /min no longer blocks (checkCmdStart retired)',
56
+ r.blocked === false, `status=${r.status} stdout=${r.stdout}`);
57
+ }
58
+
59
+ {
60
+ const r = runGate('powershell.exe -File C:\\Dev\\some-script.ps1');
61
+ assert('bare PowerShell .ps1 launch no longer blocks (checkDirectShellLaunch retired)',
62
+ r.blocked === false, `status=${r.status} stdout=${r.stdout}`);
63
+ }
64
+
65
+ {
66
+ const r = runGate('[Win32]::SetForegroundWindow($handle)');
67
+ assert('a window-focus Win32 API call no longer blocks (checkWindowFocusApi retired)',
68
+ r.blocked === false, `status=${r.status} stdout=${r.stdout}`);
69
+ }
70
+
71
+ // ===========================================================================
72
+ // 2. checkPlaywright survives, untouched -- a separate safety property.
73
+ // ===========================================================================
74
+
75
+ {
76
+ const r = runGate('npx playwright test --headed');
77
+ assert('Playwright --headed still blocks',
78
+ r.blocked === true, `status=${r.status} stdout=${r.stdout}`);
79
+ assert('Playwright --headed block message names the right reason',
80
+ /must run headless/.test(r.stdout), r.stdout);
81
+ }
82
+
83
+ {
84
+ const r = runGate('PWDEBUG=1 npx playwright test');
85
+ assert('Playwright PWDEBUG=1 still blocks',
86
+ r.blocked === true, `status=${r.status} stdout=${r.stdout}`);
87
+ }
88
+
89
+ {
90
+ const r = runGate('npx playwright show-report');
91
+ assert('Playwright show-report still blocks',
92
+ r.blocked === true, `status=${r.status} stdout=${r.stdout}`);
93
+ assert('Playwright show-report block message names the right reason',
94
+ /launches foreground UI/.test(r.stdout), r.stdout);
95
+ }
96
+
97
+ {
98
+ const r = runGate('npx playwright test --reporter=list');
99
+ assert('an ordinary headless Playwright run is NOT blocked',
100
+ r.blocked === false, `status=${r.status} stdout=${r.stdout}`);
101
+ }
102
+
103
+ {
104
+ const r = runGate('git status');
105
+ assert('an unrelated ordinary command passes clean', r.blocked === false, `status=${r.status} stdout=${r.stdout}`);
106
+ }
107
+
108
+ // ===========================================================================
109
+ if (failures.length > 0) {
110
+ console.error('\nforeground-process-gate tests — FAIL\n');
111
+ for (const f of failures) console.error(` - ${f}`);
112
+ process.exit(1);
113
+ }
114
+ console.log('\nforeground-process-gate tests — PASS');
@@ -146,34 +146,16 @@ const WI = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee';
146
146
  }
147
147
 
148
148
  // ===========================================================================
149
- // 2. foreground-process-gate.js
149
+ // 2. foreground-process-gate.js — moved to its own file, tests/foreground-process-gate.test.mjs
150
+ //
151
+ // Narrowed 2026-08-26 (epic 688ad6da WP-4, lifeai-env): the window-focus/
152
+ // process-launch checks this section used to assert (SetForegroundWindow
153
+ // blocking, hidden/minimized allowances) were retired — that whole class is
154
+ // now caller-logged by lifeai-env's lib/TermLaunch.psm1, not hard-blocked
155
+ // here. The dedicated test file covers what remains (checkPlaywright) plus
156
+ // asserts the four retired checks stay retired, so removing this embedded
157
+ // section is not a coverage loss — see that file instead.
150
158
  // ===========================================================================
151
- {
152
- const focusPayload = {
153
- tool_input: {
154
- command: "powershell -NoProfile -Command \"Add-Type '[DllImport(\\\"user32.dll\\\")] public static extern bool SetForegroundWindow(System.IntPtr hWnd);'\"",
155
- },
156
- };
157
- const r = runHook('foreground-process-gate.js', focusPayload, {});
158
- assert('FPG blocks SetForegroundWindow focus API', r.status === 1, `status=${r.status} ${r.stdout}${r.stderr}`);
159
- assert('FPG block mentions window focus operations', /Window focus\/restore\/minimize\/collapse/.test(r.stdout + r.stderr));
160
-
161
- const hiddenPayload = {
162
- tool_input: {
163
- command: 'powershell.exe -NoProfile -NonInteractive -WindowStyle Hidden -File ".\\\\scripts\\\\helper.ps1"',
164
- },
165
- };
166
- const h = runHook('foreground-process-gate.js', hiddenPayload, {});
167
- assert('FPG allows hidden PowerShell helper', h.status === 0, `status=${h.status} ${h.stdout}${h.stderr}`);
168
-
169
- const minimizedPayload = {
170
- tool_input: {
171
- command: 'Start-Process powershell.exe -WindowStyle Minimized -ArgumentList "-NoProfile"',
172
- },
173
- };
174
- const m = runHook('foreground-process-gate.js', minimizedPayload, {});
175
- assert('FPG allows minimized Start-Process without focus APIs', m.status === 0, `status=${m.status} ${m.stdout}${m.stderr}`);
176
- }
177
159
 
178
160
  // ===========================================================================
179
161
  // 3. post-tool-batch-gate.js