lasso-mcp 1.19.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -2
- package/README.md +3 -2
- package/dist/doctor/doctor.d.ts +1 -1
- package/dist/doctor/doctor.js +1 -1
- package/dist/index.js +1 -1
- package/dist/launcher/chrome-ledger.d.ts +1 -1
- package/dist/launcher/chrome-ledger.d.ts.map +1 -1
- package/dist/launcher/chrome-ledger.js +1 -1
- package/dist/launcher/chrome-ledger.js.map +1 -1
- package/dist/render/render-chrome.d.ts.map +1 -1
- package/dist/render/render-chrome.js +66 -13
- package/dist/render/render-chrome.js.map +1 -1
- package/dist/render/render-doctor.d.ts +23 -0
- package/dist/render/render-doctor.d.ts.map +1 -1
- package/dist/render/render-doctor.js +50 -2
- package/dist/render/render-doctor.js.map +1 -1
- package/dist/render/render-flags.d.ts +26 -1
- package/dist/render/render-flags.d.ts.map +1 -1
- package/dist/render/render-flags.js +19 -5
- package/dist/render/render-flags.js.map +1 -1
- package/dist/render/render-guardian.d.ts +1 -1
- package/dist/render/render-guardian.d.ts.map +1 -1
- package/dist/render/render-guardian.js +1 -1
- package/dist/render/render-guardian.js.map +1 -1
- package/doc//346/217/220/346/241/210-render-stop/347/253/257/345/217/243/344/275/234/347/224/250/345/237/237/345/214/226.md +236 -0
- package/doc//346/270/262/346/237/223/346/241/243-/345/271/266/350/241/214/351/252/214/346/224/266/351/232/224/347/246/273/351/205/215/346/226/271.md +129 -0
- package/doc//346/270/262/346/237/223/346/241/243/350/256/276/350/256/241/345/206/263/350/256/256.md +4 -0
- package/package.json +1 -1
- package/src/doctor/doctor.ts +1 -1
- package/src/index.ts +1 -1
- package/src/launcher/chrome-ledger.ts +1 -1
- package/src/render/render-chrome.ts +70 -13
- package/src/render/render-doctor.ts +70 -2
- package/src/render/render-flags.ts +40 -5
- package/src/render/render-guardian.ts +1 -1
package/README.en.md
CHANGED
|
@@ -206,7 +206,7 @@ Goes to the Internet Archive (Wayback Machine) to find the last archived copy of
|
|
|
206
206
|
|
|
207
207
|
## Install
|
|
208
208
|
|
|
209
|
-
**Current version v1.
|
|
209
|
+
**Current version v1.20.0** (changelog in the collapsed block at the end of this section).
|
|
210
210
|
|
|
211
211
|
Prerequisites: Node.js ≥ 20 + Claude Code (or any MCP-capable client).
|
|
212
212
|
|
|
@@ -218,11 +218,12 @@ Restart Claude Code → `/mcp` → `lasso ✓ Connected`. **That's the one line
|
|
|
218
218
|
|
|
219
219
|
**macOS users wanting desktop control**: run `lasso doctor` once and tick `lasso-rust-helper` for "Accessibility" and "Screen Recording" as prompted — `doctor` walks you through it step by step.
|
|
220
220
|
|
|
221
|
-
**Deterministic render browser for other AI tools (render tier)**: if you use rendering tools like media-gen-mcp that demand "same input → same pixels", one line after installing lasso — `npx -y lasso-mcp render-chrome --ensure` — brings up a deterministic headless Chrome on port 9224 (frozen flag snapshot + isolated temp profile) and prints the `wsEndpoint` for the consumer to attach to; **the browser keeps running even if the consumer process is SIGKILLed** (lifecycle owned by lasso), and it is idle-reaped after 10 minutes with its profile cleaned up (tunable via `LASSO_RENDER_IDLE_MS`). Companions: `render-chrome --status` introspection / `--stop` / `render-chrome doctor [--clean]` orphan & stale-profile sweep (dry-run by default).
|
|
221
|
+
**Deterministic render browser for other AI tools (render tier)**: if you use rendering tools like media-gen-mcp that demand "same input → same pixels", one line after installing lasso — `npx -y lasso-mcp render-chrome --ensure` — brings up a deterministic headless Chrome on port 9224 (frozen flag snapshot + isolated temp profile) and prints the `wsEndpoint` for the consumer to attach to; **the browser keeps running even if the consumer process is SIGKILLed** (lifecycle owned by lasso), and it is idle-reaped after 10 minutes with its profile cleaned up (tunable via `LASSO_RENDER_IDLE_MS`). Companions: `render-chrome --status` introspection / `--stop` (honors `LASSO_RENDER_PORT`: an explicit valid port stops only that port, unset = all render records, an invalid value exits 1; global teardown remains `chrome-stop --modes render`) / `render-chrome doctor [--clean]` orphan & stale-profile sweep (dry-run by default; honors `LASSO_RENDER_PORT` like `--stop`: an explicit valid port scopes the orphan scan, unset = full scan, an invalid value exits 1; in-use instances with a touch heartbeat within 10 minutes are exempt from orphan judgment). **Multiple parallel acceptance agents on one machine** (whose independent teardown commands would kill each other's instances) need a three-env namespace: `LASSO_RENDER_PORT` + `LASSO_LAUNCHED_CHROMES_PATH` + `LASSO_RENDER_GUARDIAN_PID_PATH` — with all three set, parallel agents are mutually invisible; see the full recipe and teardown discipline in [doc/渲染档-并行验收隔离配方.md](doc/渲染档-并行验收隔离配方.md) (Chinese).
|
|
222
222
|
|
|
223
223
|
<details>
|
|
224
224
|
<summary>📋 Changelog (v1.8 → v1.18.6 — click to see what each version changed)</summary>
|
|
225
225
|
|
|
226
|
+
- **v1.20.0**: render-tier parallel-safety batch (stop/doctor port scoping) — ① 🔴 **behavior change**: `render-chrome --stop` previously ignored `LASSO_RENDER_PORT` and killed **every render tier on the machine** (the #1 entry point for parallel acceptance agents killing each other's instances); now, **an explicitly set `LASSO_RENDER_PORT` stops only that port** (symmetric with `--ensure`/`--status`), unset = collect-all unchanged, an invalid value exits 1 as a usage error. Old scripts that set the port yet expect a full sweep should switch to `chrome-stop --modes render`; the `--stop` output shape is unchanged (idempotent `{"stopped":[...]}`). ② `render-chrome doctor` orphan judgment is scoped the same way with double exemption: an explicit port scans only that port, and other namespaces' in-use instances are no longer misjudged as orphans (out-of-scope port + touch heartbeat within 10 minutes, both exempt — `--clean` no longer kills in-use instances). ③ the **multi-agent parallel acceptance** three-env recipe (`LASSO_RENDER_PORT` + `LASSO_LAUNCHED_CHROMES_PATH` + `LASSO_RENDER_GUARDIAN_PID_PATH`) verified on a live machine: two terminals tearing down concurrently, mutually invisible, zero cross-kills. Consumers like media-gen-mcp only call `--ensure` and are unaffected (verified at source level).
|
|
226
227
|
- **v1.19.0**: deterministic render tier + performance/accuracy batch — ① new `lasso-mcp render-chrome`: a **deterministic rendering browser** for other AI tools (e.g. media-gen-mcp) — one `--ensure` line launches a headless Chrome with a frozen flag snapshot (the browser survives consumer kills; auto-reclaimed after 10 min idle with profile cleanup; see README render section); ② perf: handshake budget on engine cold start (fast-fail instead of 60s hangs, tunable via `LASSO_MCP_HANDSHAKE_TIMEOUT_MS`), first-install npx tax removed, 2FA probe made idempotent, fast-path for truncated large evaluations; ③ accuracy: SERP layout-change detection chain live (selector rot auto-detected with baseline recording). Tool interfaces unchanged (purely additive subcommand and flags).
|
|
227
228
|
- **v1.18.8**: doctor & CLI polish — ① `doctor` no longer reports "unhealthy" due to **ad-hoc signing** (previously a false `ready:false`: ad-hoc is Apple's free legitimate scheme, fully functional — the only cost is re-granting system permissions after rebuilds; a proper Developer ID signature still passes); ② `lasso launch-chrome --help` fixed (previously it actually launched a Chrome; now prints usage); ③ architecture doc fully aligned + 20 legacy cleanups (tests up to 2471 / invariants 84).
|
|
228
229
|
- **v1.18.7**: architecture re-review landed (five-dimension checklist with fix loops) — ① browse-family interface honesty: `wait_until` / `timeout_ms` / `screenshot.element` / `stealth_profile` — four **never-effective dead parameters** — removed from tool descriptions and schema (previously silently ignored; docs no longer promise nonexistent behavior; non-breaking — unknown keys are silently stripped); ② four false statements about the CI cargo face corrected in docs; ③ internals: doctor decoupled from channels, firstText single definition, test-only pass-through methods converged (2 new architecture invariants, INV 82→84; tests 2446→2455).
|
package/README.md
CHANGED
|
@@ -215,7 +215,7 @@ macOS 上能控 Finder / Mail / Safari / Notes / 系统设置等任何原生 app
|
|
|
215
215
|
|
|
216
216
|
## 安装
|
|
217
217
|
|
|
218
|
-
**当前版本 v1.
|
|
218
|
+
**当前版本 v1.20.0**(更新日志见本节末尾折叠块)。
|
|
219
219
|
|
|
220
220
|
前提:Node.js ≥ 20 + Claude Code(或任何支持 MCP 的客户端)。
|
|
221
221
|
|
|
@@ -227,11 +227,12 @@ claude mcp add lasso -- npx -y lasso-mcp
|
|
|
227
227
|
|
|
228
228
|
**macOS 想控桌面**:跑一次 `lasso doctor`,按提示给 `lasso-rust-helper` 勾上「辅助功能」和「屏幕录制」权限即可,doctor 会一步步引导。
|
|
229
229
|
|
|
230
|
-
**给其它 AI 工具当确定性渲染浏览器(渲染档)**:如果你在用 media-gen-mcp 这类要求「同一输入必须产出同一像素」的渲染工具,装好 lasso 后只需一行 `npx -y lasso-mcp render-chrome --ensure`——它会在 9224 端口拉起一个确定性 headless Chrome(冻结旗标快照 + 独立临时 profile),输出消费方直连用的 `wsEndpoint`;**消费方进程被强杀浏览器也照常存活**(生命周期归属 lasso),空闲 10 分钟自动回收并连带清理 profile(`LASSO_RENDER_IDLE_MS` 可调)。配套:`render-chrome --status` 自省 / `--stop`
|
|
230
|
+
**给其它 AI 工具当确定性渲染浏览器(渲染档)**:如果你在用 media-gen-mcp 这类要求「同一输入必须产出同一像素」的渲染工具,装好 lasso 后只需一行 `npx -y lasso-mcp render-chrome --ensure`——它会在 9224 端口拉起一个确定性 headless Chrome(冻结旗标快照 + 独立临时 profile),输出消费方直连用的 `wsEndpoint`;**消费方进程被强杀浏览器也照常存活**(生命周期归属 lasso),空闲 10 分钟自动回收并连带清理 profile(`LASSO_RENDER_IDLE_MS` 可调)。配套:`render-chrome --status` 自省 / `--stop` 收尾(认 `LASSO_RENDER_PORT`:显式设 port 只收该 port,未设=全部 render 记录,非法值 exit 1;全局收口仍可用 `chrome-stop --modes render`)/ `render-chrome doctor [--clean]` 孤儿与陈年 profile 清理(默认只报告;认 `LASSO_RENDER_PORT`,同 `--stop`:显式设 port 只判该 port,未设=全扫,非法值 exit 1;touch 心跳 10 分钟内的在用实例豁免不判孤儿)。**同机多 agent 并行验收**(多个 agent 各自清场会互杀对方实例)需配三 env 契命名空间隔离:`LASSO_RENDER_PORT` + `LASSO_LAUNCHED_CHROMES_PATH` + `LASSO_RENDER_GUARDIAN_PID_PATH`,配齐后并行互不可见,配方与清场纪律见 [doc/渲染档-并行验收隔离配方.md](doc/渲染档-并行验收隔离配方.md)。
|
|
231
231
|
|
|
232
232
|
<details>
|
|
233
233
|
<summary>📋 更新日志(v1.8 → v1.18.6,点开看每版改了什么)</summary>
|
|
234
234
|
|
|
235
|
+
- **v1.20.0**:渲染档并行安全批(stop/doctor 端口作用域化)——① 🔴 **行为变更**:`render-chrome --stop` 此前无视 `LASSO_RENDER_PORT`、会收掉**全机**渲染档(同机多 agent 并行验收时互杀对方实例的第一入口);现在**显式设了 `LASSO_RENDER_PORT` 只收该 port**(与 `--ensure`/`--status` 对称),未设=维持全收不变,非法值 exit 1 报用法错。设了 port 却想全收的旧脚本请改用 `chrome-stop --modes render`;`--stop` 输出形状不变(幂等 `{"stopped":[...]}`)。② `render-chrome doctor` 孤儿判定同样作用域化 + 双豁免:显式 port 只判该 port,他人命名空间实例不再被误判孤儿(范围外 port + touch 心跳 10 分钟内新鲜双重豁免,`--clean` 不再误杀在用实例)。③ 配套**同机多 agent 并行验收**三 env 隔离配方(`LASSO_RENDER_PORT` + `LASSO_LAUNCHED_CHROMES_PATH` + `LASSO_RENDER_GUARDIAN_PID_PATH`)真机验证:双终端并发各自清场,并行互不可见零互杀。media-gen-mcp 等消费方只调 `--ensure` 不受影响(已源码级实证)。
|
|
235
236
|
- **v1.19.0**:确定性渲染档 + 性能/准确率批——① 新增 `lasso-mcp render-chrome`:给其它 AI 工具(如 media-gen-mcp)当**确定性渲染浏览器**——`--ensure` 一行拉起带冻结旗标快照的 headless Chrome(消费方进程被强杀浏览器照常存活,空闲 10 分钟自动回收并清理 profile),详见 README 渲染档节;② 性能:浏览器引擎冷启动握手加预算(卡死快速失败不再挂 60 秒,`LASSO_MCP_HANDSHAKE_TIMEOUT_MS` 可调)、首装 npx 下载税消除、2FA 探测幂等化、大求值截断快路;③ 准确率:搜索页改版检测链上线(选择器失效自动发现并记录基线)。工具接口零变化(纯新增子命令与旗标)。
|
|
236
237
|
- **v1.18.8**:doctor 与 CLI 打磨——① `doctor` 不再因 **ad-hoc 签名**报「不健康」(此前 `ready:false` 误报:ad-hoc 是官方免费合法方案,功能正常,唯一代价是重编译后需重新系统授权;Developer ID 正签仍 pass)② `lasso launch-chrome --help` 修复(此前会误启动一个 Chrome,现在正确打印用法说明)③ 架构文档全量对齐 + 20 项历史遗留清理(测试增至 2471 / 不变量 84)。
|
|
237
238
|
- **v1.18.7**:架构重审落地(03 清单五维+循环修复)——① browse 族接口面诚实化:`wait_until` / `timeout_ms` / `screenshot.element` / `stealth_profile` 四个**从未生效的死参数**从工具描述与 schema 移除(此前传入会被静默忽略,现在文档不再承诺不存在的行为;非破坏——传了也会被静默剥离);② 「隐藏的 Chrome」文档中关于 CI 的四处失实描述改真;③ 内部:doctor 与 channels 解耦、firstText 单一定义、测试穿堂方法收敛(新增 2 条架构不变量,INV 总数 82→84;测试 2446→2455)。
|
package/dist/doctor/doctor.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type RustBridgeLike } from "../desktop/desktop-doctor-checks.js";
|
|
2
2
|
import { type StealthProfileName } from "../browse/stealth-profiles.js";
|
|
3
3
|
import type { McpClient } from "../subprocess/McpClient.js";
|
|
4
|
-
export declare const LASSO_VERSION = "1.
|
|
4
|
+
export declare const LASSO_VERSION = "1.20.0";
|
|
5
5
|
export interface DoctorCheck {
|
|
6
6
|
name: string;
|
|
7
7
|
status: "pass" | "fail" | "warn";
|
package/dist/doctor/doctor.js
CHANGED
|
@@ -137,7 +137,7 @@ import { probeCreepjs } from "./creepjs-probe.js";
|
|
|
137
137
|
import { defaultHeadlessProfileForHost } from "../browse/stealth-profiles.js";
|
|
138
138
|
const execFileP = promisify(execFile);
|
|
139
139
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
140
|
-
export const LASSO_VERSION = "1.
|
|
140
|
+
export const LASSO_VERSION = "1.20.0";
|
|
141
141
|
// ============================================================
|
|
142
142
|
// runDoctor
|
|
143
143
|
// ============================================================
|
package/dist/index.js
CHANGED
|
@@ -212,7 +212,7 @@ const fsReadFile = fsPromises.readFile;
|
|
|
212
212
|
* INV-76(v1.7 INV-1..75 零回归)→ 1.8.0
|
|
213
213
|
* 与 package.json version + doctor.ts LASSO_VERSION 三处对齐(grep 验;INV-63 守)。
|
|
214
214
|
*/
|
|
215
|
-
const LASSO_SERVER_VERSION = "1.
|
|
215
|
+
const LASSO_SERVER_VERSION = "1.20.0";
|
|
216
216
|
/**
|
|
217
217
|
* cloud 浏览器双重解锁判定(parse5 §3.4 + INV-25)。
|
|
218
218
|
*
|
|
@@ -25,7 +25,7 @@ export interface LaunchedChromeRecord {
|
|
|
25
25
|
*/
|
|
26
26
|
idleMs?: number;
|
|
27
27
|
}
|
|
28
|
-
/** 台账路径(env LASSO_LAUNCHED_CHROMES_PATH
|
|
28
|
+
/** 台账路径(env LASSO_LAUNCHED_CHROMES_PATH 可覆盖;测试隔离 + 同机多 agent 并行验收隔离用,配方见 doc/渲染档-并行验收隔离配方.md)。 */
|
|
29
29
|
export declare function launchedChromesPath(): string;
|
|
30
30
|
/** launcher 侧结构化日志(INV-64:不 import ../util/logger;由调用方注入)。 */
|
|
31
31
|
export type LedgerLogFn = (payload: Record<string, unknown>) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome-ledger.d.ts","sourceRoot":"","sources":["../../src/launcher/chrome-ledger.ts"],"names":[],"mappings":"AA2BA,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,EAAE,OAAO,GAAG,eAAe,CAAC;IAClC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC7C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,
|
|
1
|
+
{"version":3,"file":"chrome-ledger.d.ts","sourceRoot":"","sources":["../../src/launcher/chrome-ledger.ts"],"names":[],"mappings":"AA2BA,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,EAAE,OAAO,GAAG,eAAe,CAAC;IAClC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC7C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kGAAkG;AAClG,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,8DAA8D;AAC9D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAYrE;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,EAAE,CAyCvD;AAKD;;;GAGG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,oBAAoB,EACzB,KAAK,GAAE,WAAwB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wDAAwD;AACxD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,GAAE,WAAwB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,qCAAqC;AACrC,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,GAAE,WAAwB,GAC9B,IAAI,CAWN"}
|
|
@@ -21,7 +21,7 @@ import { promises as fsp, readFileSync, writeFileSync, renameSync, mkdirSync } f
|
|
|
21
21
|
import * as path from "node:path";
|
|
22
22
|
import os from "node:os";
|
|
23
23
|
import process from "node:process";
|
|
24
|
-
/** 台账路径(env LASSO_LAUNCHED_CHROMES_PATH
|
|
24
|
+
/** 台账路径(env LASSO_LAUNCHED_CHROMES_PATH 可覆盖;测试隔离 + 同机多 agent 并行验收隔离用,配方见 doc/渲染档-并行验收隔离配方.md)。 */
|
|
25
25
|
export function launchedChromesPath() {
|
|
26
26
|
const override = process.env.LASSO_LAUNCHED_CHROMES_PATH;
|
|
27
27
|
if (override && override.trim().length > 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome-ledger.js","sourceRoot":"","sources":["../../src/launcher/chrome-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9F,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,OAAO,MAAM,cAAc,CAAC;AAiCnC,
|
|
1
|
+
{"version":3,"file":"chrome-ledger.js","sourceRoot":"","sources":["../../src/launcher/chrome-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-chrome.d.ts","sourceRoot":"","sources":["../../src/render/render-chrome.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render-chrome.d.ts","sourceRoot":"","sources":["../../src/render/render-chrome.ts"],"names":[],"mappings":"AA0BA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAI9B,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,sBAAsB;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAoBtE;AAsCD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AA2DD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,GAAE,MAAM,EAA0B,EACtC,IAAI,GAAE;IACJ,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;CACjE,GACL,OAAO,CAAC,IAAI,CAAC,CAiGf"}
|
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
* 强依赖——stdout 纯净性是硬约束,一切日志/警告走 stderr)
|
|
8
8
|
* - `--status`:自省(恒 exit 0);`renderSessions` = 当前打开 page/target 数
|
|
9
9
|
* (CDP /json/list 实时计数——台账契约禁新字段下的诚实降级,设计决议 3.7)
|
|
10
|
-
* - `--stop`:幂等(不在运行也 exit 0),输出 {"stopped":[{port,pid,action}]}
|
|
11
|
-
*
|
|
10
|
+
* - `--stop`:幂等(不在运行也 exit 0),输出 {"stopped":[{port,pid,action}]};
|
|
11
|
+
* 认 `LASSO_RENDER_PORT`(提案 §6.1:显式合法 → 只收该 port;未设 → 全部 render
|
|
12
|
+
* 记录;显式非法 → exit 1 用法错)
|
|
13
|
+
* - `doctor [--clean]`:孤儿检测 + 陈年 profile 清理(默认 dry-run);孤儿判定认
|
|
14
|
+
* `LASSO_RENDER_PORT`(提案 §6.2:显式合法=只判该 port;未设=全扫;非法=exit 1)
|
|
12
15
|
*
|
|
13
16
|
* 退出码全集(设计决议 3.6):0 成功;2 Chrome 二进制不存在;3 端口被非渲染档
|
|
14
17
|
* 占用 / 既有渲染档不健康且重生失败;4 拉起超时(>20s);5 内部错误;1 用法错。
|
|
@@ -23,7 +26,7 @@ import { stopLaunchedChromes } from "../launcher/chrome-stop.js";
|
|
|
23
26
|
import { chromeTouchPath, chromeTouchMtimeSync } from "../launcher/chrome-touch.js";
|
|
24
27
|
import { launchRenderChrome, probeRenderHealth, } from "./render-launcher.js";
|
|
25
28
|
import { renderDoctor } from "./render-doctor.js";
|
|
26
|
-
import { renderCdpPort, renderIdleDefaultMs } from "./render-flags.js";
|
|
29
|
+
import { renderCdpPort, renderCdpPortScope, renderIdleDefaultMs } from "./render-flags.js";
|
|
27
30
|
/** argv 解析(单独导出便于单测)。--ensure/--status/--stop 为 flag 形态;doctor 子命令。 */
|
|
28
31
|
export function parseRenderChromeArgs(argv) {
|
|
29
32
|
const out = { command: "ensure" };
|
|
@@ -60,14 +63,24 @@ Usage:
|
|
|
60
63
|
detached, port 9224). Single-line JSON on
|
|
61
64
|
stdout; logs go to stderr
|
|
62
65
|
lasso-mcp render-chrome --status Introspection (always exit 0)
|
|
63
|
-
lasso-mcp render-chrome --stop Stop render-mode Chrome(s), idempotent
|
|
66
|
+
lasso-mcp render-chrome --stop Stop render-mode Chrome(s), idempotent.
|
|
67
|
+
Honors LASSO_RENDER_PORT: explicit valid
|
|
68
|
+
port stops only that port (symmetric with
|
|
69
|
+
--ensure/--status); unset = all render
|
|
70
|
+
records (design 3.7); invalid value =
|
|
71
|
+
exit 1 usage error
|
|
64
72
|
lasso-mcp render-chrome doctor [--clean] Orphan render-Chrome scan + stale profile
|
|
65
|
-
sweep (dry-run by default; --clean executes)
|
|
73
|
+
sweep (dry-run by default; --clean executes).
|
|
74
|
+
Honors LASSO_RENDER_PORT same as --stop:
|
|
75
|
+
explicit valid port scopes the orphan scan,
|
|
76
|
+
unset = full scan, invalid = exit 1
|
|
66
77
|
|
|
67
78
|
Exit codes (--ensure): 0 ok; 2 chrome binary missing; 3 port occupied by non-render
|
|
68
79
|
process / unhealthy render chrome and respawn failed; 4 launch timeout (>20s);
|
|
69
|
-
5 internal error. Env: LASSO_RENDER_PORT (default 9224
|
|
70
|
-
|
|
80
|
+
5 internal error. Env: LASSO_RENDER_PORT (default 9224; --stop honors it — explicit
|
|
81
|
+
valid port scopes the stop, unset = all render records, invalid = exit 1),
|
|
82
|
+
LASSO_RENDER_IDLE_MS (default 600000; <=0 disables auto-reap),
|
|
83
|
+
LASSO_RENDER_GUARDIAN_PID_PATH.`;
|
|
71
84
|
/** stderr 单行 JSON 日志(stdout 纯净性——一切日志走 stderr)。 */
|
|
72
85
|
function cliLog(payload) {
|
|
73
86
|
process.stderr.write(`${JSON.stringify({ ts: Date.now(), ...payload })}\n`);
|
|
@@ -106,10 +119,16 @@ async function runStatus(writeStdout, fetchFn) {
|
|
|
106
119
|
};
|
|
107
120
|
writeStdout(`${JSON.stringify(out)}\n`);
|
|
108
121
|
}
|
|
109
|
-
async function runStop(writeStdout) {
|
|
110
|
-
// 实现在 stopLaunchedChromes({modes:["render"]}) 之上(设计决议 3.7
|
|
111
|
-
//
|
|
112
|
-
|
|
122
|
+
async function runStop(writeStdout, port) {
|
|
123
|
+
// 实现在 stopLaunchedChromes({modes:["render"]}) 之上(设计决议 3.7 + 提案 §6.1):
|
|
124
|
+
// port 显式合法 → 只收该 port(与 ensure/status 对称);未设 → 收全部 render 记录
|
|
125
|
+
// (任意 port,3.7 语义不变)。归属验证/树杀/删账/profile 清理 100% 走 chrome-stop。
|
|
126
|
+
// 非法 env 的 exit 1 在 CLI stop 分支(需 exitFn,见下)。
|
|
127
|
+
const result = await stopLaunchedChromes({
|
|
128
|
+
...(port !== undefined ? { port } : {}),
|
|
129
|
+
modes: ["render"],
|
|
130
|
+
logFn: cliLog,
|
|
131
|
+
});
|
|
113
132
|
writeStdout(`${JSON.stringify(result)}\n`);
|
|
114
133
|
}
|
|
115
134
|
// ============================================================
|
|
@@ -131,7 +150,25 @@ export async function runRenderChromeCli(argv = process.argv.slice(3), opts = {}
|
|
|
131
150
|
}
|
|
132
151
|
try {
|
|
133
152
|
if (parsed.command === "doctor") {
|
|
134
|
-
|
|
153
|
+
// 提案 §6.2(2026-09-02):doctor 孤儿判定随 LASSO_RENDER_PORT 作用域化
|
|
154
|
+
// (与 --stop 同一原则/同一 env/同一 scope 函数)。非法 env → CLI 层 exit 1
|
|
155
|
+
// (stop 同规);renderDoctor 本体恒不 throw——它收已解析的 scopePort。
|
|
156
|
+
const scope = renderCdpPortScope();
|
|
157
|
+
if (scope.scope === "invalid") {
|
|
158
|
+
writeStderr(`${JSON.stringify({
|
|
159
|
+
evt: "render_doctor_invalid_port_env",
|
|
160
|
+
env: "LASSO_RENDER_PORT",
|
|
161
|
+
raw: scope.raw,
|
|
162
|
+
hint: "refusing to guess scope; unset the env for a global scan or fix the value",
|
|
163
|
+
})}\n`);
|
|
164
|
+
exitFn(1);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const report = renderDoctor({
|
|
168
|
+
clean: parsed.clean,
|
|
169
|
+
...(scope.scope === "explicit" ? { scopePort: scope.port } : {}),
|
|
170
|
+
logFn: cliLog,
|
|
171
|
+
});
|
|
135
172
|
writeStdout(`${JSON.stringify(report)}\n`);
|
|
136
173
|
exitFn(0);
|
|
137
174
|
return;
|
|
@@ -142,7 +179,23 @@ export async function runRenderChromeCli(argv = process.argv.slice(3), opts = {}
|
|
|
142
179
|
return;
|
|
143
180
|
}
|
|
144
181
|
if (parsed.command === "stop") {
|
|
145
|
-
|
|
182
|
+
// 提案 §6.1(2026-09-02):scope 解析上移到 CLI 分支以便取 exitFn——
|
|
183
|
+
// - 显式合法 → port 限定(与 ensure/status 对称);
|
|
184
|
+
// - 未设 → 全收(设计决议 3.7 语义不变);
|
|
185
|
+
// - 显式非法 → exit 1 用法错(stderr 单行 JSON 注明 env 名+原值,不猜作用域、
|
|
186
|
+
// 不动台账——kubectl #1272 教训:作用域旗标被静默忽略+广谱删除是同类事故)。
|
|
187
|
+
const scope = renderCdpPortScope();
|
|
188
|
+
if (scope.scope === "invalid") {
|
|
189
|
+
writeStderr(`${JSON.stringify({
|
|
190
|
+
evt: "render_stop_invalid_port_env",
|
|
191
|
+
env: "LASSO_RENDER_PORT",
|
|
192
|
+
raw: scope.raw,
|
|
193
|
+
hint: "refusing to guess scope; unset the env for a global stop or fix the value",
|
|
194
|
+
})}\n`);
|
|
195
|
+
exitFn(1);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
await runStop(writeStdout, scope.scope === "explicit" ? scope.port : undefined);
|
|
146
199
|
exitFn(0);
|
|
147
200
|
return;
|
|
148
201
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-chrome.js","sourceRoot":"","sources":["../../src/render/render-chrome.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"render-chrome.js","sourceRoot":"","sources":["../../src/render/render-chrome.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,18 @@ export interface RenderDoctorOrphan {
|
|
|
14
14
|
}
|
|
15
15
|
export interface RenderDoctorReport {
|
|
16
16
|
orphans: RenderDoctorOrphan[];
|
|
17
|
+
/**
|
|
18
|
+
* 被豁免不判孤儿的候选清单(提案 §6.2,2026-09-02 新增字段——既有字段零改动,
|
|
19
|
+
* 只追加)。reason:`portMismatch` = scope 不匹配(显式 LASSO_RENDER_PORT 生效
|
|
20
|
+
* 且候选 port ≠ scope);`touchFresh` = touch 新鲜(≤600s,有消费者续命——含
|
|
21
|
+
* 未设 env 的全局 doctor 场景);`portUnknown` = 候选命令行不可提取 port
|
|
22
|
+
* (render-launcher 每实例必带该旗标,不可提取即形态异常,保守不杀)。
|
|
23
|
+
*/
|
|
24
|
+
outOfScope: Array<{
|
|
25
|
+
pid: number;
|
|
26
|
+
port?: number;
|
|
27
|
+
reason: "portMismatch" | "touchFresh" | "portUnknown";
|
|
28
|
+
}>;
|
|
17
29
|
staleProfiles: Array<{
|
|
18
30
|
dir: string;
|
|
19
31
|
ageHours: number;
|
|
@@ -28,6 +40,12 @@ export interface RenderDoctorReport {
|
|
|
28
40
|
export interface RenderDoctorOptions {
|
|
29
41
|
/** 执行清理(默认 false = dry-run 只报告)。 */
|
|
30
42
|
clean?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* 显式合法的 `LASSO_RENDER_PORT`(提案 §6.2 D 案:doctor 孤儿判定作用域化)。
|
|
45
|
+
* CLI 层已解析传入(非法 env 在 CLI 层 exit 1,本函数恒不 throw);undefined =
|
|
46
|
+
* 未设 env → 现状全扫(单用户维护窗不变)。
|
|
47
|
+
*/
|
|
48
|
+
scopePort?: number;
|
|
31
49
|
/** profile 基目录(默认 ~/.cache/lasso;测试隔离注入 tmp)。 */
|
|
32
50
|
profileBaseDir?: string;
|
|
33
51
|
/** 测试注入:全量进程表(默认 `ps -Axo pid=,etime=,command=`)。 */
|
|
@@ -36,6 +54,11 @@ export interface RenderDoctorOptions {
|
|
|
36
54
|
readLedgerFn?: () => LaunchedChromeRecord[];
|
|
37
55
|
/** 测试注入:时钟(默认 Date.now)。 */
|
|
38
56
|
nowFn?: () => number;
|
|
57
|
+
/**
|
|
58
|
+
* 测试注入:touch mtime 读(默认 chromeTouchMtimeSync——镜像 chrome-idle-reaper
|
|
59
|
+
* 的 touchStatFn 注入模式;E 案豁免与 reaper 收割信任同一活性信号源)。
|
|
60
|
+
*/
|
|
61
|
+
touchStatFn?: (port: number) => number | undefined;
|
|
39
62
|
/** 测试注入:树杀原语(默认 util/kill-tree killTreeSync)。 */
|
|
40
63
|
killTreeFn?: (pid: number, tag?: string) => void;
|
|
41
64
|
logFn?: LedgerLogFn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-doctor.d.ts","sourceRoot":"","sources":["../../src/render/render-doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render-doctor.d.ts","sourceRoot":"","sources":["../../src/render/render-doctor.ts"],"names":[],"mappings":"AAwCA,OAAO,EAAkB,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAQ3G,oCAAoC;AACpC,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,sCAAsC;AACtC,eAAO,MAAM,uBAAuB,QAAsB,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B;;;;;;OAMG;IACH,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,cAAc,GAAG,YAAY,GAAG,aAAa,CAAA;KAAE,CAAC,CAAC;IACzG,aAAa,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mCAAmC;IACnC,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IACvB,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,oBAAoB,EAAE,CAAC;IAC5C,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACnD,iDAAiD;IACjD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBvD;AA0BD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,kBAAkB,CA0G/E;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAIhG"}
|
|
@@ -6,6 +6,22 @@
|
|
|
6
6
|
* etime > 10min。🔴 不以 `puppeteer_dev_chrome_profile` 判定(puppeteer 通用名,
|
|
7
7
|
* chrome-devtools-mcp 等他家用,会误伤——对接说明边界 3)。
|
|
8
8
|
*
|
|
9
|
+
* 2026-09-02 提案 §6.2(doctor 端口作用域化 + touch 新鲜度豁免):
|
|
10
|
+
* - D 案:`scopePort`(CLI 层已解析的显式合法 `LASSO_RENDER_PORT`)生效时,候选
|
|
11
|
+
* 进程的 `--remote-debugging-port` 与其不匹配(或不可提取)→ 不判孤儿不计 clean,
|
|
12
|
+
* 入 `outOfScope`(reason `portMismatch`/`portUnknown`)——与 --stop 同一原则、
|
|
13
|
+
* 同一 env、同一 scope 函数,一次裁决两处对称落地;
|
|
14
|
+
* - E 案:候选 port 的 touch 文件(chromeTouchMtimeSync——与 idle reaper 同一活性
|
|
15
|
+
* 真源,消费方心跳契约 ≤60s,600s 线 = 10× 裕量)距今 ≤600s → 有消费者续命,
|
|
16
|
+
* 不判孤儿不计 clean,入 `outOfScope`(reason `touchFresh`)——连未设 env 的全局
|
|
17
|
+
* doctor 也受益(D 只保护显式设 env 场景,E 补齐在用保护);只增豁免不扩大击杀
|
|
18
|
+
* (失效方向 = 少杀,安全向)。touch 文件缺失/读失败 → 不豁免(无续命证据 =
|
|
19
|
+
* 与 reaper 同向,安全侧)。
|
|
20
|
+
* - `outOfScope` = 被豁免不判孤儿的候选清单(诚实降级:作用域 doctor 报零孤儿
|
|
21
|
+
* ≠ 全机干净,报告型 CLI 不得让用户误读)。
|
|
22
|
+
* - CLI 层非法 env exit 1 与 stop 同规;本函数本体「恒不 throw」保持——它收已
|
|
23
|
+
* 解析的 scopePort。
|
|
24
|
+
*
|
|
9
25
|
* --clean 才动手(默认 dry-run 只报告)。清理动作 = 指纹对 + `--user-data-dir` 含
|
|
10
26
|
* render-chrome-profile- 前缀**双重证据**命中才树杀 + rmSync profile。这是全仓
|
|
11
27
|
* **唯一**不经台账归属验证的杀路径——窄化为 R4 显式设计(孤儿定义即无台账),
|
|
@@ -23,6 +39,7 @@ import { readdirSync, rmSync, statSync } from "node:fs";
|
|
|
23
39
|
import * as path from "node:path";
|
|
24
40
|
import os from "node:os";
|
|
25
41
|
import { readLedgerSync } from "../launcher/chrome-ledger.js";
|
|
42
|
+
import { chromeTouchMtimeSync } from "../launcher/chrome-touch.js";
|
|
26
43
|
import { killTreeSync } from "../util/kill-tree.js";
|
|
27
44
|
import { renderFingerprintMatch, RENDER_PROFILE_PREFIX, } from "./render-flags.js";
|
|
28
45
|
/** 孤儿年龄线(设计决议 3.9:拉起窗口外的陈留才判孤儿)。 */
|
|
@@ -59,6 +76,14 @@ function extractUserDataDir(command) {
|
|
|
59
76
|
const m = command.match(/--user-data-dir=(\S+)/);
|
|
60
77
|
return m?.[1];
|
|
61
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* 命令行中提取 --remote-debugging-port=<n> 的值(镜像 extractUserDataDir;提案 §6.2
|
|
81
|
+
* D/E 共用同一提取正则。render-launcher 每实例必带该旗标——per-instance 项之一)。
|
|
82
|
+
*/
|
|
83
|
+
function extractDebugPort(command) {
|
|
84
|
+
const m = command.match(/--remote-debugging-port=(\d+)/);
|
|
85
|
+
return m ? parseInt(m[1], 10) : undefined;
|
|
86
|
+
}
|
|
62
87
|
/** 默认全量进程表读取(macOS/Linux 同形)。 */
|
|
63
88
|
function defaultPsAllFn() {
|
|
64
89
|
try {
|
|
@@ -78,11 +103,13 @@ export function renderDoctor(opts = {}) {
|
|
|
78
103
|
const nowFn = opts.nowFn ?? (() => Date.now());
|
|
79
104
|
const readLedgerFn = opts.readLedgerFn ?? readLedgerSync;
|
|
80
105
|
const killTreeFn = opts.killTreeFn ?? ((pid, tag) => killTreeSync(pid, tag));
|
|
106
|
+
const touchStatFn = opts.touchStatFn ?? ((port) => chromeTouchMtimeSync(port));
|
|
81
107
|
const base = opts.profileBaseDir ?? path.join(os.homedir(), ".cache", "lasso");
|
|
82
|
-
// ---- 1. 孤儿扫描(指纹对 + 台账缺位 +
|
|
108
|
+
// ---- 1. 孤儿扫描(指纹对 + 台账缺位 + 年龄线 + 提案 §6.2 第四重豁免)----
|
|
83
109
|
const ledger = readLedgerFn();
|
|
84
110
|
const ledgerPids = new Set(ledger.map((r) => r.pid));
|
|
85
111
|
const orphans = [];
|
|
112
|
+
const outOfScope = [];
|
|
86
113
|
const psAll = (opts.psAllFn ?? defaultPsAllFn)();
|
|
87
114
|
for (const line of psAll.split("\n")) {
|
|
88
115
|
const trimmed = line.trim();
|
|
@@ -103,6 +130,27 @@ export function renderDoctor(opts = {}) {
|
|
|
103
130
|
// 第三重:年龄线(刚拉起未记账的竞态窗口容忍)
|
|
104
131
|
if (etimeSec <= RENDER_ORPHAN_MIN_AGE_SEC)
|
|
105
132
|
continue;
|
|
133
|
+
// 第四重(提案 §6.2,2026-09-02):D 端口作用域 + E touch 新鲜度豁免——
|
|
134
|
+
// 只增豁免不扩大击杀(失效方向 = 少杀,安全向);豁免者入 outOfScope 诚实报告。
|
|
135
|
+
const candPort = extractDebugPort(command);
|
|
136
|
+
if (candPort === undefined) {
|
|
137
|
+
// port 不可提取:render-launcher 每实例必带该旗标,不可提取即形态异常——
|
|
138
|
+
// 保守不杀(scope 与否同规)
|
|
139
|
+
outOfScope.push({ pid, reason: "portUnknown" });
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (opts.scopePort !== undefined && candPort !== opts.scopePort) {
|
|
143
|
+
// D 案:显式 LASSO_RENDER_PORT 生效,候选在他人命名空间 → 不判孤儿不计 clean
|
|
144
|
+
outOfScope.push({ pid, port: candPort, reason: "portMismatch" });
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// E 案:touch 新鲜(≤600s = 有消费者续命;心跳契约 ≤60s → 10× 裕量,与 reaper
|
|
148
|
+
// 收割包络同源对齐)。touch 缺失/读失败(undefined)→ 不豁免(安全侧)。
|
|
149
|
+
const touchMtime = touchStatFn(candPort);
|
|
150
|
+
if (touchMtime !== undefined && nowFn() - touchMtime <= RENDER_ORPHAN_MIN_AGE_SEC * 1000) {
|
|
151
|
+
outOfScope.push({ pid, port: candPort, reason: "touchFresh" });
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
106
154
|
const profileDir = extractUserDataDir(command);
|
|
107
155
|
const cleanable = profileDir !== undefined && path.basename(profileDir).startsWith(RENDER_PROFILE_PREFIX);
|
|
108
156
|
orphans.push({ pid, etimeSec, profileDir: cleanable ? profileDir : undefined, cleanable, command });
|
|
@@ -162,7 +210,7 @@ export function renderDoctor(opts = {}) {
|
|
|
162
210
|
}
|
|
163
211
|
}
|
|
164
212
|
}
|
|
165
|
-
return { orphans, staleProfiles, cleaned, clean };
|
|
213
|
+
return { orphans, outOfScope, staleProfiles, cleaned, clean };
|
|
166
214
|
}
|
|
167
215
|
/** 读取 fixture/文本形状的进程表时复用的行解析(导出供测试对齐真实 ps 形状)。 */
|
|
168
216
|
export function parsePsLine(line) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-doctor.js","sourceRoot":"","sources":["../../src/render/render-doctor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"render-doctor.js","sourceRoot":"","sources":["../../src/render/render-doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,12 +8,37 @@ export declare const RENDER_DETERMINISTIC_FLAGS: readonly string[];
|
|
|
8
8
|
/**
|
|
9
9
|
* 渲染档 CDP 端口默认(设计决议 3.2)。选值查证:9222 = lasso launch-chrome 默认档;
|
|
10
10
|
* 9223 = media-gen Flow provider CDP 惯例;**9224 = 空闲**。
|
|
11
|
-
* env `LASSO_RENDER_PORT`
|
|
11
|
+
* env `LASSO_RENDER_PORT` 覆盖(测试隔离 + 并行验收隔离用,配方见 doc/渲染档-并行验收隔离配方.md;单值覆盖不构成端口协商——冲突仍
|
|
12
12
|
* exit 3,协商留 R7)。
|
|
13
13
|
*/
|
|
14
14
|
export declare const RENDER_CDP_PORT_DEFAULT = 9224;
|
|
15
15
|
/** 渲染档 CDP 端口(env LASSO_RENDER_PORT 覆盖;非法/越界值降级默认并保持诚实)。 */
|
|
16
16
|
export declare function renderCdpPort(): number;
|
|
17
|
+
/**
|
|
18
|
+
* `LASSO_RENDER_PORT` 作用域解析三态(提案 §6.1 实施决议,2026-09-02):
|
|
19
|
+
* - `unset`:未设/空串 → `--stop`/`doctor` 维持「全收/全扫」(设计决议 3.7 语义不变);
|
|
20
|
+
* - `explicit`:显式且合法 → 只作用该 port(与 ensure/status 对称);
|
|
21
|
+
* - `invalid`:显式但非法/越界 → CLI 层 exit 1 用法错(stderr 注明 env 名+原值),
|
|
22
|
+
* 不猜作用域、不动台账——「用户已表达作用域,因值写错被静默按全局删除」正是
|
|
23
|
+
* kubectl #1272 的事故形态(提案 §6.1 裁决理由 a)。
|
|
24
|
+
*
|
|
25
|
+
* 🔴 同谓词硬约束(提案 §6.1 修订轮):本函数与 `renderCdpPort()` 共享**同一接受集**
|
|
26
|
+
* (下方 `parseRenderPortRaw` 私有 helper,两函数同源调用)——消费方 media-gen-mcp
|
|
27
|
+
* runEnsure 的 execFileAsync 不传 env → process.env 全量继承,shell 泄漏的奇形合法值
|
|
28
|
+
* 同一字符串同时到达 ensure 与 stop,谓词分叉即「ensure 在 9224 运行 / stop exit 1
|
|
29
|
+
* 拒收」裂脑态。等价语料 tripwire 见 test/unit/render-flags.spec.ts。
|
|
30
|
+
*/
|
|
31
|
+
export type RenderCdpPortScope = {
|
|
32
|
+
scope: "unset";
|
|
33
|
+
} | {
|
|
34
|
+
scope: "explicit";
|
|
35
|
+
port: number;
|
|
36
|
+
} | {
|
|
37
|
+
scope: "invalid";
|
|
38
|
+
raw: string;
|
|
39
|
+
};
|
|
40
|
+
/** `LASSO_RENDER_PORT` 作用域三态解析(供 --stop/doctor CLI 分支取 scope 与 exitFn)。 */
|
|
41
|
+
export declare function renderCdpPortScope(): RenderCdpPortScope;
|
|
17
42
|
/**
|
|
18
43
|
* 渲染档临时 profile 目录名前缀(设计决议 3.4)。R-INT-08 查证:`~/.cache/lasso/`
|
|
19
44
|
* 内无同名占用带。rmSync 归属守卫(chrome-stop.ts cleanupRenderProfile 的
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-flags.d.ts","sourceRoot":"","sources":["../../src/render/render-flags.ts"],"names":[],"mappings":"AA0CA;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EA2CvD,CAAC;AAKF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,4DAA4D;AAC5D,wBAAgB,aAAa,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"render-flags.d.ts","sourceRoot":"","sources":["../../src/render/render-flags.ts"],"names":[],"mappings":"AA0CA;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EA2CvD,CAAC;AAKF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,4DAA4D;AAC5D,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAClB;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBtC,2EAA2E;AAC3E,wBAAgB,kBAAkB,IAAI,kBAAkB,CAEvD;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,2BAA2B,CAAC;AAK9D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAKD,uCAAuC;AACvC,eAAO,MAAM,yBAAyB,4CAA4C,CAAC;AACnF,eAAO,MAAM,yBAAyB,+BAA+B,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE/D"}
|
|
@@ -95,19 +95,33 @@ export const RENDER_DETERMINISTIC_FLAGS = [
|
|
|
95
95
|
/**
|
|
96
96
|
* 渲染档 CDP 端口默认(设计决议 3.2)。选值查证:9222 = lasso launch-chrome 默认档;
|
|
97
97
|
* 9223 = media-gen Flow provider CDP 惯例;**9224 = 空闲**。
|
|
98
|
-
* env `LASSO_RENDER_PORT`
|
|
98
|
+
* env `LASSO_RENDER_PORT` 覆盖(测试隔离 + 并行验收隔离用,配方见 doc/渲染档-并行验收隔离配方.md;单值覆盖不构成端口协商——冲突仍
|
|
99
99
|
* exit 3,协商留 R7)。
|
|
100
100
|
*/
|
|
101
101
|
export const RENDER_CDP_PORT_DEFAULT = 9224;
|
|
102
102
|
/** 渲染档 CDP 端口(env LASSO_RENDER_PORT 覆盖;非法/越界值降级默认并保持诚实)。 */
|
|
103
103
|
export function renderCdpPort() {
|
|
104
|
-
const
|
|
104
|
+
const s = parseRenderPortRaw(process.env.LASSO_RENDER_PORT);
|
|
105
|
+
return s.scope === "explicit" ? s.port : RENDER_CDP_PORT_DEFAULT;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 私有共享谓词(提案 §6.1 同谓词硬约束的落点):raw undefined 或 `trim()===""` →
|
|
109
|
+
* unset;否则 `parseInt(raw,10)` + `Number.isInteger` + `0<n≤65535`(parseInt 语义
|
|
110
|
+
* 非 Number/正则语义:"+9224"/" 9224"/"09224"/"9224.5"/"9224 " 均为 explicit:9224;
|
|
111
|
+
* "0x2406" → parseInt 停在 x 得 0 → invalid)。renderCdpPort 与 renderCdpPortScope
|
|
112
|
+
* 禁止各自实现更严/更宽的谓词。
|
|
113
|
+
*/
|
|
114
|
+
function parseRenderPortRaw(raw) {
|
|
105
115
|
if (raw === undefined || raw.trim() === "")
|
|
106
|
-
return
|
|
116
|
+
return { scope: "unset" };
|
|
107
117
|
const n = parseInt(raw, 10);
|
|
108
118
|
if (!Number.isInteger(n) || n <= 0 || n > 65535)
|
|
109
|
-
return
|
|
110
|
-
return n;
|
|
119
|
+
return { scope: "invalid", raw };
|
|
120
|
+
return { scope: "explicit", port: n };
|
|
121
|
+
}
|
|
122
|
+
/** `LASSO_RENDER_PORT` 作用域三态解析(供 --stop/doctor CLI 分支取 scope 与 exitFn)。 */
|
|
123
|
+
export function renderCdpPortScope() {
|
|
124
|
+
return parseRenderPortRaw(process.env.LASSO_RENDER_PORT);
|
|
111
125
|
}
|
|
112
126
|
/**
|
|
113
127
|
* 渲染档临时 profile 目录名前缀(设计决议 3.4)。R-INT-08 查证:`~/.cache/lasso/`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-flags.js","sourceRoot":"","sources":["../../src/render/render-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,+DAA+D;AAC/D,uCAAuC;AACvC,6EAA6E;AAC7E,+DAA+D;AAC/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsB;IAC3D,yDAAyD;IACzD,0BAA0B;IAC1B,iCAAiC;IACjC,uCAAuC;IACvC,0CAA0C;IAC1C,oBAAoB;IACpB,0CAA0C;IAC1C,sDAAsD;IACtD,0BAA0B;IAC1B,wBAAwB;IACxB,yBAAyB,EAAE,4CAA4C;IACvE,wBAAwB;IACxB,oBAAoB;IACpB,mCAAmC,EAAE,gFAAgF;IACrH,0BAA0B;IAC1B,4BAA4B;IAC5B,kCAAkC;IAClC,uCAAuC;IACvC,gBAAgB;IAChB,qBAAqB;IACrB,qBAAqB;IACrB,4BAA4B;IAC5B,iCAAiC;IACjC,0BAA0B;IAC1B,gBAAgB;IAChB,wBAAwB;IACxB,qBAAqB;IACrB,yJAAyJ;IACzJ,4BAA4B;IAC5B,gBAAgB;IAChB,mBAAmB;IACnB,cAAc;IACd,sBAAsB;IACtB,mEAAmE;IACnE,cAAc;IACd,eAAe,EAAE,oBAAoB;IACrC,4BAA4B;IAC5B,4BAA4B,EAAE,wCAAwC;IACtE,yCAAyC;IACzC,uCAAuC,EAAE,OAAO;IAChD,0CAA0C,EAAE,OAAO;IACnD,kCAAkC,EAAE,OAAO;CAC5C,CAAC;AAEF,+DAA+D;AAC/D,0CAA0C;AAC1C,+DAA+D;AAC/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C,4DAA4D;AAC5D,MAAM,UAAU,aAAa;IAC3B,MAAM,
|
|
1
|
+
{"version":3,"file":"render-flags.js","sourceRoot":"","sources":["../../src/render/render-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,+DAA+D;AAC/D,uCAAuC;AACvC,6EAA6E;AAC7E,+DAA+D;AAC/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsB;IAC3D,yDAAyD;IACzD,0BAA0B;IAC1B,iCAAiC;IACjC,uCAAuC;IACvC,0CAA0C;IAC1C,oBAAoB;IACpB,0CAA0C;IAC1C,sDAAsD;IACtD,0BAA0B;IAC1B,wBAAwB;IACxB,yBAAyB,EAAE,4CAA4C;IACvE,wBAAwB;IACxB,oBAAoB;IACpB,mCAAmC,EAAE,gFAAgF;IACrH,0BAA0B;IAC1B,4BAA4B;IAC5B,kCAAkC;IAClC,uCAAuC;IACvC,gBAAgB;IAChB,qBAAqB;IACrB,qBAAqB;IACrB,4BAA4B;IAC5B,iCAAiC;IACjC,0BAA0B;IAC1B,gBAAgB;IAChB,wBAAwB;IACxB,qBAAqB;IACrB,yJAAyJ;IACzJ,4BAA4B;IAC5B,gBAAgB;IAChB,mBAAmB;IACnB,cAAc;IACd,sBAAsB;IACtB,mEAAmE;IACnE,cAAc;IACd,eAAe,EAAE,oBAAoB;IACrC,4BAA4B;IAC5B,4BAA4B,EAAE,wCAAwC;IACtE,yCAAyC;IACzC,uCAAuC,EAAE,OAAO;IAChD,0CAA0C,EAAE,OAAO;IACnD,kCAAkC,EAAE,OAAO;CAC5C,CAAC;AAEF,+DAA+D;AAC/D,0CAA0C;AAC1C,+DAA+D;AAC/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C,4DAA4D;AAC5D,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC;AACnE,CAAC;AAqBD;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,GAAuB;IACjD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACtE,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;IAClF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB;IAChC,OAAO,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AAE9D,+DAA+D;AAC/D,+CAA+C;AAC/C,+DAA+D;AAC/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC7C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,sBAAsB,CAAC;IAC1E,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAAE,OAAO,sBAAsB,CAAC;IACxD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,+DAA+D;AAC/D,sBAAsB;AACtB,+DAA+D;AAC/D,uCAAuC;AACvC,MAAM,CAAC,MAAM,yBAAyB,GAAG,yCAAyC,CAAC;AACnF,MAAM,CAAC,MAAM,yBAAyB,GAAG,4BAA4B,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,OAAO,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;AACpG,CAAC"}
|