open-tui-orchestrator 0.9.17 → 0.9.18
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/CHANGELOG.md +6 -0
- package/README-zh.md +1 -1
- package/README.md +1 -1
- package/docs/release-policy.md +1 -1
- package/package.json +1 -1
- package/release.json +8 -8
- package/scripts/core/contracts.mjs +1 -1
- package/scripts/core/runner.mjs +18 -4
- package/scripts/core/unit-memory-sampler.ps1 +15 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.18 — core 1.16.5
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **The per-unit memory sampler now actually runs (and the learning loop is live).** Two Windows-specific killers, both found by exact reproduction: (1) spawning the sampler PowerShell with `detached: true` made it die silently before executing a single line (no write, no error, no exit) — the spawn is now a plain child; (2) the tree walk used an unfiltered `Get-CimInstance Win32_Process` snapshot, which stalls under load, and crashed on a null pid in the tree — it now walks children with per-parent filtered queries plus null guards. The sampler also writes a `.start` marker and an `.error` file (and the runner tees its stderr), so a silent failure can never happen again unnoticed. Verified end-to-end: a real orchestration recorded six 68MB peaks for its agent into `unit-memory.json`, so estimates now come from measurements (p90 × safety) instead of the conservative default. The 0.9.17 mechanism itself is unchanged and was already verified; safety behaviour (falling back to the default when no samples exist) stays.
|
|
8
|
+
|
|
3
9
|
## 0.9.17 — core 1.16.4
|
|
4
10
|
|
|
5
11
|
### Changed
|
package/README-zh.md
CHANGED
|
@@ -177,6 +177,6 @@ node cli.mjs --agent claude --doctor
|
|
|
177
177
|
node cli.mjs --agent openclaw --doctor
|
|
178
178
|
~~~
|
|
179
179
|
|
|
180
|
-
当前通用核心为 1.16.
|
|
180
|
+
当前通用核心为 1.16.5,离线回归为 336/336 通过;覆盖无窗 headless 派发默认(`--mode window` 保留可见弹窗;launcher/身份/租约/恢复契约同构,隐藏载具不抢焦点)、单元载体分级(TUI 类 agent 走 ConPTY 伪终端载体——真实控制台、无窗口、不抢焦点,身份/租约/恢复契约与窗口模式同构;print 类维持无控制台载体)、执行看板(块与任务状态实时 `[board]` 行、run `events.jsonl`、只读 `--watch <runId>` 流式视图含 `--jsonl`、`--status` 活动 run 摘要)、任务不丢失、内存拟合动态并发(按宿主的单元内存画像学习;“合并到放得下”并保 256MB 底线)、依赖波次、同项目任务按资源键精细化拆分、全局容量租约(排队块等待指数退避+抖动;`ORCH_WAIT_BACKOFF_MS`/`ORCH_WAIT_BACKOFF_MAX_MS` 可调;协调器互斥等待亦可调可重试:`ORCH_MUTEX_WAIT_MS`/`ORCH_MUTEX_RETRIES`,锁票按龄回收 `ORCH_MUTEX_TICKET_TTL_MS`)、Windows Terminal 启动(同步拉起,弹窗可靠且不抢发起窗焦点)、失焦启动回归、进程身份、断点恢复、恢复账本加固(launcherFiles 工作区包容、验收契约哈希绑定、注册表锁老化回收)、守护进程驱动的控制器丢失自动恢复(test/guardian-live-result.json)与手动 --resume-run 收编存活窗口恢复(test/recovery-live-result.json)、发起方自动识别(环境标记优先、进程链兜底:kimi/codex/claude/pi/opencode/openclaw/hermes)、`orch` 强制编排入口、print-class 数据驱动画像适配管线(表面探测→画像→解析自检→活验守门→重封→自动提交,失败一律回滚;画像 agent 按 `modelDetection` 跟随发起窗 model/effort;hermes 画像已落地——hermes 发起即自动挡:识别其身份并以自身 CLI 执行(`--no-restore-cwd` 防旧会话 CWD 写偏))、调用方自助通道(调用方自带计划文件在覆盖/依赖/回退保证不变的前提下跑通且全程零模型调用、调用方自带单元命令让任意 CLI 走同一启动器/租约/恢复/验收契约、只读 `--tasks` 账本助手、单元命令的 resume 身份一致性、未知 agent 的两条出路诊断)、档位去向留痕(summary 记录 model/effort 与三态来源:explicit/宿主会话/host-default;机器可读入口 stdout 保持纯数据)、机器可调用失败契约(公开入口失败一律只回一行 `[orchestrator] FATAL: <原因>`、无 Node 栈帧(`ORCH_DEBUG=1` 才打);未知 run 不甩 `ENOENT`、不挂起——`--verify-run`/`--resume-run` 立刻回 `Run not found: <id>`,`--watch` 先给有界宽限 `ORCH_WATCH_GRACE_MS`(默认 60s,覆盖 `--run-windows` 仍在规划、run 目录尚未建立的竞态)再拒,看板中途丢 `summary.json` 也立刻报错而不静默停摆)、维护锁、当前核心安全审计及修复(docs/security-audit-2026-09-09.md)、弱网配置、SDK 诊断、宿主 CLI 探测超时重试与逐候选拒绝诊断、OpenClaw 版本门诊断(tui 接口探针先行:未验证版本以探针实测结果 + 最后验证版本 fail-closed——版本常量只记「最后验证于」,不是准入门槛)、恢复账本校验覆盖盘符根工作区和干净发行副本。测试环境要求:离线套件假定发起 agent 的 CLI(默认 `codex`)可在 PATH 解析(Windows 下前置 codex vendor bin,即回归环境约定);缺失时依赖 agent 解析的测试文件按设计快速失败(fail-closed),其中两个运行期依赖 CLI 的用例已标注 `{skip}`。真实模型额度、不同 Windows 用户安装、长时间断网恢复和每个未来 Agent 的现场兼容性也仍需单独验收。
|
|
181
181
|
|
|
182
182
|
未知宿主、无可执行 CLI 或显式路径无效时,命令会直接失败并给出原因;不会自动安装、猜测替代路径或换用其它 Agent。
|
package/README.md
CHANGED
|
@@ -177,6 +177,6 @@ node cli.mjs --agent claude --doctor
|
|
|
177
177
|
node cli.mjs --agent openclaw --doctor
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
-
The current generic core is 1.16.
|
|
180
|
+
The current generic core is 1.16.5, with 336/336 offline tests passing. Coverage includes headless spawn mode as the default (--mode window keeps the visible Windows Terminal popups; the launcher/identity/lease/recovery contract is shared, and the hidden carrier cannot steal focus; TUI-class agents run on a ConPTY pseudo-terminal carrier — a real console that stays fully invisible, while print-class CLIs keep the no-console carrier), a live run board (per-transition [board] stdout lines, run events.jsonl, read-only --watch <runId> streaming with --jsonl, and --status active-run rows), lossless task accounting, memory-fit dynamic concurrency (per-host learned unit-memory profiles; merge-to-fit under a free-memory floor), dependency waves, fine-grained same-project splitting by resource keys, global capacity leases with exponential + jittered wait backoff for queued blocks (ORCH_WAIT_BACKOFF_MS / ORCH_WAIT_BACKOFF_MAX_MS) and a tunable, retried coordinator-mutex wait (ORCH_MUTEX_WAIT_MS / ORCH_MUTEX_RETRIES) with age-based ticket reclamation (ORCH_MUTEX_TICKET_TTL_MS), Windows Terminal launch (synchronous and reliable, without stealing the initiating window's focus), unfocused-start regressions, process identity, checkpoint recovery, recovery-ledger hardening (launcher-files workspace containment, acceptance-contract hash binding, registry-lock stale reclaim), guardian-driven automatic resume after controller loss (test/guardian-live-result.json) plus manual --resume-run adoption of surviving windows (test/recovery-live-result.json), initiating-agent detection (env markers first, then the process chain: kimi/codex/claude/pi/opencode/openclaw/hermes), the `orch` force-execute entry, print-class data-driven profile adaptation (surface probe → profile → resolution self-check → live verification → reseal → auto-commit, rolled back on failure; profile `modelDetection` lets profiled agents follow the initiating window's model/effort; an adapter-less agent with a landed profile (hermes) is a first-class auto host — the initiating agent is detected and drives its own CLI as the executor with `--no-restore-cwd` guarding against stale-session CWD writes), the caller-driven channel (a caller-supplied plan file kept under the unchanged coverage/dependency/fallback guarantees with zero model calls in the run, caller-supplied unit commands driving any CLI in the same launcher/lease/recovery/acceptance contract, the read-only --tasks ledger helper, resume identity rules for unit commands, and the two-path diagnostic for unknown agents), model/effort traceability (summary records model/effort plus the source: explicit / host session / host-default; machine-readable stdout stays pure data), the machine-caller failure contract (every public entry fails closed with one `[orchestrator] FATAL: <reason>` line and no Node stack unless `ORCH_DEBUG=1`; an unknown run id never dumps `ENOENT` and never hangs — `--verify-run`/`--resume-run` refuse immediately with `Run not found: <id>`, and `--watch` honours a bounded `ORCH_WATCH_GRACE_MS` grace (default 60 s, covering the window in which `--run-windows` is still planning) before refusing, reporting a summary that disappears mid-watch instead of watching forever), the maintenance lock, a current-core security audit with fixes landed (docs/security-audit-2026-09-09.md), weak-network configuration, SDK diagnostics, host CLI probe timeout retry with per-candidate rejection diagnostics, OpenClaw version-gate diagnostics (the runtime tui interface probe runs first; unverified versions fail closed carrying the probe result and the last-verified version — the constant records "last verified", it is not an admission gate), recovery-ledger containment that covers drive-root workspaces, and clean package publication. Test-env requirement: the offline suite assumes the initiating agent CLI (default `codex`) is resolvable on PATH — on Windows prepend the codex vendor bin (the documented regression convention). Without it, agent-resolution-dependent test files fail fast by design (fail-closed); the two runtime-CLI-dependent cases are annotated `{skip}`. Real model quotas, installation under a different Windows user, prolonged offline recovery and field compatibility for future Agents also require separate acceptance.
|
|
181
181
|
|
|
182
182
|
An unknown host, missing CLI or invalid explicit path fails with a diagnostic. The tool does not install software, guess a replacement path or switch to another Agent.
|
package/docs/release-policy.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
2026-09-17 现场修复轮(core 1.15.2 / 0.9.12):**单元停滞看门狗 + 残窗收口**。① 停滞判据=进度(检查点/结果/启动器 out·pty 日志/宿主会话 mtime)停止超过 `ORCH_UNIT_STALL_MS`(默认 600000ms)→ 判 `stalled` → 走正常收口(杀净后代、launcher 自查 exit 0;绝不强杀 launcher 本体)→ 计入该块 attempts 预算自动重跑;`ORCH_UNIT_TIMEOUT_MS`(默认 2700000ms)限制单元寿命;预算耗尽的 reason 现在带上次失败文本。实机演示(`D:/temp/orch-stall-live/`,sleeper 单元 + ORCH_UNIT_STALL_MS=8000):两窗弹出→8s 判停滞→自动关→自动重开 a2→再次判停滞→`finalized success=false`(rc=1),无残留进程、无残留窗口;判据 `test/unit-stall.test.mjs`(修复前会一直挂到运行上限)。② 残窗收口=只按**本 run 自己**录下的窗口句柄(`win-*.window.json`)且「窗口属 Windows Terminal + 宿主无任何子进程(尸体窗)」才发 WM_CLOSE;纯函数判据 `leftoverWindowHandles()`(`test/leftover-windows.test.mjs`)+ 运行前自动收口(`sweepLeftoverRunWindows()` 在 runner 之前);实逮并清掉本轮矩阵/停电演练留下的 8 个尸体窗(可见窗口 12→4,余下全为不可见宿主窗)。③ 旁记:force-kill launcher 的思路被现场否决(会在 WT 留下「[已退出进程,代码为 1]」死窗格)——正确收口是杀后代让 launcher 自己 exit 0。
|
|
14
14
|
|
|
15
|
-
当前源码封印记录通用核心 1.16.
|
|
15
|
+
当前源码封印记录通用核心 1.16.5、47 个核心文件和 70 个运行时文件。最新离线回归为 336/336 通过;当前已覆盖任务不丢失、多块并行容量调度、依赖波次、单块/纯串行计划不触发普通开窗、同项目任务按资源键精细化拆分并行(资源不明则整组串行兜底)、全局容量租约(排队等待指数退避+抖动:首等 600ms、×1.7、封顶 5s、抖动 ±20%;`ORCH_WAIT_BACKOFF_MS`/`ORCH_WAIT_BACKOFF_MAX_MS` 可调)、无窗 headless 派发默认(`--mode window` 保留可见弹窗;launcher/身份/租约/恢复契约同构,隐藏载具不抢焦点;2026-09-10 在 pi/claude/opencode/kimi 四宿主实跑通过:双块收据齐、零弹窗)、单元载体分级(TUI 类 agent 的 ConPTY 伪终端载体:真实控制台、无窗口、不抢焦点,身份/租约/恢复契约与窗口模式同构;print 类维持无控制台载体;2026-09-12 在 codex(pty)与 pi(stdio)双载体实跑通过)、执行看板(块与任务状态实时 `[board]` 行、run `events.jsonl` 事件流、只读 `--watch <runId>` 流式视图、`--status` 活动 run 摘要)、Windows Terminal 启动(同步拉起,弹窗可靠且不抢发起窗焦点)、进程身份、断点身份、损坏账本拒绝、账本 launcherFiles 工作区包容校验、验收契约创建时哈希锚定(resume/verify 篡改即拒)、注册表锁老化回收、轮询截止时间、SDK 缺失诊断、CLI 只读 `--version` 版本痕迹(不改状态、不解析 agent CLI)、强制编排入口 `orch`(跳过全部 inline 回退——单块/纯串行/只读定性/自改都会派发单元,维护锁仍是唯一门)、调用方自助通道(`--plan-file` 自带计划文件走既有覆盖/依赖/回退硬校验且全程零模型调用,`--unit-cmd`/`--unit-cmd-file` 自带单元命令绕过宿主识别与探测、任意 CLI 走同一启动器/租约/恢复/验收契约,只读 `--tasks` 账本助手,单元命令的 resume 身份一致性,未知 agent 的两条出路诊断)、print-class 数据驱动画像适配管线(`node scripts/adapt.mjs` 与 `ORCH_AUTO_ADAPT=1` 自动模式:表面探测→画像→解析自检→活验守门→重封→自动提交,失败一律回滚;2026-09-11 aider 0.86.2 实弹完成表面/画像/自检并在未登录时正确 fail-closed;画像自动发现 model/effort 探测规格(`modelDetection`,只读 env/配置文件精确键名),发起窗 model/effort 对画像 agent 同样跟随;hermes 画像正式落地:`--agent hermes` 解析为 profile 宿主、hermes 发起即自动挡——适配探活实测 12.5s 取回令牌)、档位去向留痕(summary 的 model/effort 与三态来源 explicit/宿主会话/host-default;机器可读入口 stdout 保持纯数据)、机器可调用失败契约(公开入口失败只回一行 `[orchestrator] FATAL: <原因>`、无栈帧(`ORCH_DEBUG=1` 才打);未知 run 不甩 `ENOENT` 也不挂起:`--verify-run`/`--resume-run` 立刻 fail-closed,`--watch` 有界宽限 `ORCH_WATCH_GRACE_MS`(默认 60s)后 fail-closed,看板中途丢 `summary.json` 立刻报错)、宿主 CLI 探测超时重试与逐候选拒绝诊断(scripts/core/host-probe.mjs)、OpenClaw 版本门诊断(接口探针先行:版本常量只记「最后验证于」——未验证版本必须以 `tui` 接口探针实测结果 + node-pty 状态 + 最后验证版本 fail-closed;2026-09-14 本机 2026.9.3 实测:探针 OK、node-pty present;扩版仍需逐版 config/transcript/TUI 验收 + 用户侧 gateway 凭据)、恢复账本 launcherFiles 包容校验覆盖盘符根工作区、发起方自动识别(环境标记优先、进程链就近命中:kimi/codex/claude/pi/opencode/openclaw/hermes)、kimi、claude 与 opencode 适配器的启动器回环、控制器异常死亡后的守护进程自动接管恢复(test/guardian-live-result.json)与手动 --resume-run 收编存活窗口恢复(test/recovery-live-result.json)、维护锁(自身维护期间动作入口只回固定话术并放行,docs/maintenance-lock.md)和干净发布副本。2026-09-09 已完成当前核心安全复扫(双路 LLM 源码审计,docs/security-audit-2026-09-09.md):无 Critical/High,4 个 Medium 与 1 个 Low 已修复并纳入回归,其余 Low 登记为已知问题;该报告、对应修复提交与本次封印共同构成当前核心的新安全基线,替换 2026-09-05 绑定旧哈希的历史基线。长期环境验收仍单独列为发行门槛。覆盖率摘要保存在 `coverage/coverage-summary.json`,它是验证产物,不会随发行副本发布。
|
|
16
16
|
|
|
17
17
|
Codex、pi 和固定版本 OpenClaw 适配器各自负责宿主参数、会话输出、完成判定和关闭流程。Windows Terminal 是默认可见承载;PowerShell 只作为生命周期脚本和进程枚举辅助,不承担宿主适配。没有经过对应适配器验证的 CLI 会直接失败,不自动安装或回退到其它 Agent。
|
|
18
18
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-tui-orchestrator",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Split a multi-part agent request into a verified TODO ledger, then run the parallel blocks in hidden or visible TUI windows of the agent CLI you already use (Windows).",
|
|
6
6
|
"type": "module",
|
package/release.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 2,
|
|
3
|
-
"coreVersion": "1.16.
|
|
3
|
+
"coreVersion": "1.16.5",
|
|
4
4
|
"files": {
|
|
5
5
|
"adapt-lib.mjs": "4902e049b9b63c1d8eab285720a490b2925bb1611aacc060aa5db3289107d61d",
|
|
6
6
|
"agent-auth-prompt.txt": "18fa9c01972cd99a2fe2b1b74a440b34921a051ba6c0d54daf2f5bf1096457b0",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"checkpoint.mjs": "246de59db9a7aac48b12eea1554ff281eaf9dd897e620ecf73d954f39b3cf94a",
|
|
10
10
|
"claude-host.mjs": "8ab7661e2b56eab07709b2a16c7f6e04dab8708edfbe672300254109c2323aaa",
|
|
11
11
|
"claude-runtime.mjs": "06e7aba4a5c62a2bf0f12e09089db778c265a0aa21b31a53dbac7245586abe20",
|
|
12
|
-
"contracts.mjs": "
|
|
12
|
+
"contracts.mjs": "cdf1a8c233496c9e3ad6daf2862bceb04612dc6f7d8ba76ae6a1572a7a49b43c",
|
|
13
13
|
"failure-report.mjs": "0eae69efeabef1bde13855ae37f6cfdc18f55de58ad8a680cf35df6d67dc764b",
|
|
14
14
|
"host-cli.mjs": "6ad40cb2a0d216d064359d1d3e3fb38cd66218b518acdde7cd644b41e8450a0c",
|
|
15
15
|
"host-model.mjs": "8dd0fae5745f6a5a223d97d1d985ce3d2bd1c111fb8693b1efb5b72874f5b7d3",
|
|
@@ -42,17 +42,17 @@
|
|
|
42
42
|
"recovery.mjs": "faa98340e970651ad1ddca9c9dda60345e3e0a4b8e163f78b4674ed231b0b2a4",
|
|
43
43
|
"run-board.mjs": "ee98dac04d2babe68ff3c0a88f40547a380188ed8de7135cf54c9a0f469ae9e3",
|
|
44
44
|
"run-guardian.mjs": "e1b2b17663c0a9a8a408e8a25484b87adcf7144f4d08f81c03d736a704feda6b",
|
|
45
|
-
"runner.mjs": "
|
|
45
|
+
"runner.mjs": "59357979209e7fb44a18f446c7666eb8b503b6c4f96664f2d5bc00c7039a57f4",
|
|
46
46
|
"runtime-context.mjs": "39ee58751764034504a6e3c5a6cb53ded725abee5a5ccd7675ade7d690bdb58b",
|
|
47
47
|
"unit-carrier.mjs": "462b4512910a458815a1d5f7c1bce2e0e43e53e0511f5be3e13f118c879aeb48",
|
|
48
48
|
"unit-command.mjs": "93791c8e1d5ce7ccd87a9eb2a78438961faa723cb445535cadfef1254f1168ff",
|
|
49
|
-
"unit-memory-sampler.ps1": "
|
|
49
|
+
"unit-memory-sampler.ps1": "9852cbe22d6876ec14a685064be0678fac497431cff7100aac3007fb0985a27f",
|
|
50
50
|
"unit-memory.mjs": "d7e066ce6d19740237a6375809535cd3d9e59a0250abe1995fbfbd1bb3ccf35f",
|
|
51
51
|
"unit-runtime.mjs": "21a7a287e59c068c6d277281d4fb092852cfe21f4bb2df62d6695106f4f20665"
|
|
52
52
|
},
|
|
53
53
|
"runtimeFiles": {
|
|
54
54
|
"cli.mjs": "8b6817604286769142d0620ed8da96d433596e84362cee66594e099c88f1a1c4",
|
|
55
|
-
"package.json": "
|
|
55
|
+
"package.json": "33ad87fd2a5ce24098fadfa195f7e511e0fbc244231f9566508e1a2bf378218c",
|
|
56
56
|
"repair.mjs": "5a456b42560bfa21fd1e66ccdff7416f88e82fe711db5c04279717e73275a076",
|
|
57
57
|
"scripts/recover-stale.mjs": "c6dfecdfd7621b77999b710127aa1f5e3b444032bc0e2f91ec95f94c07c59f97",
|
|
58
58
|
"scripts/adapt.mjs": "20209c74212d334ea5aa1dfe35816a1b7a4b7f0415eb27c5a1975925dbbd10c5",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"scripts/core/checkpoint.mjs": "246de59db9a7aac48b12eea1554ff281eaf9dd897e620ecf73d954f39b3cf94a",
|
|
66
66
|
"scripts/core/claude-host.mjs": "8ab7661e2b56eab07709b2a16c7f6e04dab8708edfbe672300254109c2323aaa",
|
|
67
67
|
"scripts/core/claude-runtime.mjs": "06e7aba4a5c62a2bf0f12e09089db778c265a0aa21b31a53dbac7245586abe20",
|
|
68
|
-
"scripts/core/contracts.mjs": "
|
|
68
|
+
"scripts/core/contracts.mjs": "cdf1a8c233496c9e3ad6daf2862bceb04612dc6f7d8ba76ae6a1572a7a49b43c",
|
|
69
69
|
"scripts/core/failure-report.mjs": "0eae69efeabef1bde13855ae37f6cfdc18f55de58ad8a680cf35df6d67dc764b",
|
|
70
70
|
"scripts/core/host-cli.mjs": "6ad40cb2a0d216d064359d1d3e3fb38cd66218b518acdde7cd644b41e8450a0c",
|
|
71
71
|
"scripts/core/host-model.mjs": "8dd0fae5745f6a5a223d97d1d985ce3d2bd1c111fb8693b1efb5b72874f5b7d3",
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
"scripts/core/recovery.mjs": "faa98340e970651ad1ddca9c9dda60345e3e0a4b8e163f78b4674ed231b0b2a4",
|
|
99
99
|
"scripts/core/run-board.mjs": "ee98dac04d2babe68ff3c0a88f40547a380188ed8de7135cf54c9a0f469ae9e3",
|
|
100
100
|
"scripts/core/run-guardian.mjs": "e1b2b17663c0a9a8a408e8a25484b87adcf7144f4d08f81c03d736a704feda6b",
|
|
101
|
-
"scripts/core/runner.mjs": "
|
|
101
|
+
"scripts/core/runner.mjs": "59357979209e7fb44a18f446c7666eb8b503b6c4f96664f2d5bc00c7039a57f4",
|
|
102
102
|
"scripts/core/runtime-context.mjs": "39ee58751764034504a6e3c5a6cb53ded725abee5a5ccd7675ade7d690bdb58b",
|
|
103
103
|
"scripts/core/unit-carrier.mjs": "462b4512910a458815a1d5f7c1bce2e0e43e53e0511f5be3e13f118c879aeb48",
|
|
104
104
|
"scripts/core/unit-command.mjs": "93791c8e1d5ce7ccd87a9eb2a78438961faa723cb445535cadfef1254f1168ff",
|
|
105
|
-
"scripts/core/unit-memory-sampler.ps1": "
|
|
105
|
+
"scripts/core/unit-memory-sampler.ps1": "9852cbe22d6876ec14a685064be0678fac497431cff7100aac3007fb0985a27f",
|
|
106
106
|
"scripts/core/unit-memory.mjs": "d7e066ce6d19740237a6375809535cd3d9e59a0250abe1995fbfbd1bb3ccf35f",
|
|
107
107
|
"scripts/core/unit-runtime.mjs": "21a7a287e59c068c6d277281d4fb092852cfe21f4bb2df62d6695106f4f20665",
|
|
108
108
|
"scripts/gate.mjs": "f578fb41d112dd1d44fe5b46e451d4753ed7251ea150e8f44acb138340d604ae",
|
|
@@ -4,7 +4,7 @@ import crypto from 'node:crypto';
|
|
|
4
4
|
import {spawnSync} from 'node:child_process';
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
|
|
7
|
-
export const CORE_VERSION = '1.16.
|
|
7
|
+
export const CORE_VERSION = '1.16.5';
|
|
8
8
|
export const SUCCESS = new Set(['verified']);
|
|
9
9
|
export const TERMINAL = new Set(['verified','failed','blocked','cancelled','awaiting-verification','preflight-failed','popup-failed','timeout','needs-reconciliation']);
|
|
10
10
|
|
package/scripts/core/runner.mjs
CHANGED
|
@@ -28,19 +28,33 @@ function unitPeakFile(la, key, token) {
|
|
|
28
28
|
}
|
|
29
29
|
function startUnitSampler(la, key, token, rootPid) {
|
|
30
30
|
try {
|
|
31
|
-
if (!la || !Number.isInteger(rootPid) || rootPid <= 0)
|
|
31
|
+
if (!la || !Number.isInteger(rootPid) || rootPid <= 0) {
|
|
32
|
+
console.error('[mem] sampler skipped (rootPid=' + String(rootPid) + ', la=' + (la ? 'yes' : 'no') + ')');
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
32
35
|
const sampler = path.join(path.dirname(fileURLToPath(import.meta.url)), 'unit-memory-sampler.ps1');
|
|
33
|
-
|
|
36
|
+
// 2026-09-18 实测定论:detached:true 会让 PS 子进程在 Windows 上静默死掉(一行不执行、不报错、不退出)
|
|
37
|
+
// —— 去 detached,做普通子进程(引擎寿命 ≥ 单元寿命,采样器随单元结束自然收尾)。
|
|
38
|
+
const child = spawn(powershellExe(), ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', sampler, '-RootPid', String(rootPid), '-OutFile', unitPeakFile(la, key, token), '-IntervalMs', '6000'], {windowsHide: true, stdio: ['ignore', 'ignore', 'pipe']});
|
|
39
|
+
// 采样器的 stderr 落盘(2026-09-18:静默失败排查用;引擎先退出也尽量写)。
|
|
40
|
+
try {
|
|
41
|
+
const errLog = unitPeakFile(la, key, token) + '.stderr.txt';
|
|
42
|
+
child.stderr.on('data', (buf) => { try { fs.appendFileSync(errLog, buf); } catch {} });
|
|
43
|
+
} catch {}
|
|
34
44
|
child.unref();
|
|
45
|
+
console.log('[mem] sampler started pid=' + String(child.pid) + ' root=' + rootPid + ' out=' + unitPeakFile(la, key, token));
|
|
35
46
|
return true;
|
|
36
|
-
} catch {
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('[mem] sampler failed to start: ' + String(error && error.message));
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
37
51
|
}
|
|
38
52
|
async function recordUnitPeakIfReady(la, key, token, agent, waitForSample) {
|
|
39
53
|
try {
|
|
40
54
|
if (!la) return;
|
|
41
55
|
const file = unitPeakFile(la, key, token);
|
|
42
56
|
for (let i = 0; waitForSample && i < 10 && !fs.existsSync(file); i += 1) await pause(1000);
|
|
43
|
-
if (!fs.existsSync(file)) return;
|
|
57
|
+
if (!fs.existsSync(file)) { if (waitForSample) console.error('[mem] no peak sample for ' + key + ' (sampler did not finish; markers: ' + file + '.start / .error)'); return; }
|
|
44
58
|
const peak = Number(JSON.parse(fs.readFileSync(file, 'utf8'))?.peakMB);
|
|
45
59
|
fs.rmSync(file, {force: true}); // 读过即销:天然去重,旧样本不会重复入账
|
|
46
60
|
if (!Number.isFinite(peak) || peak <= 0) return;
|
|
@@ -10,14 +10,19 @@ param(
|
|
|
10
10
|
[int]$MaxMs = 3600000
|
|
11
11
|
)
|
|
12
12
|
$ErrorActionPreference = 'SilentlyContinue'
|
|
13
|
+
Set-Content -Path ($OutFile + '.start') -Value ((Get-Date).ToString('s')) -Encoding ascii
|
|
14
|
+
try {
|
|
13
15
|
|
|
14
16
|
function Get-TreeIds([int]$root) {
|
|
15
|
-
|
|
17
|
+
# 2026-09-18:全表 Get-CimInstance 在忙机器上会卡死(实测采样器刚起就被拖住 ✗)⇒ 改成按父进程过滤的递归查询。
|
|
16
18
|
$ids = @($root)
|
|
17
19
|
$frontier = @($root)
|
|
18
20
|
while ($frontier.Count -gt 0) {
|
|
19
|
-
$next = @(
|
|
20
|
-
|
|
21
|
+
$next = @()
|
|
22
|
+
foreach ($parent in $frontier) {
|
|
23
|
+
$next += @(Get-CimInstance Win32_Process -Filter ("ParentProcessId=" + $parent) -ErrorAction SilentlyContinue | Select-Object -ExpandProperty ProcessId | Where-Object { $_ })
|
|
24
|
+
}
|
|
25
|
+
$next = @($next | Where-Object { $_ -and ($ids -notcontains $_) })
|
|
21
26
|
if ($next.Count -eq 0) { break }
|
|
22
27
|
$ids += $next
|
|
23
28
|
$frontier = $next
|
|
@@ -32,8 +37,9 @@ $loops = 0
|
|
|
32
37
|
while ((((Get-Date) - $start).TotalMilliseconds) -lt $MaxMs) {
|
|
33
38
|
$alive = $false
|
|
34
39
|
$sum = [int64]0
|
|
35
|
-
foreach ($procId in $tree) {
|
|
36
|
-
|
|
40
|
+
foreach ($procId in @($tree | Where-Object { $_ })) {
|
|
41
|
+
if (-not $procId) { continue }
|
|
42
|
+
$procObj = Get-Process -Id ([int]$procId) -ErrorAction SilentlyContinue
|
|
37
43
|
if ($procObj) {
|
|
38
44
|
$alive = $true
|
|
39
45
|
$sum += [int64]$procObj.WorkingSet64
|
|
@@ -51,3 +57,7 @@ $peakMb = [int][math]::Round($peak / 1MB, 0)
|
|
|
51
57
|
$stamp = (Get-Date).ToString('s')
|
|
52
58
|
$json = '{"schema":1,"rootPid":' + $RootPid + ',"peakMB":' + $peakMb + ',"sampledAt":"' + $stamp + '","loops":' + $loops + '}'
|
|
53
59
|
Set-Content -Path $OutFile -Value $json -Encoding ascii
|
|
60
|
+
} catch {
|
|
61
|
+
Set-Content -Path ($OutFile + '.error') -Value ($_ | Out-String) -Encoding ascii
|
|
62
|
+
exit 1
|
|
63
|
+
}
|