修订日期: 2026-09-09
本路线图取代此前所有里程碑编号 (X3d/X3e/X3f/X3g/X3i/X3j 等)。旧编号只保留在
tools/nodejs/ownership/evidence/的历史证据文件中, 不再继续演进。2026-09-04 三次勘察: M0
M10 已全部收账 (仅 M10.1 等待上游产物)。本次按 "桌面 Node 保真度 / 宿主自动化能力面 / 传输与并发 / 工程与发布" 四个维度重新盘点, 增补 **M11M17** (见 "2026-09-04 三次勘察" 一节)。M11 之前的内容为已完成实绩, 不再改动。2026-08-26 所有权更新: M5 中关于宿主保留
sample/nodejs与docs/nodejs/types副本的决策已被取代。样例, 类型声明, 项目向导及其 Gradle 校验现在仅由本插件仓库维护; 宿主只保留路由, Binder 客户端, 工作区传输, Android 能力桥接与最小集成测试。详见docs/DEVELOPMENT-ASSETS.md。
为 AutoJs6 提供接近桌面体验的 Node.js 运行能力:
- 像桌面 Node.js 一样流畅运行 JavaScript — 完整 ES6+ 语法, CJS/ESM, npm 生态, 真实 V8 性能。
- 可以运行 AutoJs6 API 脚本 — Node 脚本内可调用宿主自动化能力 (无障碍, app, device, http 等)。
- 先让脚本跑起来, 出了异常再针对异常修复。 不做 "一次性完美方案", 不用测试和安全边界堆砌代码, 不把 "无穷尽验证正确性" 当作产品本体。
- 每个任务的完成标准是 一条用户可见的能力, 而不是一份报告 / 一个校验门禁 / 一条哈希锁。
- 保留最小烟雾测试 (能跑通 hello-world 级别脚本即可), 其余重型验证一律移出默认构建链, 按需手动触发。
- 诊断信息保留 (定位问题需要), 但不再新增 probe 类基础设施。
- ✅ Node.js 24.5.0 真实内嵌: 每 ABI 一个
libnode.so(~100 MB, arm64-v8a / armeabi-v7a / x86_64), dlopen + dlsym 驱动node::NewIsolate → CreateEnvironment → LoadEnvironment → SpinEventLoop完整生命周期, 常驻进程复用 V8 平台。 - ✅ 构建链可用:
:app:assembleDebug产出各 ABI + universal APK (已本机验证, v1.1.3 build 41)。 - ✅ 插件服务完备:
org.autojs.plugin.INFO发现 +org.autojs.plugin.nodejs.RUNTIME执行, 独立:nodejs_runtime进程, 同步执行 + 预热 + 重启式取消。 - ✅ CJS/ESM 与宿主预编译 TypeScript 执行, stdout/stderr 回传, 环境变量, 模块源注入, 运行时模块注入 (
autojs6:host-app-info等); 原始 TypeScript 在运行时边界 fail closed。 - ✅ 历史真机证据: API 34 x86_64 模拟器上 CJS/ESM 端到端执行通过 (见 evidence 存档)。
- [高度疑似主因] 模块源 Provider 契约硬拒绝: 插件端把 module-source-provider 契约锁死为
v2 only(MIN=2, MAX=2), 并且对请求里缺失/非 Integer 的版本字段一律按-1处理。宿主 AutoJs6 (当前 master, build 5276) 的 nodejs-api 还是 v1, 且 runScript 请求里 根本不放 版本字段 → 只要宿主附带 provider binder (加密模块场景), 插件必然返回ERR_AUTOJS6_NODE_PLUGIN_CONTRACT_MISMATCH。而两边的 AIDL 内容 完全一致, 这纯粹是元数据门禁自伤。 - 工作区归档传输是硬前置:
runScript无条件要求 workspace-archive-v2 双 FD, 缺失即抛错。任何不实现完整归档协议的调用方 (旧宿主 / adb 调试 / 第三方) 连console.log("hi")都跑不了。 - 验证性基础设施反噬开发循环:
check挂接 capability-truth / runtime-ownership / resolver 等门禁 (全仓库哈希扫描 + node 子进程); 主源码 9.2k 行 Java 对应 ~83k 行 C++ 里 93% 是 probe; 3.3k 行 conformance gradle 脚本。迭代速度被这些结构性拖慢, 而它们对 "脚本能不能跑" 没有贡献。 - 单活准入 + 重启式取消: 第二个脚本直接
BUSY, 取消 = 杀进程。可用性差 (M2 处理, 不是当前主因)。
目标: 一个只带 source 的最小请求就能执行 Node 脚本并拿到 stdout; 宿主旧契约不再被硬拒; 开发循环恢复轻快。
- M0.1 直跑模式 (direct-run):
runScript在缺少 workspace FD 时不再报错, 改为在插件私有目录直接执行 (自动建立工作目录, 路径映射恒等, 提交/回写自动跳过)。带 FD 时行为与原来完全一致。—PluginWorkspaceArchiveSession.openDirect+hasWorkspaceDescriptors分流。 - M0.2 契约宽容: 请求中缺失
contractVersion视为当前版本 (显式错误值仍拒绝); module-source-provider 接受 v1..v2, 缺失版本按 v1 处理, 并在与宿主 provider 往返时回显协商版本 (v1 宿主发 v1 请求, v1 响应归一化为 v2 语义)。— 单测 75 个全绿。 - M0.3 门禁下链:
check/ 常规构建不再依赖 capability-truth、runtime-ownership、resolver、nodejs-api publication 等验证门禁; 全部保留为手动任务 (verifyNode*系列), 需要时单独执行。—:app:check --dry-run已确认 0 引用。 - M0.4 构建验证:
:app:assembleDebug全 ABI 通过 (v1.1.3 build 41)。 - M0.5 真机烟雾验证: x86_64 模拟器 (API 36 与 API 37 各一台) 安装插件 APK, 最小请求 (仅
source, 无 FD/无契约字段) 跑通console.log, 断言 stdout 含m0.smoke=42, 约 0.9s 完成; 同机回归原 FD 路径 (CJS+ESM conformance x3d_02) 通过。承载测试:SimpleRunSmokeTest。 - M0.6 本 Roadmap.md 落库, 旧里程碑体系归档说明 (见文档头部)。
交付物: 可安装 APK + 通过的烟雾验证 + 本文档。
目标: 在真实 AutoJs6 App 里, 编辑器输入 "nodejs"; 脚本 → 点击运行 → 看到输出。
- M1.1 宿主侧联调: 用 master 分支 AutoJs6 (nodeFull flavor) + 本插件, 真机/模拟器跑通
sample/nodejs/hello-node。记录并修复联调中出现的每一个具体异常 (逐异常修复, 不做预防性改造)。— 2026-08-17 真机 (小米 Android 15 arm64) 插件 v1.1.3 + 宿主 v6.8.0: 宿主NodeExampleProjectInstrumentationTest7/7 (含 hello-node), 插件 conformance 24/24。修复 3 个异常: ① bootstrap 硬锁 config v2 → 宽容 v1..v2 并回显协商版本; ② conformance mock provider 不认 metadata preflight → not_found 回应 + 计数断言更新; ③ TS 剥离器字符串掩码用空格导致('cjs' as string)被剥成()→ 掩码改用非空白占位符 U+0001, 附回归单测。附加事实: 小米真机跑宿主 instrumentation 需先亮屏解锁并把宿主拉到前台一次, 否则 FGS 被拒、settle 超时。 - M1.2 契约对齐决策: 与宿主仓库同步
nodejs-api(以哪边为准做一次性对齐, 建议宿主升级到插件的 v2 AIDL 包, 或插件回落 v1); 移除releases/下 AAR 哈希锁对迭代的阻塞。— 2026-08-17 决策: 以插件 v2 为准, 宿主择期升级; 过渡期由插件 v1..v2 宽容层承接 (已真机验证)。依据: 两边 AIDL 内容一致; 宿主 v1 provider 对 v2 请求的拒绝响应 (version=1 + INVALID_REQUEST) 恰好触发插件的一次性降级重试, 桥是闭合的; 宿主升 v2 需要实现 v2 操作语义 (materialize_missing_plaintext 等), 不是换常量, 按"逐异常修复"原则留到宿主仓库联调时做。哈希锁阻塞已随:nodejs-api源码模块化移除: app 改用 project 依赖,assemble/check零锁引用 (dry-run 验证), 锁只留在手动发布任务 (verifyNodeJsApiPublication等)。 - M1.3 加密模块脚本联调 (宿主 provider v1 路径) 跑通。— 2026-08-17 真机: 宿主新增
pluginRuntimeDecryptsEncryptedModuleThroughHostV1Provider(AES 加密secret.cjs+ 宿主 v1NodeJsEncryptedModuleSourceProvider→ 插件 runtime 解密执行, 断言 decrypted_count=1, 一次性 v2→v1 降级协商生效), 与 live bridge 用例同类 2/2 通过。逐异常修复 2 个: ① 插件 engine-info 注入诊断把 workspace 映射预填误报为 "existing" → 新增withReplacedRuntimeModule保留真实来源 (host_broker); ② 宿主 bridge 测试仍断言旧 "working_directory" 标签 → 更新为 M0.2 后的 "exact_metadata_snapshot"。插件 conformance 24/24、宿主样例 7/7 回归通过。 - M1.4 项目级脚本 (project.json + 多文件 + node_modules) 通过工作区传输跑通。— 2026-08-17 真机: 宿主新增
pluginRuntimeRunsProjectWithNodeModulesThroughWorkspaceTransport(project.json + lib/helper.cjs + node_modules/demo-pkg → 插件 runtimerequire相对路径与裸包名均成功)。逐异常修复 1 个: 宿主NodeJsPluginWorkspaceArchiveTransport只打包请求显式命名的文件 (R4 免扫描原则), 项目里未列名的 lib/node_modules 到不了插件工作区且 v1 provider 无法按需物化明文 → 对带 project.json 标记的声明式项目目录做受限树遍历 (拒符号链接/特殊文件, 沿用 4096 文件 / 64MB 预算), 裸脚本路径保持零扫描。回归: bridge 3/3, 宿主样例 7/7。 - M1.5 失败路径可读: 联调中出现的错误信息能让用户看懂 (错误码 + 一句人话), 不再输出诊断键值对墙。— 2026-08-17 真机: 宿主新增
pluginRuntimeFailuresCarryReadableCodeAndMessage(throw / MODULE_NOT_FOUND / TSX 三类失败断言"码+一句话", 禁止键值墙与冗余前缀)。逐异常修复 3 个: ① 宿主引擎把整面 failure envelope 打进用户控制台 → envelope 只留 logcat, 控制台留 JS 栈 + 一行错误; ② 插件失败消息叠加 "plugin execution failed:" 样板前缀 → 直接用原始异常消息 (错误码走 KEY_ERROR_CODE); ③ TSX 等预派发失败被宿主 bridge 误判为 EXECUTION_LOST (零扫描 commit 校验缺席) → 宿主按commit_allowed=false+native_dispatch_started=false识别声明式预派发失败, 插件保持 TSX 拒绝先于工作区物化 (x3e 负例语义不变)。回归: 插件 conformance 24/24, bridge 4/4, 宿主样例 7/7, 冒烟通过。
目标: 常驻交互与长脚本可用, 接近本地 node foo.js 的手感。
- M2.1 stdout/stderr 流式回传 (脚本运行中即时输出, 不等结束)。— 2026-08-17 完成: AIDL 零改动 (复用
INodeJsRuntimeCallback.onEvent+ 既有 EVENT_STDOUT/EVENT_STDERR 常量, v1 事务号锁不受影响)。C++CapturingPipeReader在 fd/pipe 读取线程把原始 chunk tee 给进程级JavaOutputSink槽位 (新 JNInativeSetOutputStreamSink, 单活门禁保证 set→run→clear 无竞态); 流式 chunk 不受终态 4KB 截断上限约束, 长输出首次完整可达。服务端StreamingOutputSink增量 UTF-8 解码 (跨 chunk 多字节字符重组) 后即时onEvent; 流式生效时终态不再重复回放, fd 捕获不可用时自动回退旧行为; 无 callback 调用方行为完全不变。宿主NodeJsRuntimePluginBridge.runScript新增outputListener, 引擎把事件即时写 GlobalConsole, 终态按streamed_output_events标记跳过二次打印。验证: 新增StreamingOutputSmokeTest(脚本首行打印后 setTimeout 2s 再打印, 断言首个 stdout 事件早于 FINISHED ≥1s) 于 x86_64 API 37 模拟器 + 小米 arm64 Android 15 真机双通过; 插件 conformance 26/26; 宿主 bridge instrumentation 4/4 (真机 + 新插件 APK); 新增Utf8StreamDecoderTest4 用例; 全 ABI assembleDebug 通过。 - M2.2 协作式取消: 不重启进程即可停止脚本, 重启仅作兜底。— 2026-08-17 完成: 用 libnode 已导出的
node::Stop(Environment*, StopFlags)(dlsym, 与既有 embedder 符号同模式) 从 binder 线程停掉活跃事件循环。C++ 侧执行 id 标记的 stop scope (beginActiveScriptStopScope/registerActiveScriptEnvironment/requestActiveScriptStop): 服务端准入后开 scope, lifecycle 在 CreateEnvironment 成功后发布 Environment 指针, SpinEventLoop 返回或 FreeEnvironment 前清除; 环境未就绪时 stop 记为 pending 并在注册时立即派发; id 不匹配 (脚本已结束) 的取消直接拒绝, 杜绝停错下一个脚本。服务端cancelScript改为:requestCooperativeCancellation(标记 lease, 不关门) → native stop → 3s 宽限窗口内执行未释放才走原process_restart兜底 (同步卡死的脚本 node::Stop 停不了); 取消成功的结果统一改写为ERR_AUTOJS6_NODE_SCRIPT_CANCELLED+ 一句人话, 不再把 drain 后的 exit 0 误报成功。runtimeInfocancellationMode→cooperative_stop_with_process_restart_fallback。验证: 新增CooperativeCancelSmokeTest(setInterval 永驻脚本 → 首个流式输出到达后 cancel → 断言取消错误码 + 同 PID 复用跑下一脚本成功) 模拟器 + arm64 真机双通过; 全量 androidTest 27/27; gate 新增协作取消单测。 - M2.3 串行队列 (替代直接
BUSY拒绝)。— 2026-08-18 完成: 选串行队列而非真并发 — native 层embeddedProcessRuntimeExecutionMutex使执行天然串行 (每执行一个 fresh isolate, 但进程级互斥), 真并发需 native 大改, 与"先跑起来"原则冲突; 队列已消除用户可见的 BUSY 掉脚本问题。NodeRuntimeExecutionGate重写为 monitor + FIFO 等待队列 (容量 3):acquire(id, maxWaitMs)忙时在 binder 线程阻塞等待 (binder 线程池默认 15+, 占 4 无压力), release 直接把槽位交给队首; 满员/超时/排队中被取消各返回独立 outcome 与可读消息 (queue_full/wait_timeout/cancelled_while_queued); 等待预算 = 请求 KEY_TIMEOUT_MS, 未指定则 10min 上限。cancelScript先撤排队项 (无 native 交互) 再走 M2.2 协作停止; prewarm 保持非阻塞 tryAcquire 不排队。runtimeInfo: queueCapacity=3, queuedExecutions 快照。验证: 新增SerialQueueSmokeTest(3 线程同时提交 → 全部成功各含唯一标记, 无 BUSY) 模拟器 + arm64 真机通过; gate 单测 9 个 (FIFO 顺序/容量拒绝/等待超时/排队取消/协作取消); 全量 androidTest 28/28; 真机 M2 冒烟组 4/4。 - M2.4 npm 生态实测: 10 个高频纯 JS 包实跑。— 2026-08-18 完成: lodash / dayjs / ms / semver / uuid / debug / mime@3 / qs / js-yaml / ajv (含它们的 23 个传递依赖, 真实
npm install产物 1.3k 文件) 通过 workspace-archive 传输在插件 runtime 实跑, 每包一个核心行为断言全绿 (NpmEcosystemSmokeTest, 模拟器 + arm64 真机)。逐异常修复 3 个解析器缺口 (全部是 Node LOAD_AS_FILE 语义偏差): ① 相对 require 带"伪扩展名"被硬拒 (require('./util.inspect')应探 util.inspect.js, object-inspect 依赖) → 本地解析按 exact→+.js→…候选链走, 仅 TS/native/ESM 拒绝保持硬性; ② 包子路径同问题 (require('get-proto/Object.getPrototypeOf'), qs→side-channel 依赖链) → node_modules 子路径解析同改; ③ AutoJs6 compat shim 与 npm 包重名时 shim 胜出 (require('mime')返回 shim 而非安装的包) → 已安装 node_modules 包优先于 compat shim (桌面 Node 语义), Node builtin 与node:/autojs6:前缀不受影响, 无包安装时 shim 照常回答。axios/express 按计划延后 (需更多网络/流栈验证)。回归: 全量 androidTest 30/30。 - M2.5 长驻脚本生命周期管理与手动停止。— 2026-08-18 完成: 能力由 M2.1/M2.2 组合天然构成 (流式输出 = 长驻期间持续可见; 协作取消 = 手动停止; FIFO 队列 = 长驻期间后续脚本排队不丢), 本项收口为端到端生命周期验证: 新增
LongRunningLifecycleSmokeTest— 不带 timeout 字段的 setInterval 常驻脚本连续流出 ≥12 个 tick (~3s, 证明无隐式超时截断), 运行中getRuntimeInfo可观测 activeExecutionId/activeForMs,cancelScript停止后拿到 ERR_AUTOJS6_NODE_SCRIPT_CANCELLED, 同 PID 复用跑下一脚本。模拟器 + arm64 真机通过。注: 插件侧无超时即无限运行 (仅宿主 runBlocking 侧有 5min 默认 deadline, 属宿主策略, 宿主长驻模式 timeoutPolicy 独立管理); 断电/进程死亡后的自动重启明确不做 (checkpoint restartPolicy=never 保持)。 - M2.6 网络模块默认放开 (http/https/net/dns/tls)。— 2026-08-20 正式化: 插件端与宿主端均默认启用受支持的原生网络模块,不再接受构建期开关或旧请求键;白名单边界保持为 dns/dns/promises/http/https/net/tls,dgram 等未支持面仍明确拒绝。插件 manifest 包含
android.permission.INTERNET;NetworkDefaultOnSmokeTest覆盖无功能开关请求下的 http server + loopback 自请求。此前的临时 Gradle 属性已删除,不参与构建或宿主 AAR。
目标: Node 脚本里可用的宿主 API 覆盖日常自动化场景。
- M3.1 盘点 live bridge 现有可调用能力, 输出一页 "已可用 API 清单"。— 2026-08-18 完成: 清单落库
docs/HOST-API.md(五档分类: bridged 15 模块 / bridged-partial 7 / bridged-gated 8 / local-shim 15 / denied)。关键盘点结论: ① 可用面远大于预期 — M3.2 目标里的 toast/app.launch/click/text 查找/剪贴板/shell 全部已桥接, 唯一真缺口是 swipe/gesture (宿主 blockedMethods, 需独立 capability); ② 原定基线require("accessibility")样例的 SKIPPED 分支使其不能作真机证据, 真机验证矩阵单列一栏; ③ 宿主 getBrokerInfo 能力清单漏 lifecycle 模块 (policy 层单独补), 以文档清单为准。真机扩面验证: 宿主新增pluginRuntimeDrivesCommonAutomationApisThroughLiveBridge(一个脚本串调 toast.showToast + clipboard.setText/getText 回读 + storages.put/get 回读 + shell.exec echo + app.getAppName, 断言 7 次 live dispatch 全成功零失败), 真机 (小米 arm64 Android 15) bridge instrumentation 5/5。 - M3.2 补齐高频 API: toast / app.launch / click / swipe / text 查找 / 剪贴板 / shell。— 2026-08-18 完成: 除 swipe 外六项经 M3.1 盘点确认早已桥接并在 M3.1 用例中真机验证。swipe/gesture 缺口本项落地: 宿主
NodeBridgeProtocolaccessibility 新增 swipe(x1,y1,x2,y2,durationMs) 与 gesture(durationMs, [[x,y]...]) 派发 (复用GlobalActionAutomator→dispatchGesture同步等待完成, 时长上限 10s 防 binder 线程被长手势钉死), 从 registry blockedMethods 移出; 新增独立能力accessibility.gesture(registry gesturePolicy 要求), 插件 JS 预检与宿主 manifest 校验双侧都要求显式声明, 不被accessibility前缀隐含; 插件 accessibility shim 增加 swipe/gesture 方法。真机 (无障碍未开态):pluginRuntimeSwipesThroughAccessibilityGestureCapability断言可读 capabilityProviderMissing 失败 + 未声明能力本地拒绝零派发, 宿主 bridge 6/6; 服务开启下的完成路径待手工授权后补证 (小米 adb 不可写 secure settings)。插件 conformance 31/31 回归。HOST-API.md 已同步。 - M3.3 files / http 等与 Node 原生能力重叠的 API: 文档引导用 Node 原生实现, 不重复造桥。— 2026-08-18 完成: HOST-API.md 新增 "重叠能力选择指引" 一节 (fs/http/Buffer/npm 包 vs 对应 shim 与桥接版的取舍表, 含"仍需走桥"的边界: 设备能力与宿主身份场景)。无代码改动。
- M3.4
sample/nodejs收敛: 57 个登记样例按 "能跑/不能跑" 重新标注。— 2026-08-18 完成: 扫描全部样例的 require 依赖对照 M2/M3 现状,examples.json重标 11 条 — 升 stable 8 条 (http-client-compat/notifications/sensor-monitor/execution-queue: M2.6 网络默认开或桥已全 live 且样例自含; long-running-service: M2.5; scheduled-node-task: work_manager 全 live; database: M3.1 真机验证; fs-promises: M2.4), 降 partial 3 条 (screenshot-find-image: media_projection denied 只能走 skip 路径; disabled-features-demo: 依赖非默认实验开关; typescript-smoke: 触及 media_projection/rhino/java 门禁面)。未采用_pending/目录迁移:verifyNodeExamples门禁强制目录↔manifest 一一对应, 移目录会破坏它, 三态 status 标注已达成 "能跑/不能跑" 的表达目的。校验:verifyNodeExamples通过, 真机样例 instrumentation 7/7。
目标: 代码量与真实功能匹配, 新人可读。
M4 收尾盘点: C++ (不含 Node 头) 97.7k→51k 行 (扣除 43k 行内嵌运行时 JS 构建器后桥接核心 ~7.6k); gradle+js 验证体系 -13.3k 行; conformance androidTest 24→5 用例; 服务类 2667→693 行 + 四个职责单一的协作类; README 一页答清装/跑/查错。此后进入常态维护: 逐异常修复 + 冒烟组守护 (单测 + 12 个 androidTest)。2026-08-21 增补 M5 (宿主↔插件职责归位)。
- M4.1 删除 C++ probe 体系 (embedded_probe_* 全家, 191 值枚举, ~200 个 probe JNI 导出), 预期 C++ 从 ~83k 行降到 <15k 行。— 2026-08-18 完成: 先做双侧可达性勘察 (宿主仓 219 个 external fun 中生产路径仅 9 个, probe 分发器 runProbe 零调用方; 插件 Java 侧对 probe 零引用), 确认 probe JNI 全部是死代码后删除 ~217 个导出 (nativeEmbeddedProbe* 全家 + 5 个 legacy lifecycle 变体 + AdapterV1Diagnostics + 信号安全 crash marker)。lifecycle.cpp 20941→2075 行 (巨函数 30 参签名瘦身为 9 参 runEmbeddedScriptNodeLifecycle, 22 个 probe 选择器参数全是编译期常量); payload.cpp 5409→733; jni.cpp 4020→1366; validation.cpp (1568 行) 与 embedded_probe_* 四对文件整体删除; probe JS 源码 (sources.cpp 前 5.2k 行) 删除, 内嵌运行时 JS 构建器 (~43k 行, 真资产) 未动。C++ 总量 (不含 Node 头)
97.7k→51k 行, 扣除 JS 构建器后桥接核心 ~7.6k 行。验证: 全 ABI assembleDebug + JVM 单测 + 模拟器冒烟 (SimpleRun 3/3, StreamingOutput 1/1, CooperativeCancel 1/1)。 - M4.2 删除/归档 capability-truth、runtime-ownership、runtime-kit、conformance gradle (共 ~7k 行 gradle+js), 保留 runtime-build (libnode 构建脚本是真资产)。— 2026-08-18 完成: 删除 4 个 app 级验证 gradle (conformance 3271 行 / capability-truth 141 / runtime-ownership 52) 与配套 js 验证器 (capabilities/ownership/runtime-kit/resolver/project 五目录 ~5.6k 行)、根级 node-plugin-tools.gradle.kts; runtime-kit gradle 瘦身为仅生成 4 个 BuildConfig 字段 (getBrokerInfo/runtimeInfo 回显在用, 187→33 行), 其发布/验证任务链整体删除。共 -13.3k 行。保留: runtime-build (libnode 构建真资产)、ownership/evidence (历史证据存档, Roadmap 头部声明)、node-plugin-examples.gradle.kts (verifyNodePluginExamples 是 M3.4 样例门禁)、nodejs-api publication 手动任务 (M1.2 决策)。验证: assembleDebug + verifyNodePluginExamples + 单测全绿; :app:check 的 lintAnalyzeDebug 崩溃经基线比对确认是 AGP 9.0.1 既有 bug, 与本项无关。
- M4.3 conformance androidTest 收敛为 <10 个冒烟用例; 删除已无对应功能的用例。— 2026-08-18 完成: NodeRuntimePluginAndroidConformanceTest 24 用例删 19 留 5 (保留: x3d_01 runtimeInfo/预热进程、x3d_02 CJS+ESM 端到端、x3d_04 TSX 可读失败、x3e_05 corpus v2 七项兼容、x3f_13 provider v2 加密物化 — 每个守一条独立用户可见能力; 删除的 19 个是 TS 变体细分/工作区边界攻防/corpus v1/zlib/crypto 专项等已被冒烟组或单测覆盖的细粒度用例)。文件 2893→1696 行 (死 helper 与 corpus v1 常量迭代清理), corpus v1 资产目录删除。M2 起新增的 7 个冒烟类不动。验证: 模拟器全量 androidTest 12/12 (conformance 5 + 冒烟 7)。
- M4.4
NodeJsRuntimePluginService拆分瘦身 (2.3k 行 → 目标 <800 行)。— 2026-08-18 完成: 2667→693 行, 纯搬家零行为变化。四个同包协作类: NodePluginPayloads (820, 无状态 payload/bundle/binder helpers + procfs 诊断 + bridge 派发, 静态导入使调用点零改动)、NodeRuntimeModuleInjector (516, 运行时模块注入 + RuntimeModuleInjection/BridgeLimitPolicy, 持 Context)、NodePluginScriptExecution (419, runScriptActive 方法对象化)、NodePluginBundles (392, runtimeInfo/prewarm/result/failure 组装)。测试引用的静态成员 (prepareTypeScript* 系 / 契约版本 helpers / shouldCommitWorkspaceAfterFailure / Utf8StreamDecoder / procStatusLongValue 代理) 留在服务上; 死方法 normalizeWorkingDirectory 删除。验证: 单测 + 模拟器全量 androidTest 12/12 + arm64 真机冒烟 (裸跑+流式) 全绿。 - M4.5 文档一页化: README 里写清 "怎么装 / 怎么跑 / 出错了看哪里"。— 2026-08-18 完成: 走既有生成体系 (template_readme.md + 10 语言 lang_*.json + generate_markdown.py) 新增 "快速上手" 一节, 三条各答一问: 装 (Releases 按 ABI 下载或本地 assembleDebug + 插件中心启用)、跑 (
"nodejs";首行 + 桌面 Node 写法 + 流式输出/可停止)、错 (控制台 JS 栈 + 一行错误码, 深挖用adb logcat -s AutoJs6NodeBridge NodeJsRuntimePlugin, API 面查 docs/HOST-API.md)。features 里 M4.2 已删的 "Node 解析诊断工具和运行时构建计划校验工具" 描述同步改为 HOST-API.md 指引。全部 10 语言 README 重新生成。
目标: 宿主与插件对 Node.js 的职责边界清晰可述, 双份/错位代码归位删除, 新人按仓库就能读懂"谁管什么"。
职责共识 (归位基准, 2026-08-21 双仓实测勘察):
- 插件 = Node.js 运行时唯一归属: libnode + C++ 桥 + 内嵌 JS 运行时 (require 链 / 模块解析 / TS 剥离 / fs 策略 / 能力预检 JS 侧) + 运行时服务与执行队列 + nodejs-api 契约权威源 + sample 真值 + HOST-API.md (面向脚本作者的派生视图)。
- 宿主 = 能力提供方与桥客户端: 引擎路由与插件发现绑定 (~2.3k 行) + 能力派发与宿主侧预检 (~13.2k 行, 直接操作宿主进程内 Activity/无障碍/剪贴板, 实现必须留宿主) + 工作区打包传输与模块源 provider (~2.3k 行) + 面向用户文档 (docs/nodejs 顶层 .md 与 types/) + sample/nodejs 副本。
- 插件→宿主方向为空集: 插件 Java 14 文件 9,882 行零宿主进程内组件引用;
org.autojs.autojs.engine.NativeNodeEmbeddedRuntimeBridge的宿主包名是 JNI 符号约束 (改包名断 native 绑定), 非职责错位。宿主→插件方向以 删除宿主重复实现 为主 (插件已持权威实现), 仅个别工具/测试逐项判定回流。 - 宿主现存 node 生产 Kotlin 63 文件 58,619 行, 其中内嵌运行时层 33,954 行"有头无身" (宿主无 cpp/ 无 libnode.so, 仅 JNI 声明层; probe natives 已在 M4.1 从插件 .so 删除); androidTest 134 文件 74,866 行; node gradle 28 脚本 25,686 行 (几乎全手动); 阶段报告 520 份 ≈5.8M。
红线 (每项执行前重读):
- 宿主
.changelog/lang_zh-Hans.json有用户未提交改动, 全程不碰、不混入提交。 sample/nodejs(双仓 358 文件字节级一致) 与宿主docs/nodejs顶层 .md +types/是既有"保留"决策 — 用户可见资源, 不按重复文件删; 漂移靠verifyNodePluginExampleMirror(宿主app/node-examples.gradle.kts:387) 守。- 涉插件路径的宿主 gradle 任务必须显式传
-Pautojs.nodejs.plugin.root=D:\idea-projects\AutoJs6-Plugin-NodeJs-Runtime(两仓非兄弟目录, 默认探测必失败)。 - 插件仓当前有 fs 放开未提交改动 (
node_bridge_sources.cpp+AndroidManifest.xml), M5 宿主侧工作与其互不混合。 - 新增守卫一律手动任务, 不挂默认构建链 (延续 M0.3 原则); 不新增哈希锁。
计划执行顺序: M5.1 (防继续漂移) → M5.2/M5.3/M5.4 (零风险与低风险清理, 可并行/穿插) → M5.5 (结构解耦) → M5.6 (最大删除面) → M5.7 (打包链退役) → M5.8 (测试收敛, 依赖 M5.6) → M5.9 (收尾)。每项独立提交, 完成标准 = 该项 Check 全绿。实际执行时 M5.8 提前到 M5.6 之前, 先移除依赖内嵌类的测试再由编译器驱动删除生产层; 其余顺序不变。
- M5.1 契约单一权威源 (nodejs-api 漂移收口)。— 2026-08-21 完成并提交 (
d2b9cb156): 宿主 3 文件按插件版逐字节同步 (LF→CRLF, 含新增 src/test 契约单测 4/4); 宿主 provider 钉 v1 = 新增NodeRuntimeCapabilities.RUNTIME_MODULE_SOURCE_PROVIDER_CONTRACT_VERSION = 1(带"为何是 1"注释),NodeJsEncryptedModuleSourceProvider5 处 + androidTest 3 处改引它; 被 v2 契约移除的KEY_MODULE_SOURCE_PROVIDER_PROBE_MAX_COUNT降为宿主本地诊断键;NodeJsPluginActions.INFO改字面量后宿主模块顺带解除对 common-plugin-api 的依赖; 新增手动守卫:plugin-api:nodejs-api:verifyNodeJsApiMirror(行尾归一化逐文件比对, 10 文件验证通过)。Check 实绩: 双仓 diff 空 ✅; 加密模块用例pluginRuntimeDecryptsEncryptedModuleThroughHostV1Provider真机绿 ✅ (一次性 v2→v1 降级协商闭环保持); 桥类 6 用例 4 绿 2 失败, 该 2 失败经 stash 基线对照在未含改动的 HEAD 上逐字相同 (automation-API 的剪贴板回读与 swipe 的 PERMISSION_DENIED, 属设备环境既有问题, 非本项引入)。执行中修复的发现: 此前 6 用例"全绿"实为全部 Assume 跳过 — 设备装的插件 v1.1.3 (契约 v1) 被要求 v2 的宿主静默拒绝, probe 异常被 runCatching 吞掉; 换装当前源码构建的插件 v1.2.0 后用例才真实执行。教训: 跑桥用例前先核对插件契约版本, 且OK (N tests)亚秒完成 = 全跳过。事实: 宿主plugin-api/nodejs-api(settings.gradle.kts:102 挂载, app/build.gradle.kts:627 project 依赖) 与插件副本已实质漂移 —MODULE_SOURCE_PROVIDER_CONTRACT_VERSION宿主=1/插件=2; 插件多 MIN/MAX 常量 +supports*helpers + operation/status 键; 宿主多KEY_MODULE_SOURCE_PROVIDER_PROBE_MAX_COUNT;NodeJsPluginActions.INFO实现不同 (宿主引 common-plugin-api, 插件硬编码字面量)。动作: 以插件仓为权威, 宿主副本逐文件同步 (CRLF 归一化比对)。陷阱: 宿主 provider 的广告版本不得随共享常量升到 2 — 在宿主 provider 代码里显式钉 v1 (插件 v1..v2 宽容层承接, M1.2 决策), 除非同步实现 v2 操作语义 (materialize_missing_plaintext 等)。加一个双仓 nodejs-api src 内容比对的手动任务。Check: 双仓diff -r --strip-trailing-cr为空; 宿主NodeRuntimePluginBridgeInstrumentationTest全用例绿; 真机加密模块用例pluginRuntimeDecryptsEncryptedModuleThroughHostV1Provider绿。 - M5.2 能力声明收口与三方清单守卫 (原阶段1)。事实: 能力名三处登记且计数已互不相等 (= 漂移既成事实) — 宿主
NodeBridgePermissionManifest.kt48 条 (:76-124, 常量 :14-74) / 插件NodeBridgePermissionManifest.java57 常量 / 插件releases/nodejs-capability-catalog/1.2.0116 条; 宿主NodeBridgeProtocol.kt另散落 21 处点分能力字面量; 宿主对未知能力名只 warning 不阻断 (声明层有松耦合空间)。动作: ① 宿主 protocol 层 21 处字面量收敛到 manifest 常量; ② 建三方比对手动任务 (宿主 manifest ↔ 插件 manifest ↔ catalog, 差异出报告, 每条差异要么修复要么白名单注明理由); ③ 双侧预检是刻意设计 (HOST-API.md 第八节), 不合并; ④ 新增能力的登记顺序 (插件 cpp 声明 → 插件 manifest → 宿主 manifest → catalog) 写进 HOST-API.md。Check: 比对任务报告三方一致或全差异有注明; grep 宿主 node 生产代码点分能力字面量仅剩 manifest 定义处; 真机 accessibility.gesture 用例回归。 - M5.3 阶段产物清理 (原阶段2, 零风险先行)。事实: 宿主
docs/nodejs760 文件 8.9M, 其中reports/377 份 +phase{13,14,15,16}/143 份 = 520 份阶段报告 (≈5.8M);tools/nodejs268 文件 5.1M, 其中 phase*/r6/differential 等阶段脚本 232 份; 宿主tools/nodejs/runtime-build(7 文件, 含 libnode.exports.map) 与插件仓 runtime-build 双份。动作: 删 520 份报告与阶段工具脚本; runtime-build 先 diff — 插件侧为权威, 宿主侧若有较新内容先回流插件再删宿主份;design/48、releases/24、schemas/8、dual-engine-compat/18 等逐目录判定 (默认删, 被保留的顶层 .md 引用者留); 保留顶层 31 个 .md +types/61 文件。Check: 被删路径在宿主 gradle 与保留文档中零引用 (grep);:app:assembleAppDebug通过。 - M5.4 门禁 gradle 收敛 (原阶段3)。事实: 28 个 node gradle 脚本 25,686 行; 挂载点仅 app/build.gradle.kts :411/:1305/:1307 三处 apply,
node-gradle-scripts.gradle.kts聚合其余 24 个; 全部 verifyNode* 均为手动任务; 唯一默认构建链任务 =prepareNodeJsRuntimeSlotJniLibs→ preBuild (node-runtime-config.gradle.kts:467, :489-497)。动作: 删 phase10~16 gates、v1-1 alpha/beta/rc gates、r6-gate、embedded-node-packaging-preflight(4,545 行)、node-doctor-report、native-node-deps-report 等与内嵌体系绑定的 ~20 个脚本; 保留node-runtime-config(M5.7 再改造)、node-examples(镜像守卫)、node-build-tasks(逐任务判定);prepareNodeJsRuntimeSlotJniLibs本项不动。Check: apply 链无死引用;:app:assembleAppDebug+verifyNodePluginExampleMirror(显式传 plugin.root) 通过。 - M5.5 引擎路由解耦 (结构前置)。事实:
NodeJavaScriptEngineFactory.kt:20-22里 PLUGIN / PLUGIN_OPTIONAL backend 复用NativeNodeEmbeddedJavaScriptEngine(3,368 行) — 插件路径包在内嵌引擎壳里, 是内嵌层不可删的结构性耦合结;NodeExampleProjectInstrumentationTest经NodeEmbeddedTestHarness(136 行) 驱动而非直接走桥。动作: 新建独立NodePluginJavaScriptEngine, 只依赖桥客户端组 (NodeJsRuntimePluginHost/Bridge/Loader) 与传输组; PLUGIN 系 backend 切换到它; NodeEmbeddedTestHarness 改为桥驱动。Check: 宿主编辑器"nodejs";脚本真机经插件运行 (裸跑/流式/取消/项目脚本各抽 1); (i) 组 6 个桥测试类 +NodeExampleProjectInstrumentationTest7/7 绿。 - M5.6 内嵌运行时 Kotlin 删除 (原阶段5, 最大删除面)。事实: 14 文件 33,954 行 —
NativeNodeEmbeddedRuntimeBridge.kt19,041 /NativeNodeEmbeddedScriptService.kt5,805 /NativeNodeEmbeddedJavaScriptEngine.kt3,368 /NodeEmbeddedProcessSessionManager.kt1,774 /NativeNodeEmbeddedProjectRunner.kt1,426 /NativeNodeEmbeddedProbeService.kt1,201 / 其余 8 个 ≈1.3k, 外加INodeEmbeddedProcessControl.aidl; 宿主无 native 实现可链接, 属"有头无身"死层。附带逐项判定:NodeTypeScriptStripper.kt386 行 (插件 742 行版为权威; 查宿主 provider 明文物化是否引用 → 用则留, 不用则删);NodeDoctorReportGenerator.kt527 行 (诊断对象是内嵌运行时, 同删或改造为插件诊断);NodeRuntimeBackend枚举 EMBEDDED/NATIVE 态退役, PLUGIN 为 Node 默认 (rhinoOnly / NodeDisabled 路径保持);nodeFull/nodeMinireleaseFlavor 档位 (是 gradle property 非 flavor, 不控制任何 sourceSet) 映射到 plugin 行为保留档位名、或直接退役 — 执行时二选一并记录。动作: 沿用 M4.1 手法 (先全仓 grep 引用面 → 内容锚定脚本删除 → 编译器驱动清残留)。Check: 全仓NativeNodeEmbedded/NodeEmbedded生产代码零引用;:app:testDebugUnitTest绿 (node 相关 6 个 JVM 单测 233 行按存续调整);:app:assembleAppDebug全 ABI; 真机 (i) 组回归。 - M5.7 native 打包链退役。事实:
prepareNodeJsRuntimeSlotJniLibs(node-runtime-config.gradle.kts:467) 是唯一挂 preBuild 的 node 任务;isNodeJsRuntimePackagedInHost(:422) 为真时从插件仓拷 libnode.so 进宿主 APK。动作: M5.6 后宿主永不打包 libnode → 该任务与 runtimeSlot / pluginProjectDir 探测链退役;node-runtime-config瘦身为 backend BuildConfig 字段 (plugin/rhino 二态); jniLibs 只剩 4 个 libc++_shared.so 走常规打包。Check::app:assembleAppDebug产物 APK 无 libnode.so, 前后体积对比记录在案; 安装后"nodejs";脚本仍经插件运行。 - M5.8 androidTest 收敛 (原阶段4, 依赖 M5.6)。事实: 134 文件 74,866 行 — (i) 桥驱动真插件 6 文件 3,785 行 (保留, 宿主守护链); (ii) 内嵌内部行为 31 文件 67,932 行 (删, 含单文件 17,530 行的
EmbeddedNodePackagedApkSmokeTest.kt); (iii) 旧 conformance/probe/corpus 35 文件 16,391 行 (删); 其余 72 文件 25,749 行逐类判定 — 测宿主派发/能力层的留 (必要时改桥驱动), 测内嵌行为的删; 插件缺失的高价值覆盖可逐用例回流插件仓, 默认不迁 (延续 M4.3 收敛哲学); fixture assets 252 个随用例清理; JVM 单测 6 文件 233 行按 M5.6 存续调整。Check: 宿主 androidTest 全量编译通过; (i) 组 + 保留的能力桥用例真机绿; 插件仓 12 个 androidTest 不受影响。 - M5.9 收尾: 盘点与文档对齐。动作: 前后行数盘点落库 (预期宿主 node 生产 Kotlin ~58.6k → ~25k, gradle ~25.7k → <2k, androidTest 只留有效面); 保留的 docs/nodejs 顶层 .md 中指向已删体系的章节更新或标注过时 (TESTING.md 235K / CI_GATES.md 108K / SECURITY_MODEL.md 109K 大概率大面积失效); HOST-API.md 增补 M5.2 的能力登记顺序; 本 Roadmap 勾选并记录执行偏差。Check: 保留文档无死链死引用 (抽查); 宿主 README / 设置页涉 Node 描述与 plugin-only 现实一致。
| 项 | 宿主提交 | 插件提交 | 结果 |
|---|---|---|---|
| M5.1 | d2b9cb156 |
— | 契约镜像 10 文件一致, 宿主 provider 显式钉 v1 |
| M5.2 | c3988836b |
6c9920a, 7730822 |
宿主/插件 manifest 各 48 条; catalog 47 条, 仅 accessibility.gesture 一条带原因历史例外 |
| M5.3 | 07f947efe |
— | 520 份阶段报告及 232 份阶段工具脚本退役 |
| M5.4 | 2f54cbd67 |
— | Node Gradle 脚本收敛为 4 文件, 保留任务均为手动任务 |
| M5.5 | 5ef2c6a56 |
— | 独立 NodePluginJavaScriptEngine 与通用 request/result 落地 |
| M5.8 | b98f1b84c |
— | 先删内嵌/probe 测试面, 保留桥与宿主派发测试 |
| M5.6 | 5240ce2d8 |
— | 宿主内嵌 Kotlin/JNI 声明、服务、进程池、probe 与 AIDL 清零 |
| M5.7 | 23b1b7fd6 |
— | runtime slot/native loader/preBuild 拷贝链退役; nodeFull/nodeMini 明确拒绝 |
| M5.9 | 3e4f2c548 |
本文件收尾提交 | 文档、诊断、测试命名、指标与最终验证收口 |
统一 wc -l 口径的前后盘点:
| 面 | M5 前 | M5 后 | 变化 |
|---|---|---|---|
| 宿主 Node 命名生产源码 | 77 文件 / 60,041 行 | 61 文件 / 25,959 行 | -34,082 行 (-56.8%) |
| Node Gradle/约定插件 | 27 文件 / 20,309 行 | 4 文件 / 1,624 行 | -18,685 行 (-92.0%) |
| Node androidTest | 134 文件 / 74,866 行 | 37 文件 / 16,364 行 | -58,502 行 (-78.1%) |
| Node JVM test | 6 文件 / 233 行 | 4 文件 / 157 行 | -76 行 |
终态证据:
- 宿主无
app/src/main/cpp, 无NativeNodeEmbedded*/NodeEmbedded*生产类引用;app/src/main/jniLibs仅 4 ABI 的libc++_shared.so。最终 universal APK 含 12 个常规.so, Node.so= 0。 - M5.7 同一构建条件的 APK 前后均为 43,663,670 bytes, delta = 0 (插件模式本已不打包 libnode); M5.9 全量重组产物为 46,804,197 bytes, SHA-256
9DC6DDCC756FBC3C4948F28556D6431843C25FDB687F810BEA4B5FFAFB6D9A5F, 仍为 Node.so= 0。 docs/nodejs终态为顶层 32 文件 / 298,464 bytes +types/61 文件 / 283,299 bytes; 21 份当前指南本地链接审计零断链, 11 份 R2–R6/旧路线图类材料均标记为历史快照。sample/nodejs双仓各 358 文件,verifyNodePluginExampleMirror字节比对通过;verifyNodeExamples、11 个 project-wizard 模板及类型声明守卫通过。- 离线链: nodejs-api 镜像、能力三方对齐、样例镜像、主源码、androidTest、JVM 单测、universal APK 全绿。
- 真机
968e9f18, 插件 v1.2.0:NodeRuntimePluginBridgeInstrumentationTest6/6、NodeR6EngineSwitchInstrumentationTest2/2、NodeExampleProjectInstrumentationTest7/7、NodeR6RequiredPluginSecurityInstrumentationTest1/1, 合计 16/16 真实执行通过。 - 有意保留的兼容名仅限插件已发布的
work_managerwire tokenbackend="embedded"与embedded_script.*诊断键; 它们不表示宿主持有运行时。
终态 (已达成): 宿主 node 面 = 桥客户端 + 派发能力层 + 传输 provider + 文档样例, 25,959 行; 内嵌运行时 0 行; 契约/能力/样例三类跨仓一致性各有手动守卫可查。验证链恒为: 宿主 JVM 单测 + :app:assembleAppDebug + 真插件桥冒烟; 插件侧未改动时无需重跑插件链。
M0~M5 完成后对全仓四面 (C++ 桥 / Java 服务层 / 样例与发布链 / 提交前沿) 的勘察结论:
核心能力已站稳: 真实 Node 24.5.0 内嵌、CJS/ESM/npm 纯 JS 包、流式输出、协作取消、串行队列、长驻脚本、网络默认开、live bridge 21+ 模块、fs 桌面级放开 (d5703d1)。日常自动化脚本场景基本闭环。
二次勘察时的三条战线 (历史基线; M6/M7 执行后已修正):
- TypeScript 的“生产端缺位”判断已被跨仓核对纠正: 单看 Node Runtime 仓时,
8e08b3b的 fail-closed 与错误文案确实像一条断链; 但宿主仓已在0938deed2→ebbf1b8d2系列提交中实现完整消费链, 相邻仓AutoJs6-Plugin-TypeScript-Engine也已形成 v0.6.0 / TypeScript 6.0.3 正式候选。M7.1~M7.3 与 M7.5 已据此验收, 仅 legacy stripping 的发布观察期仍开放。 - fs 放开收尾已由 M6.2/M6.4 完成: API 37 真服务进程覆盖 workspace 外写读删与
/proc/sys/dev负例, README/HOST-API/catalog 已同步;filesystemRoots明确裁定为兼容诊断元数据。 - M5 收官欠账已由 M6.1/M6.5 完成: catalog/runtime-kit 1.3.0、48=48=48 零例外、十语言 1.1.0/1.2.0 CHANGELOG、构建噪音与悬空文档均已收账。
服务层三个实缺口 (2026-08-25 勘察时, 已由 M8.1~M8.3 全部收账):
KEY_TIMEOUT_MS名不副实 — 只作队列等待预算, 脚本执行本身无 wall-clock 超时; 死循环脚本永久占据唯一执行槽 → 3 个排队者依次WAIT_TIMEOUT→ 后续请求全部QUEUE_FULL, 只能人工cancelScript。宿主 5min deadline 到期也不会停掉插件侧脚本。- 取消兜底升级路径 (3s 宽限 → gate 永久关门 →
Process.killProcess) 是最危险的代码路径却零自动化证据。 KEY_EXECUTION_MODE/KEY_RUNTIME_ADAPTER是契约死键 (main 源码零读取), checkpoint 门禁被 engine-info 旁路架空, 裸请求路径恒 false。
能力面缺口 (按用户价值排序): dgram/UDP 完全缺失 (无 facade, 设备发现/组播类脚本不可行); npm 生态第二批未收账 (axios/express 自 M2.4 延后至今; ESM 自实现层 realEsmCorpus: partial_required); package_manager registry 设备端下载 deferred; inspector 调试面三重封锁 (kNoCreateInspector, devtools deferred); V8 启动快照禁用 (disabled-until-snapshot-batch); trace_events 隐式缺失 (不在任何名单, 报错体验不一致); WASI deferred (2 个样例 design-gated)。
发布链: Node 24.17.0 (lts-security, 2026-06 发布) 晋级被上游 Android 产物阻塞 (node2417Promotion: deferred, 5 项前置全未动); runtime-kit 1.2.0 自报 releaseReady: false (blockedReasons 全指向 24.17 与容器 digest 未钉); runtime-build.lock.json 含本机绝对路径且其 sha256 已入 kit 信任链。
已知但不立项 (逐异常修复原则, 未造成用户可见问题): processHandler 挂主线程 Looper; commitWorkspaceQuietly 异常路径双调 (靠 AtomicBoolean 兜住); broker/provider 关闭阶段 RemoteException 静默; prewarm 失败无退避; 未知能力名只告警不阻断; node_bridge_sources.cpp 单文件 43.7k 行 (JS 以 raw string 维护); desktop-parity-suite 二级清单不受门禁保护; unsupported 样例状态零使用; resource 指标只采不控。异常真实发生时再逐项修复。
- 验证一律本地/离线优先 (网络环境易触发 Cloudflare 502/524/529, 尤其 524): gradle 一律带
--offline(依赖已在本地缓存); C++ 改动先用 NDK clang-fsyntax-only离线语法校验 (手法见 fs 放开时的实践:clang++.exe -fsyntax-only -std=c++20 --target=aarch64-linux-android24 -I. -Inode-v24.5.0/include/node ..., 宏列表按现状调整) 再进构建; androidTest 走本地模拟器 (x86_64) / USB 真机, 不依赖外网。全部 M6~M10 中仅两处允许联网且单独标注: M9.2 corpus 制备 (开发机一次性, 可走镜像源)、M10.1 上游版本复查 (手动)。 sample/nodejs(含examples.json) 仅在插件仓维护, 任何改动由插件侧verifyNodePluginExamples校验; 宿主不再保留样例镜像。- README/CHANGELOG 只改
.readme/与.changelog/的 lang JSON 及模板, 经.python/generate_markdown.py生成, 不直接编辑产物 .md; 生成时被顺带重写但无实质变化的文件用 git checkout 还原。 - 契约 (nodejs-api) 改动延续 M0.2 宽容原则: 新键缺失有默认、旧键不破坏、AIDL 事务号零改动优先; 插件仓作为权威源, 由
verifyNodeHostApiMirror反向校验宿主编译镜像。 - 延续既有红线: 不新增 probe/哈希锁类基础设施; 新守卫一律手动任务不挂默认构建链; 宿主仓用户未提交改动不碰。
计划执行顺序: M6 (全离线, 最快清欠账) → M7 与 M8 可并行 (互无依赖) → M9 → M10 按条件成熟推进。每项独立提交, 完成标准 = 该项 Check 全绿。
目标: 仓库自述与代码现实一致 — fs 放开 / TS fail-closed / M5 收官三条战线的文档、样例、发布物欠账全部清零。
- M6.1 仓库卫生小项打包: ①
version.properties构建噪音 (BUILD 56→57) 随本项提交收编; ②PADDLE_OCR_*三键确认零引用后删除 (宿主仓继承残留); ③ build-logic 插件 IDorg.autojs.build.local-arr-register-convention拼写修正为local-aar-...(当前零 apply 引用, 零风险); ④tools/nodejs/runtime-build/README.md:23悬空任务引用改指build-node-runtime.sh/.ps1的 plan 档 (verify-runtime-build-plan.js本体仍在)。Check: 全仓 grep 悬空任务名与 PADDLE_OCR 零命中;:app:assembleDebug --offline通过。— 2026-08-25 完成: BUILD 57 收编、三项 Paddle 残留删除、插件 ID 与 runtime-build 文档修正; PowerShell plan 输出 Node 24.17 目标/24.5 当前版本与 3 ABI, 离线 assembleDebug 67 tasks 通过。后续 M8 验证构建按项目既有自动递增规则将当前工作树推进至 BUILD 58, 无需回退。 - M6.2 fs 放开收尾: ① 新增
UnrestrictedFsSmokeTest— workspace 外路径 (如/sdcard/Download) 写→读回断言, 模拟器经adb shell appops set ... MANAGE_EXTERNAL_STORAGE allow自动授权; ②/proc/sys/dev拦截保持的负例断言 (放开模式下唯一硬边界); ③filesystemRoots元数据裁定 (采集了但零消费): 删除解析或注明"仅诊断元数据", 二选一记录于此。Check: 新冒烟用例模拟器绿;:app:testDebugUnitTest --offline全绿。— 2026-08-25 完成: 保留filesystemRoots作为兼容的纯诊断元数据, 明确其不授予/扩大/收窄 fs 权限; API 37 x86_64 模拟器真实服务进程完成/sdcard/Download写读删及三敏感根负例 1/1, JVM 单测与 androidTest 编译全绿。 - M6.3 样例状态复核 (双仓同步): ①
disabled-features-demo期望输出与现状脱节 (child_process/worker_threads 已默认启用, 样例仍断言被禁) — 改造为显式传 false 的开关演示或更新期望, 裁定记录; ②sandboxed-scriptstable + design-gated 标注矛盾裁定 (其余 12 条 design-gated 全是 partial/disabled); ③ 5 条 TS 标签样例按 fail-closed 现状重标 (其中 4 条为 raw TS, 编译器缺位期间实际不可跑, M7 闭环后再升回); ④ 3 条 fs 面 partial 样例 (filehandle-advanced/fs-watch/compile-cache) 按放开后现状复核; ⑤examples.json为全部非 stable 条目补一行reason字段 (机器可读的"为什么不能跑", 现散落三处),verifyNodePluginExamples加存在性校验 (轻量, 仅查非 stable 有 reason)。Check:verifyNodePluginExamples --offline通过; 宿主verifyNodePluginExampleMirror通过 (--offline + plugin.root)。— 2026-08-25 完成: disabled-features-demo 改为验证当前默认开放面, sandboxed-script 转 disabled, 4 个 raw TS 转 disabled、typescript-smoke 保持 partial, filehandle-advanced/fs-watch 升 stable、compile-cache 保持 partial; M6 阶段分布 stable 23 / partial 23 / disabled 11, 34 个非 stable reason 全覆盖; M7.5 收账后当前分布为 stable 28 / partial 22 / disabled 7。插件门禁与宿主 358 文件字节镜像门禁均通过。 - M6.4 用户文档同步 (10 语言生成体系): ① README features 与快速上手补 fs 权限模式 (插件独立 uid、装后需手动授予"所有文件访问"、不授予时报 EACCES 属预期) 与 TS 现状 (需编译器, 迁移期 legacy 开关); ② CHANGELOG 补 1.1.0 与 1.2.0 条目 (M1~M5 用户可见变更: 流式输出/协作取消/串行队列/npm 实测/网络默认开/swipe/契约收口/fs 放开/TS fail-closed); ③ HOST-API.md 增补 "fs 访问模式" 与 "TypeScript 编译要求" 两节。Check:
generate_markdown.py全 10 语言生成无报错; 抽查 zh-Hans 与 en 两份内容正确; 无关文件 git checkout 还原后工作区仅含预期改动。— 2026-08-25 完成: 10 份语言源补齐 fs/TS 能力与快速上手, 10 语言 CHANGELOG 补发 v1.1.0/v1.2.0, HOST-API 明确 Android 权限边界、敏感根、诊断元数据与宿主编译责任; 生成器全量成功并抽查中英文产物。 - M6.5 catalog 1.3.0 发布 (本地发布物, 无联网): ①
accessibility.gesture补入bridge.permissionCapabilities, 删除守卫历史例外; ② features 增补 fs 访问模式条目、修订 TypeScript 策略条目; ③ runtime-kit 同步引用新 catalog, 顺带清理runtime-build.lock.json的androidFork.localPath本机绝对路径 — 注意 lock 的 sha256 被 kit 的 buildProvenance 引用, 两文件必须同一提交联动更新; ④ 终态三方对齐: 插件 manifest 48 = 宿主 manifest 48 = catalog 48。Check: 宿主:app:verifyNodeCapabilityManifestAlignment --offline三方一致且零白名单例外; 插件:app:assembleDebug --offline(runtime-kit BuildConfig 回显) 通过。— 2026-08-25 完成: 发布 catalog/runtime-kit 1.3.0, 补 gesture/swipe operation 与 48th capability、fs/TS 策略和 TS 新错误码; 清除本机路径并联动更新三段 SHA-256, hashed JSON 统一 LF 以跨平台复现; 宿主守卫为 48=48=48、documentedDifferences=0, 插件 APK 内两份资产哈希与 release lock 完全一致, assembleDebug 通过并回显 kit 1.3.0。
目标: TS 从"默认不可用"回到一条端到端用户能力 — 编辑器 .ts 脚本一键运行, 报错栈指向 .ts 原始行号。涉宿主仓, 红线照旧。
- M7.1 编译器落点决策 (一次性, 同 M1.2 模式): 候选 ① 独立 TypeScript Compiler 插件 APK (错误文案的既有方向, 架构最干净, 工程量最大); ② 宿主借插件 Node 自举编译 — typescript npm 预置为资产, 编译请求本身作为一次插件 runtime 执行 (跑 tsc API), 产物 js + source map 回宿主后再派发真正执行, 零新仓库 (建议先做一次可行性 spike: 插件跑 tsc 编译 hello.ts 的耗时与内存); ③ 插件内嵌编译 (与 8e08b3b "插件退出 TS 转译业务"方向冲突, 仅作对照)。决策与依据记录写入本文件。— 2026-08-25 完成并纠正勘察误判: 采用候选①, 但无需新建工程 — 相邻仓
AutoJs6-Plugin-TypeScript-Engine已存在, 当前正式候选为 v0.6.0 / TypeScript 6.0.3, 使用官方完整Program编译而非 transpile-only; 宿主0938deed2起已有公开 Binder client。候选②会重复已完成的独立编译服务且把编译与执行生命周期重新耦合, 不再 spike; 候选③继续否决。 - M7.2 编译链路端到端: .ts 入口 → 编译产物 →
typeScriptPrecompiledSnapshot+typeScriptPrecompiledSourceNames请求键 (3f1b3b1 已备好消费端) → 插件执行; 覆盖单文件、多文件项目、动态 import (.ts 说明符经快照映射, 含 missing/ambiguous 负例)。Check: 宿主模拟器/真机用例 — TS hello + 多文件项目 + 动态 import 三例全绿; 插件 conformance x3d_06/07 回归。— 2026-08-25 完成: 宿主0ae1ec30e/622bfddcc/ebbf1b8d2已分别交付 Node 预编译、多文件项目与封闭动态映射; TypeScript Engine Roadmap 保存 API 31/35/37 的聚焦通过证据。当前插件源码的 x3d_06/07 在 API 37 回归 2/2; 仓库原样的 CJS、ESM、project、packaged-dynamic 四例经宿主→Compiler 0.6.0→Node Runtime 在同一目录各连续执行两次, 8/8 PASS。实跑发现并修复宿主 workspace v2 把虚拟 compilermoduleSources回写成main.cjs/main.mjs、导致复跑冲突的问题: 仅运行前不存在的 module-source 覆盖被标为 ephemeral, 输出快照不再物化它们; 原有真实支持文件和脚本其他输出仍同步。新增策略单测 1/1, 主应用离线构建安装通过, 四个目录复跑后文件清单与原始输入完全一致。 - M7.3 栈帧回映: 宿主组合编译器 source map 与插件已归一化的栈位置基线 (61f3a36/92f3be6), TS 脚本 throw 时控制台栈指向 .ts 文件与原始行号 (M1.5 "码+一句话"风格保持)。Check: 用例断言栈文本含
.ts:与正确行号。— 2026-08-25 完成: 宿主TypeScriptSourceMapTest7/7 离线通过, 覆盖 entry/imported 模块与相对路径唯一映射; TypeScript Engine S4-1 的三设备证据精确回映lib/fail.ts:3:11与main.ts:2:5, 生成的fail.js不泄漏。Node Runtime 的61f3a36/92f3be6继续作为生成行偏移与 imported CJS 帧归一化基线。 - M7.4 legacy 剥离器退役: 新链路稳定后删除
NodeTypeScriptStripper(~800 行) 及其单测; 删除KEY_LEGACY_TYPESCRIPT_STRIPPING_ENABLED; conformance x3d_04/05 断言同步。Check::app:testDebugUnitTest --offline全绿; grep 零 stripper 生产引用。— 2026-08-29 完成: 直接删除 802 行正则 erasure、专属 JVM 兼容测试和 provider 私有prepare_plaintext_typescript二次准备协议, 宿主与两仓 nodejs-api 源码镜像同步删除请求键。运行时改为单一 JavaScript-output admission policy;入口、预加载模块、provider 解密明文以及 native 直达路径遇到.ts/.mts/.cts均返回ERR_AUTOJS6_TYPESCRIPT_COMPILER_REQUIRED, snapshot / provider v3 按需编译仍可读取原始源码但只有编译后的.js/.mjs/.cjs能进入执行。完整离线 JVM/构建/镜像/样例门禁通过;Android 9/12/15 三台真机各跑 conformance 10/10, 合计 30/30。releases/**/1.3.0与 APK 中随附的 1.3.0 catalog/runtime-kit 是已发布元数据快照, 保持不可变;其中遗留字段没有生产消费者, 其版本化刷新留给下一次 catalog/runtime-kit 发布,不构成可调用的 stripping 路径。 - M7.5 样例收账 (双仓同步): 5 个 TypeScript-tag 样例 (其中 4 个为可执行 raw TS 项目) 接新链路升 stable, expected-output/项目元数据更新; packaged-typescript 走打包与动态 import 路径验证。Check:
verifyNodePluginExamples+ 宿主镜像守卫通过; 设备至少抽 2 例实跑绿。— 2026-08-25 完成: typescript-cjs/typescript-esm/typescript-project/packaged-typescript 与声明元数据 smoke 全部升 stable, README/project.json 明确需 Compiler 0.6.0+ 且 raw 直派仍 fail-closed; 57 例当前分布 stable 28 / partial 22 / disabled 7, 29 个非 stable reason 全覆盖。插件样例门禁与宿主 358 文件字节镜像门禁通过; API 37 对 4 个可执行样例做同目录双跑 8/8 PASS, packaged 例真实输出packaged:dynamic, 且零编译产物泄漏。
目标: 失控脚本不再需要人工干预; 契约键名实相符。
- M8.1 脚本执行 wall-clock 超时:
KEY_TIMEOUT_MS从"仅队列等待预算"扩展为"等待+执行总预算" (或拆双键, 设计时定, 注意宿主现有传值语义不破坏): 超时触发既有requestCooperativeCancellation→node::Stop路径 (基础设施已完备, 只差 watchdog 触发器), 结果置KEY_TIMED_OUT=true+ 专用错误码一句话; 未指定 timeout 保持无限运行 (M2.5 长驻语义不变)。宿主侧配套: runBlocking deadline 放弃前先发cancelScript(涉宿主仓)。Check: watchdog 单测; androidTest — 死循环脚本 + timeout 3s 得到超时错误且同 PID 复用下一脚本;LongRunningLifecycleSmokeTest回归确认无 timeout 行为不变。— 2026-08-25 完成: 采用既有单键作为 Binder 入口起算的 queue + preparation + native execution 总预算,<=0仍不限制脚本执行、无显式预算的队列仅保留原 10 分钟安全上限; 不改 contract version/AIDL/已发布 nodejs-api 1.2.0。执行租约由布尔位升级为ACTIVE/CANCELLED/TIMED_OUT/COMPLETED原子仲裁, 消除完成/人工取消/watchdog 的末端竞态, 队列 deadline 同时改为饱和加法。预算耗尽统一返回timedOut=true、ERR_AUTOJS6_SCRIPT_TIMEOUT与阶段诊断, active watchdog 先发node::Stop, 3 秒未释放再沿既有进程重启兜底。宿主NodeJsRuntimePluginHost已先于本项具备timeout+5sBinder 响应兜底及超时后有界cancelScript, 无需重复实现; 当前宿主 main Kotlin 编译与 nodejs-api 镜像门禁通过。JVM gate/deadline 14/14;while(true)3 秒超时 + 同 PID 后继复用在 API 28/36/37 模拟器与 3 台真机 6/6, 队列预算同矩阵 6/6;LongRunningLifecycleSmokeTest与CooperativeCancelSmokeTest各 6/6, 证明无 timeout 长驻与人工取消语义未回归。 - M8.2 取消兜底升级路径最小回归: 构造协作停止停不掉的夹具 (候选:
Atomics.wait阻塞主线程; 若实测while(true)已足够停不掉则用之并记录), 断言 3s 宽限后process_restart兜底生效、错误码可读、进程重启后可服务下一请求。Check: 新 androidTest 模拟器绿 (可标记慢用例, 不入高频冒烟组)。— 2026-08-25 完成:Atomics.wait、execFileSync与无握手 FIFO 的首轮试验都会在真正进入不可中断调用前被node::Stop正常终止, 不能冒充兜底证据; 终态CancellationRestartFallbackSmokeTest使用私有 cache FIFO + ready 文件握手 + 500ms 稳定窗, 取消前断言 Binder 调用仍未完成, 从而可靠阻塞在同步readFileSync系统调用。六设备矩阵 (API 28/36/37 模拟器 + Android 9/12/15 三台真机) 6/6 观察到 3s 协作宽限后 runtime-onlyProcess.killProcess, Binder death 不早于 2.75s, 重绑 PID 必须变化且后继脚本输出 42。进程被杀时底层 AIDL 无法再返回结果 Bundle, 因而可读错误由宿主负责:NodeJsRuntimePluginHost把已派发事务的 transport loss 包为dispatchStarted=true,NodeJsRuntimePluginBridge归一化为failure_kind=execution_lost、fallback_safe=false、ERR_AUTOJS6_NODE_PLUGIN_EXECUTION_LOST; 新增纯分类单测 2/2 离线通过。该慢用例保持聚焦执行, 不并入高频冒烟组。 - M8.3 契约死键裁定: ①
KEY_EXECUTION_MODE接线到 lifecycle-config (替代 engine-info 旁路), 使interactive_long_running请求能真实开启 checkpoint 门 —restartPolicy=never与"进程死亡不自动重启"决策不变, checkpoint 价值 = 长驻脚本主动存进度、重启后自读恢复; ②KEY_RUNTIME_ADAPTER零消费 → 契约标 deprecated 或删除, 按宽容原则处理。Check: 契约单测更新 (宿主镜像同步); grep main 源码死键零残留; checkpoint 门在显式 executionMode 下可开的单测。— 2026-08-25 完成: lifecycle config 现在以 BundleKEY_EXECUTION_MODE为权威, 仅在缺键时兼容回退engine-info, 两者均缺失才落one_shot; 无engine-info的显式interactive_long_running请求推导interactive_session, 而宿主 live checkpoint 派发仍独立执行 mode + launch-surface 授权。KEY_RUNTIME_ADAPTER为保持 contract-v2 字面兼容而保留并标@Deprecatedno-op, 宿主请求模型、wire 写入与插件 conformance 伪填充全部删除; C++embedded_script.runtime_adapter.*仅是内部 adapter 诊断, 与废弃请求键无关。验证: lifecycle 纯策略单测 4/4; 两仓契约单测各 7/7, 10 文件镜像守卫通过; 精确 grep 显示宿主 main 对 runtimeAdapter 零建模/发送、插件 app main 已真实读取 executionMode;ExecutionModeLifecycleSmokeTest在 API 28/36/37 模拟器与 Android 9/12/15 三真机 6/6, 断言 checkpoint=true、automaticRestart=false、restartPolicy=never; 宿主 main Kotlin 离线编译通过。
目标: 每项一条用户可见能力, 按需求频度排序。
- M9.1 dgram (UDP) 放开: denylist 移除, 并入
rawNodeNetworkModulesEnabled辖区 (M2.6 网络默认开的自然延伸, manifest 已有 INTERNET); 顺带把trace_events从隐式缺失改为显式 denylist (给清晰的ERR_AUTOJS6_BUILTIN_DISABLED)。C++ 改动先 NDK clang-fsyntax-only离线校验。Check: androidTest UDP 回环 echo (createSocket/bind/send/message) 模拟器绿; trace_events require 得到清晰错误码; 新样例 udp-discovery (双仓同步) 过门禁。— 2026-08-25 完成:dgram/node:dgram并入默认开启的 raw-network builtin 路由,module.isBuiltin、module.builtinModules、require.resolve、profile 与禁用请求负例同步; 同轮把生态依赖实际需要的http2纳入相同网络边界,trace_events则转为明确 denylist。DgramUdpSmokeTest在 API 37 x86_64 模拟器完成 UDP4 loopback bind/send/message/reply, 并断言关闭 raw-network 时 dgram/http2 可读拒绝、trace_events 始终返回ERR_AUTOJS6_BUILTIN_DISABLED;udp-discovery样例已双仓镜像且过样例门禁。 - M9.2 npm 生态第二批: axios + express (M2.4 明言延后, 收账) + 2~3 个 ESM-only 真实包 (顺带收
realEsmCorpus: partial_required的账)。corpus 在开发机一次性npm install制备 (唯一联网步骤, 可走 npmmirror 镜像避 Cloudflare), 产物进 androidTest assets, 设备端离线实跑。Check:NpmEcosystemSmokeTest扩展 — axios loopback 自请求、express 起服务自访问、ESM 包 import 断言, 全绿。— 2026-08-25 完成: 真实锁定的 npm-install corpus 从 10 包扩到 15 包, 新增 axios 1.19.0、express 5.2.1、nanoid 6.0.1、p-limit 7.3.1、yocto-queue 1.2.2 及其传递依赖; 设备端全程离线, axios/express 各用 localhost HTTP 自服务验证完整网络栈, 三个 ESM-only 包用动态 import 验证 exports/条件解析。实跑暴露并修复 packageexports数组 fallback 解析以及 http2 builtin 路由两个兼容缺口;NpmEcosystemSmokeTest在 Android 9/12/15 三台 arm64 真机与 API 36/37 x86_64 模拟器矩阵 6/6 通过,realEsmCorpus欠账关闭。 - M9.3 registry 设备端下载评估 (
registryDownload: deferred收账): 先出一页决策 — 范围 (纯 JS 包 + 生命周期脚本维持 denied)、网络策略 (归入宿主 network 能力声明)、镜像源可配置; 决策通过再实施package_manager.install端到端。Check: 决策记录入本文件; 若实施, package-install 样例升级 + 真机跑通一例真实小包下载安装 (此步涉外网, 单独手动触发, 不入常规验证链)。— 2026-08-25 评估完成, 决策为暂不实施设备端 registry 下载: 当前package_manager.install/update继续只消费宿主管理、已落盘且可验证的本地包, 这是能力收账而不是暗中开放网络。允许实施前必须同时具备 ① 仅纯 JS 包且 install/preinstall/postinstall 等生命周期脚本永久 denied, ② registry/mirror 显式 allowlist 与 HTTPS/重定向/SSRF 策略, ③ 宿主network能力声明和每次安装用户可见授权, ④ tar 路径穿越/符号链接/解压炸弹防护, ⑤ 单包/文件数/总字节/依赖深度与时间配额, ⑥ lockfile、完整性哈希及依赖图确定性, ⑦ 下载/解析/提交全链取消与原子回滚。现有 facade 没有这些边界, 为一个已有宿主离线解包替代方案的功能引入供应链攻击面收益不成立; 因而不升级 package-install 样例,registryDownload: deferred保持为有理由的产品决策。
- M10.1 Node 24.5.0 → 24.17.0 (lts-security) 晋级: 被上游 Android 产物阻塞 (
node2417Promotion: deferred, nodejs-mobile 24.17 port 不存在; runtime-kitreleaseReady: false同源)。动作: 每月手动复查上游一次 (联网, 单独触发); 长期无产物则评估自建容器源码构建 (现sourceBuild: bootstrap_only, 需先钉容器 digest)。Check (晋级时): 3 ABI libnode.so 产出且 sha256/buildId 落 lock; 插件全量冒烟组回归; runtime-kitreleaseReady转 true。— 2026-08-25 已按月度动作复查: 上游 degaso/nodejs-mobile releases 最新仍为v24.5.0-r1, 全部分支 也没有 24.17 port/产物; Node 官方 24.17.0 已发布但不能替代 Android libnode。阻塞条件未变, 本项保持未勾选; 不以未经钉定容器与三 ABI 验证的自建产物冒充晋级。 - M10.2 inspector 本地调试档位: 现为 Environment 级三重封锁 (
kNoCreateInspector等)。分解: ① 安全边界决策 (debug 构建限定 + 显式请求键双门 + 仅 localhost + adb forward;sensitivePathRedaction: not_proven一并裁定); ② native 条件解锁; ③ 端到端 chrome://inspect 连插件进程断点调试。Check: debug 构建 devtools 可连且断点命中; release 构建三重封锁不变 (负例); inspector-debug/cpu-profile/heap-snapshot 三样例按落地面重标。— 2026-08-25 完成: 新增 contract-v2inspectorEnabled请求键, 宿主只在自身 Debug 构建发送, 插件再以BuildConfig.DEBUG和 nativeAUTOJS6_NODE_DEBUG_BUILD双重裁剪; Release 三 ABI 构建实证宏恒为 0, 继续设置kNoCreateInspector, Debug 显式开启才移除该位并声明kOwnsInspector, 且始终保留 no-start-signal/no-wait。JS 只暴露受控Session/console/open/close/url,open强制 127.0.0.1、拒绝非本机 host 与wait=true, 默认请求仍返回ERR_AUTOJS6_BUILTIN_DISABLED; 为兼容 Node inspector 的惰性初始化, 原生模块在 process facade 冻结前预载。InspectorDebugSmokeTest在 API 37 x86_64 模拟器用真实 WebSocket/CDP 完成 Runtime.enable、Debugger.enable、断点暂停与恢复, 同时验证 CPU Profiler profile 与 Runtime heap usage; 文档明确 adb forward、无敏感路径/值脱敏及仅限本地受信调试。inspector-debug/cpu-profile/heap-snapshot 双仓样例由 disabled 改为 partial: 前两者可用, heap snapshot 的有界导出仍未实现。公共 API 以向后兼容的常量增量发布nodejs-api:1.3.0(AIDL transaction hash 保持不变), runtime-kit 1.3.0 同步钉定新 AAR SHA-256, 手动 publication 门禁通过。 - M10.3 冷启动优化评估: V8 startup snapshot 现禁用 (
disabled-until-snapshot-batch)。先测量常驻进程复用下冷启动的真实占比与耗时分布; 若冷启动 <1s 且频率低, 记录"不值得做"结论并关闭本项 (合法完成态); 否则再立实施项。Check: 测量数据与结论记录入本文件。— 2026-08-25 完成评估, 结论为当前不值得实现自定义 startup snapshot。新增RuntimeColdStartMeasurementTest: 每台设备先 force-stop, 将专用进程 bind + service 同步预热单独计时, 再在同一常驻 PID 内连续执行 21 个 fresh isolate (首轮 + 20 个 warm 样本), 记录 wall/native total 及 isolate/environment/bootstrap/script 分相。Android 15/12/9 三台 arm64 真机的 bind+首次执行分别为 403/362/661ms, warm fresh-isolate wall median/P95 分别为 121/135、157/166、361/404ms; API 37 x86_64 模拟器为 bind+首次 1767ms、warm median/P95 228/396ms, 其 1065ms 一次性 bind/预热成本不属于每次 isolate snapshot 的主要收益。四设备 80 个 warm 样本 P95 均远低于 1s, process runtime 全程复用且执行频率受单槽串行模型约束; 预期收益不足以抵消 snapshot 生成、ABI/Node 版本耦合和发布验证成本, 保持disabled-until-snapshot-batch, 有新实机证据跨过阈值时再重开。
M0~M10 收账后, 对插件仓 master (c369c8c, v1.2.0 build 66) 与宿主仓 (d38871887) 做第三次全面勘察。方法: 逐文件核对 C++ 内嵌运行时 (node_bridge_sources.cpp 44,115 行 + 其余 7.5k 行)、Java 服务层 (13 文件 9,190 行)、AIDL 契约、宿主 NodeBridgeProtocol.kt (8,260 行) 的 dispatch 表、样例清单 (58 条: stable 29 / partial 25 / disabled 4)、发布物与工程规范 (D:/idea-projects/AUTOJS6_PLUGIN_NEW_REPO_AGENTS.md)。
结论一句话: 核心能力已站稳并闭环 (真实 Node 24.5.0 / CJS+ESM 原生 linker / npm 15 包 / 流式 / 协作取消+超时 / 串行队列 / 长驻 / 网络默认开 / fs 桌面式放开 / TS 宿主编译链 / live bridge 31 模块 / debug inspector), 但离 "接近桌面体验 + 覆盖日常自动化" 的初衷仍有五类实质缺口, 且 1.1.0/1.2.0 两个版本的全部成果尚未对用户发布。
五类缺口 (按用户价值排序):
- 屏幕与图像链路整体缺席 — 宿主
dispatchMediaProjection(NodeBridgeProtocol.kt:1951-1962) 与dispatchImage除 readImage/recycle 外 (:1964-1979) 一律返回 capabilityProviderMissing;recorder.start/stop同 (:2355-2370)。这不是结构性不可能: 宿主自身具备 ScreenCapturer + OpenCV, 且 OCR/barcode 已能消费 image handle (:1985-2007)。截屏/找图/找色/OCR 是自动化脚本最高频能力, 当前 Node 脚本完全用不上, screenshot-find-image / ocr-automation / pro-parity screenshot-ocr 三样例只能 skip。 - 桌面 Node 保真度被 "limited facade" 层拖累 — 几乎每个 builtin 都经
__autojs6_limited_*白名单子集包装 (如stream只导出枚举成员, 缺一个即报 "allowlisted module 'stream' is unavailable",node_bridge_sources.cpp:34980-35005); 全局fetch被桥接版替换 (:3462) 走宿主 OkHttp 并要求network声明, 与 "raw http 默认开" 自相矛盾;worker_threads策略 maxWorkers=1 / taskTimeout 5s / 64MB / 仅 11 个 builtin (:3871-3913);process.stdin是永不产出数据的空桩 (:2586);node:sqlite/wasi/cluster/repl不可用 (:3600-3675)。这层 4.4 万行 JS 是最大维护面, 也是 npm 包 "在桌面能跑、在插件报 unavailable" 的根源。 - 桥传输是 10 ms 文件轮询 — JS 写请求 JSON 文件 → Java 线程每 10 ms 扫目录 (
PluginNodeBridgeFileTransportSession.java:40,174-190) → Binder → 回写响应文件 → JS 每 10 msreadFileSync重试 (node_bridge_sources.cpp:6857-6889)。单次桥调用延迟地板 10~30 ms, 事件类模块 (sensors/ui/ui.overlay/websocket/input_observer) 全靠drainEvents拉取。并有一处确定的长驻缺陷: 会话内seen文件名列表与responseJsonValues无上限增长 (:206-210, :303), 结束时全部响应 JSON 序列化进 native payload (:329-341) — 高频桥调用的长驻脚本内存线性增长 + O(n²) 扫描 + 巨型终态 payload。 - 单执行槽 —
NodeRuntimeExecutionGate单槽 + FIFO 3 (QUEUE_CAPACITY = 3, :17), native 全局互斥;runScript同步阻塞 Binder 线程直到脚本结束 (INodeJsRuntimePlugin.aidl)。用户可见: "一个常驻服务脚本 + 一个临时脚本" 无法同时运行 (multi-instance 样例 partial)。 - 工程与发布欠账 — GitHub 仅有 v1.0.0 (2026-07-16),
origin/master停在 a8ce1ce (07-16), 本地 master 领先 67 提交 (1.1.0/1.2.0 全部成果未推送、未打 tag、无 Release); CHANGELOG/README 缺 M8~M10 用户可见能力 (超时 / dgram+http2 / axios+express / inspector / executionMode 零提及); 无.githubCI、无AGENTS.md、无THIRD_PARTY_NOTICES.md;generate_markdown.py无--check; Manifest 缺 Wake Activity 激活协议与allowBackup=false;settings.gradle.kts:7,13仍用mavenLocal()+ 旧 idorg.autojs.build.platform-versions1.4.1 并提交了gradle/data/9 个消费端覆盖文件 (组织规范 MUST: 在线io.github.supermonster003.autojs6-platform-versions1.7.4, 禁 mavenLocal, 禁 gradle/data)。
已核实的正面事实 (不立项): 3 ABI libnode.so 与 libautojs6-node.so PT_LOAD 对齐均为 0x4000 (16 KB 就绪, ELF 层面); Release APK arm64 26 MB / universal 79 MB (libnode 压缩率好, useLegacyPackaging=true 抽取后安装占用约 +110 MB, 属可接受取舍); RSS/Threads 指标已采集 (NodePluginPayloads.java:195-196); Rhino 兼容选择器链 (text().findOne() 等) 已在插件侧实现并映射到 accessibility 描述符; 宿主 Bun 运行时插件 (b07a09890) 的 AIDL 形态承袭本插件 (getRuntimeInfo/runScript/cancelScript/prewarmRuntime 同名, 另把 getInfo 并入同一接口, 回调为 oneway), 本契约已成为宿主 "运行时插件" 的模板。
宿主端仍未桥接给 Node 的 Rhino 能力 (供 M14/M15 取材): images 捕获与全部分析方法、media_projection、recorder 录音、floaty (ui.overlay 仍为 POC p14_08_provider_poc, NodeBridgeProtocol.kt:887)、events 观察者 (通知/toast/按键真源)、device 信息面 (现仅 5 方法 :679, 无 width/height/density/brightness/battery)、app 扩展方法 (intent/openUrl/uninstall 等)、dialogs 高级形态、keys 全局动作 (powerDialog 等)、RootAutomator/Shizuku、web (WebView)。threads/timers/http/crypto/files 属 Node 原生更优, 不桥接。
- 延续 M6
M10 约定 15 (离线优先 / 样例仅插件仓 / 文案走生成器 / 契约 additive / 红线)。 - 对外动作需用户确认: push、打 tag、创建 GitHub Release、删除远端分支、发布 catalog/runtime-kit, 一律在执行前列出将要发生的事并等待明确同意; 一次同意只覆盖当次动作。
- 能力新增五处同步: 插件 cpp 声明 → 插件 manifest → 宿主 manifest → catalog (HOST-API 第十一节顺序) 之外, 再加
docs/nodejs/types/autojs6-node/*.d.ts与docs/HOST-API.md表格; 缺任一处不算完成。 - 保真度改动以 corpus 说话: 触碰
__autojs6_limited_*或 require 链的改动, 完成标准固定为NpmEcosystemSmokeTest+NodeRuntimePluginAndroidConformanceTest全绿, 不接受 "理论上等价"。 - 每项独立提交, 完成标准 = 该项 Check 全绿; 涉宿主仓的项在宿主仓独立提交并把提交号记回本文件。
- 版本名称按实际情况调整: Roadmap 中的 v1.1.0/v1.2.0 等为规划参考, 可依据实际版本历史合理变更 (2026-09-08 用户明确补充)。
计划执行顺序: M11 (12 个工作日, 全离线, 让已完成的价值真正到用户手里) → M12.1 (确定缺陷, 半天) → M13 与 M14 并行 (M13 纯插件仓; M14 双仓) → M12.212.3 → M15 → M16 → M17 按上游与资源推进。
目标: 用户能装到 1.2.0; 仓库自述与组织规范一致; 后续每次改动有 CI 守护。
- M11.1 文档欠账清零: ①
.changelog/lang_*.json的v1.2.0补 M8.1 (脚本 wall-clock 超时ERR_AUTOJS6_SCRIPT_TIMEOUT)、M8.3 (executionMode权威化 +runtimeAdapter废弃)、M9.1 (dgram/http2 默认开, trace_events 明确拒绝)、M9.2 (axios/express + 3 个 ESM-only 包)、M10.2 (debug-only 本地 inspector) 五条; ②.readme/lang_*.jsonfeatures 补超时/UDP/调试三点; ③.python/generate_markdown.py增加--check只读校验模式 (组织规范 11.1) 并提供check_markdown.bat; ④ 全 10 语言重新生成。Check:py .python/generate_markdown.py --check零漂移; grep 10 份 CHANGELOG 均含dgram与inspector; 无关文件 git checkout 还原后工作区仅含预期改动。 — 2026-09-08 完成: 十语言补齐五项历史能力与三项 README 功能, 重新生成 35 份文档/应用内说明; --check 与 Windows 入口零漂移。生成器回归 2/2 覆盖 CRLF、缺失/过期输出、退出码及内容/mtime 全程只读; 十份 CHANGELOG 均含 dgram/inspector。 - M11.2 构建平台对齐 (组织规范 5.1 MUST): ①
settings.gradle.kts删除mavenLocal(), 插件 id 改为io.github.supermonster003.autojs6-platform-versionsversion1.7.4(以D:/idea-projects/AutoJs6-Gradle-Platform-Versions/version.properties当时值为准并确认已发布); ② 删除gradle/data/全部 9 个消费端覆盖文件与.bak/*.pre-platform-versions.bak; ③version.properties移除仅为中央下界重复声明的MIN_SUPPORTED_*键 (保留 compileSdk/targetSdk/minSdk/Java 与OVERRIDDEN_*=NONE); ④ 把 feature 分支feature/mediainfo-snapshot-v2-contract上 09323e6 的同类清理意图在 master 重做 (该分支 cpp 改动与 master ccd69fb 逐字相同, 无需合并)。Check:.\gradlew.bat --no-daemon '-Djava.vendor=Eclipse Adoptium' '-Djava.vendor.version=Temurin-21.0.12.1+1' :app:assembleDebug :app:testDebugUnitTest通过且日志仅一段Version information for IDE platform and Gradle plugins; grep 全仓无agpVersionMap/mavenLocal/gradle/data。 — 2026-09-08 完成: 使用已发布且缓存可用的公共平台插件 1.7.4, 移除本地仓库、9 份消费端覆盖、2 份迁移备份和 5 个重复 MIN_SUPPORTED_* 键。Temurin 参数的完整离线 assembleDebug + testDebugUnitTest 通过, 平台决策日志恰一段; 当前本地不存在原 feature 分支, 不做无依据合并。 - M11.3 AGENTS.md + CI 基线: ① 新建根
AGENTS.md(按AUTOJS6_PLUGIN_NEW_REPO_AGENTS.md裁剪为本仓真实约束: 身份字段、验证链:app:testDebugUnitTest+ 12 个 androidTest 冒烟组 + 真机 SimpleRunSmokeTest、离线原则、NDK clang-fsyntax-only手法、LFS 二进制、红线与 "不做" 清单、本 Roadmap 为唯一路线图); ②.github/workflows/build.yml: push/PR/手动触发, JDK Temurin 21, Gradle 缓存,testDebugUnitTest+assembleDebug+assembleDebugAndroidTest。LFS 带宽约束: 3 个libnode.so共约 326 MB, GitHub LFS 免费带宽 1 GB/月, 不能每次 push 都lfs: true拉取 — 单元测试 job 用lfs: false(不需要 .so), 打包/模拟器 job 以actions/cache按.gitattributes中 LFS oid 缓存对象且只在手动触发或 tag 时运行, 并在 job 内断言 jniLibs 下的 .so 不是 LFS 指针文件 (否则会把 130 字节指针打进 APK 而构建 "成功"); 模拟器冒烟 (API 36 x86_64,SimpleRunSmokeTest+StreamingOutputSmokeTest+NodeRuntimePluginAndroidConformanceTest) 作为独立 job, 允许workflow_dispatch手动触发以控时长; ③.github/workflows/markdown.yml(Windows,check_markdown.bat)。Check: 两条 workflow 在 GitHub 首次运行全绿 (推送需 M11.5 用户确认); 本地act或等价 dry-run 不作要求。 — 2026-09-08 完成: 本仓 AGENTS、Windows 文档 workflow 与按 unit/package/emulator 拆分的 Android workflow 已落地。LFS 缓存键取 git lfs ls-files 的真实 oid (.gitattributes 不含 oid), 打包前检查 ELF 魔数; push/PR 不下载原生库, 打包只在手动/tag 触发, 模拟器消费打包 job 产物。actionlint 与 Bash 语法检查通过; Windows 文档 CI 验证 35 份文档无漂移与生成器回归 2/2; push JVM CI 70/70; 手动 Android CI unit/package/emulator 三 job 全绿, API36 x86_64 实跑 SimpleRun + Streaming + conformance 11 项, 合计 13/13。 - M11.4 Manifest 激活协议与安全默认 (组织规范 6/17): ① 新增
WakeActivity(Theme.NoDisplay, exported,org.autojs.permission.PLUGIN, actionorg.autojs.plugin.action.WAKE, 立即 finish) 与org.autojs.plugin.WAKE_ACTIVITYmeta-data; ②android:allowBackup="false"; ③ 新增 androidTestPluginManifestContractTest(Wake Activity / INFO 与 RUNTIME 服务的 exported+permission+action+category /requiresHostVersion) 与PluginInfoContractTest(supportedAbis恰为 3 ABI, 版本来自 PackageInfo, capabilities 含契约版本)。Check: 两个新用例模拟器绿; 有 ColorOS 类设备时实测插件中心 "激活" 按钮, 否则在本文件记录 "未执行真实设备激活验证"。 — 2026-09-08 完成: WakeActivity/元数据/权限/DEFAULT category 与 allowBackup=false 落地; PluginInfo 版本取已安装 PackageInfo, 补齐本地化描述与 @raw 使用说明。两项新契约测试在 API 36 16 KB x86_64 AVD 与小米 arm64 真机各 2/2; 同轮 12 类冒烟 + conformance 11 项各通过, 每设备共 25/25。未执行真实设备激活验证 (本轮没有 ColorOS 类设备), 不将 Manifest 测试视为插件中心按钮实测。 - M11.5 发布 1.2.0 (对外动作, 需用户确认): ① 确认
VERSION_NAME=1.2.0、VERSION_BUILD=git rev-list --count HEAD; ②:app:appendDigestToReleasedFiles产出 4 个带 CRC32 的已签名 APK, 逐个zipalign -c -P 16 -v 4校验并安装冒烟 (arm64 真机 + x86_64 模拟器); ③ 推送 master (对 origin/master 为 fast-forward), 按实际版本历史创建v1.2.0tag, 创建 GitHub Release (说明取 CHANGELOG-zh-Hans/en 对应节); ④ feature 分支feature/mediainfo-snapshot-v2-contract在 M11.2 吸收后删除本地与远端。Check:gh release view v1.2.0列出 4 个 APK 且 CRC32 与文件一致;git status --short为空;origin/master == master。 — 2026-09-08 完成: 用户明确批准本次 v1.2.0 发布并允许按实际情况调整版本名。master 的 74 个待推送提交已 fast-forward 同步, v1.2.0 注释标签指向 a7c1dd654d490286da68fa64450bfd414d5acb4e; 该提交 VERSION_BUILD=105 与提交数一致。两个旧候选 03734c9/2e762b5 实际均为 VERSION_NAME=1.1.3, 本次不补写错配的 v1.1.0 标签; 原 feature 分支本地与远端均不存在。四份 build105 签名 APK 经 apksigner、zipalign -c -P 16 -v 4、版本/ABI/ELF/许可证核验, arm64 小米 API35、armv7 Sony G8441 API28、x86_64 16KB API36 AVD、universal 小米各通过 SimpleRun/NpmEcosystem/Info/Manifest 4/4, 合计 16/16。收集任务已修复实际输出目录与签名/原生库检查, 配套 Release 测试包解决 AGP 依赖扣除与 R8 裁剪冲突。GitHub Release v1.2.0 于 2026-09-08 12:27 CST 正式公开并设为 latest, 附件恰好四份, GitHub 返回的大小与 SHA-256 逐一等于本地实测包; CRC32 为 arm64 08C05B3A / armv7 0D180A10 / x86_64 BC90135B / universal 89E6B200。中英说明取生成 CHANGELOG 对应节; 发布后以独立文档提交回填验收记录, 保留 v1.2.0 标签及 build105 发布物。 - M11.6 第三方声明与 16 KB 实证 (组织规范 5.5/17): ① 新建
THIRD_PARTY_NOTICES.md: Node.js (MIT) 及 libnode 静态链入的 V8 / ICU / OpenSSL / zlib / libuv / c-ares / nghttp2 / simdjson 等许可证, libnode 来源 degaso/nodejs-mobilev24.5.0-r1与runtime-build.lock.json中的 sha256,libc++_shared.so来自 NDK; ② 16 KB: 记录 3 ABIlibnode.so与libautojs6-node.soPT_LOAD 对齐 0x4000 的核验命令与结果 (本次勘察已用llvm-readelf -lW确认), 说明useLegacyPackaging=true下 zip 对齐不适用的裁定; 在PAGE_SIZE=16384的 x86_64 AVD (API 36) 跑SimpleRunSmokeTest+NpmEcosystemSmokeTest。Check: 文件存在且 README 许可证徽章一致; 16 KB AVD 两用例绿, 或记录阻塞原因 (如 AVD 镜像不可用) 与 arm64 未实证的事实, 不夸大为 "全面支持"。 — 2026-09-08 完成: THIRD_PARTY_NOTICES 与 APK 内完整 Node/fork、NDK LLVM 许可证落库 (首次从固定上游 commit 取许可, 构建/设备验证离线)。NDK r28c llvm-readelf -lW 核验: arm64/x86_64 的 node/bridge/libc++ 均 0x4000; armeabi-v7a 的 libnode=0x4000、bridge/libc++=0x1000, 更正此前“三 ABI 全部 16 KB”的推断, 不对 32 位作 16 KB 声明。API 36 x86_64 AVD 实读 PAGE_SIZE=16384, SimpleRun + 15 包 NpmEcosystem 与其余用例合计 25/25; 小米 API 35 arm64 4 KB 同组 25/25。arm64 的 16 KB 环境未实证。完整矩阵与命令见 THIRD_PARTY_NOTICES。 - M11.7 样例与类型声明卫生: ① 10 个文档型/阶段遗留样例逐条裁定 — capability-truth-report / crash-evidence-bundle / adapter-cutover-status / debug-hot-reload / security-corpus / hardened-sandbox / sandboxed-script / multi-instance / startup-snapshot / provider-health: 无可运行能力者删除 (
verifyNodePluginExamples要求目录↔manifest 一致, 同步删examples.json条目), 仅保留能真实演示的 (provider-health 若只打印元数据也删); ②examples.json清理phase7~phase13历史标签; ③docs/nodejs/types/autojs6-node/62 文件对照 HOST-API:media_projection.d.ts/recorder.d.ts/image.d.ts等 denied 面加@deprecated/@remarks 尚未提供 provider说明, 等 M14 落地再去掉。Check:verifyNodePluginExamples+typeCheckNodeTypescriptSmoke通过; 样例数与三态分布记录于此。 — 2026-09-08 完成: 逐项检查上述十例入口, 均为硬编码状态/数组或 design-gated 文本, 全部删除并同步 manifest; 清除阶段标签, 既有 example 元数据检查改按元数据存在性执行。image/media_projection/recorder 的未提供方法补弃用说明, 保留实际可用入口。verifyNodePluginExamples 与 typeCheckNodeTypescriptSmoke 离线通过; 当前 48 例 = stable 28 / partial 18 / disabled 2。
目标: 高频桥调用不再有 10 ms 级地板, 长驻脚本跑一天内存不涨。
-
M12.1 桥会话诊断有界化 (确定缺陷, 先修): 事实:
PluginNodeBridgeFileTransportSession.java的seen(:61,206-210) 为ArrayList且只增不减、containsO(n);responseJsonValues(:62,303) 保存全部响应,bridgeResponsesJsonSnapshot()(:329-341) 在终态把它们全部塞进 native payload。动作:seen改为请求文件删除后即移除 (或有界LinkedHashSet上限 256); 响应记录改环形缓冲 (最近 32 条 + 总计数/失败计数), 终态 payload 只带摘要与最近 N 条。Check: 新增 JVM 单测 — 模拟 10,000 次请求/响应后两集合大小 ≤ 上限、payload 长度恒定;LongRunningLifecycleSmokeTest增一条断言embedded_script.bridge_live_responses_json长度 < 64 KB。 — 2026-09-08 完成: 调试器在真实文件桥处理 96 次请求后观察到 pending=0、seen=96、responses=96, 证实完成后仍全部保留。请求去重改 HashSet 并在成功删除请求文件后释放; 文件存在性检查与删除/释放共用锁, 避免扫描快照中的旧文件再次派发。BridgeSessionHistory 只保留最近 32 条, 每条至多 1536 UTF-8 字节, 数组上限 49185 字节; 大响应只截断诊断副本, 调用结果原文照常交付, 原总计数/失败计数继续累计。JVM 72/72, 新增两用例覆盖 10,000 次请求清理、恒定尾部长度、80 KB 响应及多字节边界。真实文件桥 96 次完成后保留请求=0、响应=32; LongRunningLifecycle 增真实 Binder 桥 96 次调用与终态 <64 KiB 断言。小米 arm64 API35 与 16 KB x86_64 API36 AVD 各通过文件桥/长驻/最小脚本 3/3, 取消后 PID 复用。IDE 与离线 Gradle 构建通过; 十语言新建 v1.3.0 未发布条目, 35 份文档无漂移。 2026-09-09 Release 补验: 首次混淆回归在文件桥测试中出现 NoSuchMethodError; R8 usage 证实仅测试调用的四参数构造器和 start() 已被裁剪。测试改从公开 Binder runScript 强制选择 file, 真实执行 96 次 device 调用后断言 transport=file、总数=96、保留请求=0、响应=32、诊断 <64 KiB, 不为内部测试入口增加 keep 规则。小米 arm64 API35、Sony G8441 armv7 API28、x86_64 API36 / 16 KB AVD 配套 Release 测试均通过该用例 (桥接全类各 6/6); Release 非 debuggable, 本轮依据异常栈与混淆产物定位, 没有把 Debug 结果当作 Release 证据。 -
M12.2 桥传输去文件化 (JNI 直通): 事实: 双向 10 ms 轮询 (
PluginNodeBridgeFileTransportSession.java:40,174-190;node_bridge_sources.cpp:6805-6809,6857-6889), 每次调用还在 JS 主线程做同步 fs。动作: 新增 native binding__autojs6_bridge_native_post(requestJson)(V8 函数, JNI 调 JavahostBroker.dispatch), 响应经uv_async_t唤醒事件循环后 resolve 对应 Promise; 文件传输保留为回退 (autojs6:bridge-live-config加transport: "jni" | "file", 默认 jni, 失败自动降级); pending 上限沿用 32/128。C++ 改动先 NDK clang-fsyntax-only离线校验。Check: 新增BridgeLatencySmokeTest— 200 次device.isScreenOn往返, 记录 P50/P95 (目标 P50 < 2 ms, 现约 20 ms), 数据写入本文件;NpmEcosystemSmokeTest+ conformance 11/11 回归; 强制transport: "file"时用例仍绿。 — 2026-09-08 完成: 默认 JNI/Binder 直通, UTF-8 byte[] 保真; uv_async_t 在 Node 线程整批交付响应, 无文件/轮询。请求及响应队列沿用 32/128 上限, 重复/超时/取消/跨执行迟到响应丢弃, 关闭前释放 V8 句柄及 loop 引用。配置 transport=file 保留原协议, JNI 接受请求前不可用才自动回退, 已派发错误不重放。三 ABI NDK clang 离线语法检查与 Debug/混淆 Release 构建通过, JVM 72/72; npm 15 包 + conformance 11/11 在三 ABI 全绿。BridgeLatencySmokeTest 覆盖两通道各 200 次、32 并发、Unicode/NUL、重复响应、超时后跨脚本迟到响应及 PID 复用; arm64/x86_64 各 5/5 (含长驻与最小脚本), armv7 合计 16/16 (含 corpus/conformance)。实测 P50/P95 (ms, JNI 对 file): 小米 arm64 API35 Debug 0.523/0.606 对 11.188/22.226; 16 KB x86_64 API36 AVD 3.737/9.479 对 12.844/26.326; Sony API28 armv7 4.333/7.445 对 26.642/40.743。P50<2ms 目标在 arm64 达成, AVD 与旧 armv7 未达, 不宣称所有设备均低于 2ms。arm64 混淆 Release 配套测试 3/3, JNI 0.296/0.345 对 file 11.631/22.613; 十语言与 HOST-API 同步, 35 份生成文档无漂移。 2026-09-09 进程池回归修正: Node 24.21 候选的 x86_64 Release 完整组中, BridgeLatencySmokeTest 的同进程复用断言实际得到 PID 3980 与 3977; Android am_proc_start 证实分别为 nodejs_runtime1 与 nodejs_runtime0, 属于两个存活 worker。该组通道关闭/迟到回复/FD 基线检查改为绑定 NodeJsRuntimeSlot0Service, 明确验证同一 worker 的连续执行, 保留 PID 相等、超时、Unicode 和 FD 增长断言; 公共调度与双进程准入实现未改。修正后 Release 桥组在三台真机各 5/5, x86_64 AVD 完整组 52/52; 小米 Debug 桥组 5/5。IDE 两次测试启动未建立可用 debug session, 本次依据设备断言与进程事件, 不宣称取得 debugger 事件。临时 logpoint 已清除, AVD 已关闭。 -
M12.3 事件推送通道 (替代 drainEvents 轮询): 事实: sensors / ui / ui.overlay / websocket / input_observer 均以
drainEvents由脚本拉取。动作: 基于 M12.2 的回调通道, 订阅类调用返回subscriptionId, 宿主通过既有INodeJsHostCapabilityCallback.onResponse以 additive 键event=true推送; JS 侧各 facade 暴露on/once/off(EventEmitter),drainEvents保留兼容。契约 additive, AIDL 零改动。Check: sensorson("event")首事件到达延迟 < 50 ms (模拟器加速度传感器); websocketon("message")回环用例;drainEvents旧用例不回归。 — 2026-09-08 功能已落地, 首事件总延迟验收待补: 宿主提交 593ddb582, 请求 events=true 协商 subscriptionId, 既有 callback 的 Bundle/JSON 增 event=true, AIDL 无改动。五类订阅均支持 on/once/off; ui.on/once 保留返回取消监听函数的旧语义。旧宿主与 file 通道继续 drainEvents, JNI 降级前清除推送协商字段。Native 事件队列最多 128 条/4 MiB, 300 条突发验证交付最近 128 条、丢弃计数 172、RPC 不丢弃; 关闭订阅释放 loop 引用, 文件轮询为 0。三 ABI clang 语法检查与 Debug/混淆 Release 构建通过, JVM 72/72、38 模块类型与 48 样例校验通过; arm64 与 16 KB x86_64 Debug 各 16/16, arm64 混淆 Release 16/16 (含 15 包 corpus 与 conformance 11/11)。宿主 AVD 8/8 覆盖加速度计、真实 WebSocket 回环及 file 回退、UI 按钮/输入、悬浮窗、按键 fake 源、旧拉取用例、确认先于事件。宿主测试 APK 临时排除两份与当前控制台 API 不匹配的旧测试源 (ConsoleViewLayoutDeviceTest / ConsoleViewStackFrameLinkDeviceTest), 主 APK 正常构建; 不宣称宿主全量测试通过。R8 构建并行时 AVD 出现时限失败, 构建结束后同一 APK 的 8 项全部通过。传感器显式 samplingIntervalMs=20 (默认仍 250, Android 采样周期仅为提示) 时首事件总耗时 60.2/82.5/86.7 ms; 最后一次确认 19.2 ms、采样到 JS 13.2 ms (按 SensorEvent BOOTTIME 与 Node MONOTONIC 校正)。传输已低于 50 ms, 订阅到首事件总耗时未达原 Check, 因此本项暂不勾选。十语言与 HOST-API 已同步。 2026-09-09 验收补记: 回查 M13.5 最终回归build/m13/stdin-host-final-avd.txt, x86_64 API36 / 16 KB AVD 的同组 8/8 已通过, 其中传感器订阅到首事件 34.618494 ms、ready=24.505217 ms、采样到 JS=10.435284 ms, JNI dispatch=2 (订阅/关闭)、无 drainEvents 轮询; 同组包含真实 WebSocket 回环/file 回退与既有推送验证。原 Check 明确采用模拟器加速度传感器, 此前未回填这次已通过的结果, 现据原验收口径勾选。前述 60~86 ms 及并行构建下的较慢轮次仍保留, 34.6 ms 是本机通过样本, 不表述为所有设备或所有负载下的硬时限保证。 -
M12.4 常驻进程空闲策略: 事实:
:nodejs_runtime进程仅在取消兜底时被杀 (NodeJsRuntimePluginService.java:619-629), 无空闲回收; RSS/Threads 已采集 (NodePluginPayloads.java:195-196)。动作: 请求级KEY_IDLE_EXIT_MS(additive, 默认 0=不退出, 保持长驻语义) 与 runtimeInfoidleForMs; 到期无执行且无排队 →stopSelf()让系统回收, 下一次 bind 自动重建 (宿主已能处理 rebind, M8.2 证据)。Check: androidTest —idleExitMs=3000后 PID 变化且下一脚本成功; 默认请求 PID 不变 (LongRunningLifecycleSmokeTest回归)。 — 2026-09-08 完成: additive idleExitMs/idleForMs, 默认 0, 最后获准执行的请求决定后续空闲策略; 执行、预热、排队均不计为空闲, 新请求可恢复默认常驻。策略及准入与 native runtime 共用进程生命周期, Service 解绑/重建不产生过期定时器误杀; 退出与新任务准入在同一锁内互斥。根据 Android bound Service 行为修正原 stopSelf 方案: stopSelf 后只退出专用 runtime PID, 持有旧 Binder 的客户端自动重连。JVM 75/75 (新增到期准入互斥、默认覆盖、队列交接 3 项); arm64 真机与 16 KB x86_64 AVD 各 5/5 (空闲退出/重连、解绑重建与排队、LongRunningLifecycle、SerialQueue、CooperativeCancel)。3 秒退出实测 PID: arm64 25696→25735, AVD 23830→23852; 最终调整把工作区描述符清理包含在执行租约内后, AVD 再通过 2/2, PID 24010→24031。新脚本成功, 默认请求等待 3.5 秒后 PID 不变。IDE 与离线 Debug 构建通过, 十语言与 35 份文档同步。宿主 7badfa02e 增请求模型透传, 主 APK 离线构建通过, 未引入默认退出偏好。 -
M12.5 原生崩溃可读性 (条件立项): 按 "不为未发生的异常写代码" 原则, 仅当真机出现第一例 libnode 原生崩溃 (宿主见
EXECUTION_LOST且 logcat 有 tombstone) 时立项: 信号处理器写最小 crash marker (cacheDir/crash/<executionId>.json: signal / 故障 so / 阶段), 下次getRuntimeInfo带lastCrash, 用户消息 "运行时进程崩溃 (SIGxxx), 详见 logcat"。Check: 复现该崩溃的最小回归用例 + marker 回报。 — 2026-09-08: 本轮设备测试未出现符合条件的 libnode 原生崩溃, 保持条件立项, 不新增信号处理器。
目标: 桌面能跑的纯 JS 代码在插件里同样能跑; 内嵌 JS 体量与真实策略需求匹配。
- M13.1 无策略 builtin 直通: 事实:
__autojs6_limited_builtin_module_names42 个 builtin (node_bridge_sources.cpp:3632-3675) 中多数无任何安全策略却被子集包装 (如stream:34980-35019、zlib:35420、crypto:32771、os:33253、readline:34893、v8:36640)。动作: 分两批 — 第一批 buffer / events / path(+posix/win32) / util(+types) / url / querystring / string_decoder / assert(+strict) / punycode / stream(+promises/web/consumers) / zlib / timers(+promises) / perf_hooks / async_hooks / diagnostics_channel / string_decoder / v8 / vm / tty / readline(+promises) / crypto / os / constants 直接返回原生模块 (仅os.constants与os.userInfo等确有策略点的用透明 Proxy 拦截), 删除对应__autojs6_limited_*构造器; 第二批保留包装: fs(+promises,/proc/sys/dev)、process、module、child_process、worker_threads、net/http/https/tls/dgram/http2 (rawNetwork 开关)、inspector、dns。Check:NpmEcosystemSmokeTest15 包 + conformance 11/11 全绿;wc -l node_bridge_sources.cpp下降 ≥ 30% 并记录前后值; 新增负例 — 直通后/proc/self/status读取仍被拒。 — 2026-09-08 功能与兼容性验证已完成, 行数指标未达: 30 个内建模块/子路径直接返回原生导出, 另将 node:test 恢复原生; os 仅保留 tmpdir/homedir 与既有 userInfo 策略, 其余导出通过 Proxy 返回 Node 实现。删除 28 个旧构造器及 85 个不可达辅助函数, node_bridge_sources.cpp 从 44,262 行降至 40,432 行 (-8.65%), 无策略包装的实际规模小于原先估计, 未为达到 30% 而删改 fs/宿主桥等有效实现, 因此本项暂不勾选。调试器发现 native 异步错误晚于旧成功快照, 导致 succeeded=true 但 stderr 有 TypeError; 成功终态改在 SpinEventLoop 的最终 exit 生成, 覆盖 beforeExit 追加异步工作与退出码 7。node:test 首次加载因 internal/worker 尝试改写已保护的 process.chdir 失败, 提前初始化 worker_threads 后通过, 不改请求开关。新增 BuiltinPassthroughSmokeTest 验证别名对象一致、完整新导出、128 KiB 异步随机数、2 MiB 压缩/序列化、AsyncLocalStorage、原生 node:test 与 /proc/self/status 的精确拒绝码。三 ABI clang/Debug 构建与 JVM 75/75 通过; arm64 与 16 KB x86_64 各 30/30 (高频组、JNI/file、推送、空闲退出、npm 15 包及 conformance 11/11)。最终模块状态说明同步后, arm64/x86_64/armv7 各 13/13; 十语言与 HOST-API 更新, 35 份文档无漂移。 - M13.2 全局 fetch / WebSocket 回归原生 undici: 事实:
__autojs6_define_global("fetch", __autojs6_controlled_fetch)(:3462) 使fetch()走宿主 OkHttp、受network声明与__autojs6_fetch_policy响应字节上限约束, 而 rawhttp已默认开;WebSocket全局同理。动作: 全局fetch/Request/Response/Headers/FormData/WebSocket恢复 Node 原生 (随 rawNetwork 默认开); 桥接版改为显式require("autojs6:fetch")/require("autojs6:websocket")(宿主网络栈: 代理/证书策略跟随宿主), HOST-API 第三、十节同步。Check: 原生fetch("http://127.0.0.1:<port>/")自服务用例 (无network声明);live-fetch/live-websocket样例改用显式模块后仍 stable。 — 2026-09-08 完成: 移除 Environment 的 kNoBrowserGlobals 标志及旧 Web 数据类回退, 全局六项使用 Node 24.5.0 自带 Undici; 显式 rawNodeNetworkModulesEnabled=false 时 fetch/WebSocket 返回原有网络禁用错误。增加 autojs6:fetch / autojs6:websocket 别名, 保留 fetch/websocket 兼容入口; live-fetch/live-websocket 与 TypeScript 样例同步。NativeWebGlobalsSmokeTest 在无宿主 broker/network 声明下验证 HTTP POST、Request/Response/Headers/FormData、WebSocket 握手/回显/关闭及网络关闭负例。arm64 与 16 KB x86_64 完整回归各 31/31, armv7 原生 Web/builtin/npm/conformance 14/14; 三 ABI clang 与 Debug 构建、JVM 75/75、样例与类型检查通过。宿主显式 fetch/推送 WebSocket 与传感器/UI 旧路径 9/9, 宿主测试提交 dec3323e68e3ee4a79f73454e036ac5f49267940; 宿主 androidTest 编译仍使用临时脚本排除两份既有 console 测试编译错误, 未修改这些文件。HOST-API 与十语言文档更新, 35 份生成文档无漂移。 - M13.3 worker_threads 桌面对齐: 事实: 策略
maxWorkers: 1, taskTimeoutMs: 5000, maxOldGenerationSizeMb: 64, worker 内仅 11 个 builtin, network denied (:3871-3913)。动作: maxWorkers 默认os.availableParallelism()(上限 8); 取消默认 taskTimeout (请求级可配); worker 内 builtin 集与主线程一致 (桥 / inspector 仍 denied);new Worker(file, { resourceLimits })用户值优先 (上限由请求级策略钉)。Check:worker-cpu样例 4 worker 并行加速比 > 2 (arm64 真机记录); wasm-worker 样例重标; 现有 worker 用例回归。 — 2026-09-08 完成: worker 默认数量 min(8, os.availableParallelism()), WorkerPool taskTimeoutMs 默认 0; JSON runtime module autojs6:worker-policy 提供请求级数量、启动超时、任务默认超时和四项资源上限, 未配置时使用 Node 内存默认, Worker 用户值低于请求上限时优先。worker builtin 名单从主线程生成, 原生网络/文件可达范围继承执行配置, 宿主桥与 inspector 拒绝; 原有嵌套 worker 禁用与局部 ESM 范围如实保留在 HOST-API。修复旧入口拒绝工作区内绝对路径/file URL、以及 CJS 包装参数 parentPort/workerData/Buffer 与标准解构声明冲突的问题。worker-cpu 以四个实际 worker 测量相同计算, arm64 串行 1365.172 ms、并行 390.420 ms、启动 112.108 ms, 计算加速 3.497 倍, 含启动 2.717 倍 (>2); armv7 为 3.753/2.850 倍, x86_64 为 2.213/1.517 倍。wasm-worker 实际编译执行 add(19,23)=42, 升 stable。新增 5 项设备测试验证四 worker、全部主线程 builtin 名称、网络/FS 边界、192 MiB 用户值及请求 96/80 MiB 限制、5.5 秒无默认超时任务、显式超时后池复用、file URL/局部 ESM/MessagePort/ArrayBuffer 转移和两个发布样例。三 ABI clang/Debug、JVM 75/75、样例/类型检查、35 份生成文档通过; arm64 与 16 KB x86_64 各 36/36, armv7 worker/Web/builtin/npm/conformance 19/19。 - M13.4 node:sqlite / node:test / npm 第三批: 事实:
node:sqlite(Node 24 内建, 进程内) 不在任何名单, 脚本只能用跨进程的宿主database桥;node:test仅 "managed subset" (node-test-project partial)。动作: ① 放行node:sqlite(数据库文件受 fs 策略即可); ②node:test直通 (M13.1 顺带) 并让node --test语义在插件内以require("node:test")+ 默认 reporter 输出到 stdout; ③ npm 第三批 (开发机一次性联网制备 corpus, 唯一联网步骤):zod/cheerio/date-fns/mqtt/ws五包进 androidTest assets。Check: 新增NodeSqliteSmokeTest(CRUD + 事务);node-test-project升 stable;NpmEcosystemSmokeTest20 包全绿 (arm64 真机 + x86_64 模拟器)。 — 2026-09-08 完成: node:sqlite 的原生 DatabaseSync/StatementSync、CRUD、事务、函数与备份可用, 主线程/worker 共用薄包装, 构造/open/backup 复用 fs 路径与真实路径检查, node: 前缀与宿主 sqlite 桥明确区分。Node 24.5 无 authorizer, 因此拒绝 ATTACH、VACUUM INTO、文件目录 PRAGMA 与 SQLite URI 字符串/空临时路径, 保留原生扩展禁用和 experimental 警告; 不开放 SQL 绕过文件边界。NodeSqliteSmokeTest 覆盖 CJS/ESM/getBuiltinModule 一致、增删改查、提交/回滚、状态属性、备份/回读、file URL/Buffer、延迟 open、危险路径/外部符号链接/SQL 文件操作/扩展负例。node:test/reporters 放行, 发布样例通过真实默认 spec reporter 输出 2/2, 失败用例返回退出码 1, node-test-project 升 stable。新增 zod 4.5.4 / cheerio 1.2.0 / date-fns 4.4.0 / mqtt 5.15.2 / ws 8.21.3 (开发机联网制备一次, 原有依赖版本未改); 完整 11,656 文件 42,630,239 字节依赖树, 设备仅使用本地 HTTP/WebSocket/MQTT 回环, npm 20 包全绿。修复 Android asset 默认忽略 _ 开头目录导致 date-fns/_lib 丢失, 保留第三方源文件原始字节/许可证; 补 plugin-owned node:sqlite 类型。三 ABI clang 与离线 Debug 构建、JVM 75/75、样例/类型检查和 35 份文档检查通过; arm64/16 KB x86_64 完整组各 38/38, armv7 SQLite/npm/worker/Web/builtin/conformance 21/21。IDE 初次编译通过, 最后两次构建等待超时且无编译错误返回, 最终产物以成功的离线 Gradle 构建和三 ABI 设备回归为证。 2026-09-09 干净检出修正: M17 隔离工作区的 npm 回归发现.gitignore的/app/**/build/误排除了 mqtt、worker-timers 等 9 个包自带的发布目录; 原工作区有文件, 已提交树缺失 404 文件 (630,041 字节)。新增仅针对 npm corpus 的目录例外并补齐原始发布文件, 不改第三方内容或依赖版本; 404 文件与测试 APK 内字节一致。Node 24.20 候选在两台 arm64 真机 (小米 API 35、Sony XQ-AT72 API 31) 的完整组均仅因此失败, 补齐后 npm 21 包各 1/1 通过。 - M13.5 stdin 与宿主→脚本消息: 事实:
process.stdin是空桩 (:2586-2620), AIDL 无任何宿主→脚本输入方法。动作:INodeJsRuntimePlugin末尾追加boolean postMessage(String executionId, in Bundle message)(contract v3, 旧宿主不调用即无影响); 插件把消息经 M12.2 通道注入:kind=stdin→ 真实process.stdinReadable (支持readline),kind=message→require("autojs6:host").on("message"); 宿主编辑器控制台输入框接入 (涉宿主, 独立提交)。Check: 用例 — 脚本readline.question()等待, 宿主postMessage一行后脚本回显; 旧契约 (无 postMessage) 宿主对新插件仍正常。 — 2026-09-08 完成: 追加第五个 AIDL 事务, 基础 contractVersion 保留 2 + maxContractVersion=3 协商扩展, 请求兼容 2..3 (直接广告 3 会被已发布严格 v2 宿主拒绝, 因此调整握手方式)。独立执行通道按 executionId 接收 stdin / JSON message, 每条 data 64 KiB、最多 32 条/384 KiB JSON 队列, stdin 单块在途且按读取需求背压; Node Readable / readline / EOF / async iterator 与 EventEmitter once/off/ref/unref 均可用, 取消及退出清理。宿主提交7e78e1416: 复用 ConsoleInputQueue, stdin_state 显示输入栏、后台投递, 保留空行与首尾空格, 关闭清理自身请求。新增 host-input stable 样例、host.d.ts、HOST-API 与十语言日志。Check: HostInputSmokeTest 5 项覆盖两行中文/emoji、JSON+CJS/ESM、EOF、取消、旧 v2 与实际样例; arm64 / 16 KB x86_64 完整组各 43/43 (含 npm 20 包 + conformance 11), armv7 26/26; 宿主实际 LogActivity 输入栏三行 (中文/空行/空格) + 清理与桥回归 8/8, 旧宿主 APK 对新插件 6/6; 3 ABI clang、IDE build、离线双仓构建、75 插件 JVM + 7 宿主队列 JVM、类型/49 样例与 35 生成文档无漂移、API 镜像 10 文件归一化一致。宿主完整 androidTest 的两项既有控制台测试编译错误仍在, 本次按 M12 既有过滤构建其余测试。 - M13.6 wasi 决策:
controlled-wasi/wasi-scoped-fs两样例 disabled 已久。一次性决策: 放开 rawnode:wasi(preopen 限工作目录, 其余交 Android 权限, 与 fs 放开原则一致) 或维持 denied; 决策与依据记录于此, 样例随之升 stable 或删除。Check: 决策入档; 若放开,wasm-basic增 WASI hello 用例。 — 2026-09-08 决策并完成: 维持 wasi / node:wasi denied。依据 Node 24.5 WASI 官方文档, preopens 不提供可靠文件系统隔离; 本项目要求 /proc、/sys、/dev 硬边界, 原生 WASI 调用绕过现有 JS fs 检查, 仅校验 preopen 根目录不足以满足约束。此版本不引入新的 WASI 隔离实现, 普通 WebAssembly / WASM worker 继续可用。删除 controlled-wasi / wasi-scoped-fs 的 10 个文件与 manifest 条目; 校验器忽略 Git 不记录的空目录 (本地空目录删除被工具自动审批拒绝, 保留目录壳)。HOST-API 与十语言日志记录结论; 离线 verifyNodePluginExamples / typeCheckNodeTypescriptSmoke 和 35 文档无漂移通过, 当前 47 例 = stable 31 / partial 16 / disabled 0。未改变运行时行为, 沿用 M13.5 刚通过的三 ABI npm/conformance/WASM worker 回归; IDE build 60 s 超时, 仅 Jetifier/SDK XML 警告, 无编译错误。
M13 Release 验证补记 (2026-09-08): build 116 的签名 arm64-v8a / x86_64 配套 Release 测试各 43/43, armeabi-v7a 为 26/26; 含 npm corpus、conformance、worker、SQLite、stdin/host message。x86_64 模拟器 page size 为 16 KB。四个签名 APK 已在本地产出, 未 push/tag/release; 后续 M14 源码不在这批 APK 中。
2026-09-08 M14.1 实现记录: 宿主 f2765e085 接入 ScreenCaptureRequester / ScreenCapturer, 授权后启动既有 mediaProjection 前台服务, stop/撤销/退出释放会话及图片。插件 image/images 增 requestScreenCapture/stopScreenCapture 别名, 保存 PNG/JPEG/WebP 在本项提前接入以支持 PNG 验收。沿用已登记的 screen_capture/image 能力及默认 32 个活跃图片句柄限制, 无 AIDL 变更。Debug 构建、三 ABI clang、75 项插件 JVM、样例/类型、npm + conformance 三 ABI 各 12/12 通过; arm64 与 x86_64 的未授权/保存用例各 1/1 通过, 宿主 conformance 5/5 通过。宿主 Android 测试构建仍用 M12 的过滤脚本排除两份已有编译错误的 ConsoleView 测试; provider registry 旧测试另有定义数量 22→24 和缺少 OCR 插件两项不匹配, 未将其记为通过。已向用户询问是否方便操作小米 968e9f18, 手工录屏授权及屏幕尺寸 PNG 验收待完成, M14.1 暂不勾选。
目标: Node 脚本可以 captureScreen → findImage/findColor/OCR → click, 与 Rhino 脚本能力对齐。
-
M14.1 宿主 MediaProjection provider: 事实:
dispatchMediaProjection恒返 capabilityProviderMissing (NodeBridgeProtocol.kt:1951-1962); 宿主 Rhino 侧已有完整 ScreenCapturer 与前台服务流程。动作:requestScreenCapture(options)复用宿主既有授权 Activity 流程 (Android 14+ 的前台服务类型mediaProjection与通知),captureScreen()返回 provider-owned image handle (复用imageHandles),stop()释放; 能力名screen_capture按 HOST-API 第十一节四处 + M11~M17 约定 3 的两处登记。Check: 真机 (录屏授权手工一次) —images.requestScreenCapture()成功后images.captureScreen()返回 handle,saveImage落盘 PNG 尺寸等于屏幕分辨率; 未授权路径返回可读permission-denied。 -
M14.2 图像分析在宿主侧 (handle 语义): 事实:
dispatchImage仅 readImage/recycle (:1964-1979), 其余 10 方法返 provider missing。动作: findImage / matchTemplate / findColor / findMultiColors / clip / resize / grayscale / threshold / saveImage 接宿主 OpenCV 实现 (与 Rhinoimages.*同一实现类), 入参 handle 与 JSON 选项, 出参点/矩形/新 handle; 活跃 handle 上限 (建议 16) 与执行结束自动 recycle (registry 已有)。Check: 真机用例 — 截屏 →clip→findColor命中宿主自身 UI 已知颜色;findImage用saveImage回读的小图作为模板命中原位置 (偏差 ≤ 2 px)。2026-09-08 实现记录: 宿主
c82d97b14接入 TemplateMatching / ColorFinder 与 OpenCV 变换, 复用 Rhino 图像后端; clip/save 使用 Android Bitmap。默认句柄上限沿用 32, 整图裁剪也返回独立图片, 所有 Mat 在操作后释放; 缺少 OpenCV 时状态为 degraded, 读取/保存/裁剪仍可用。真机与 x86_64 模拟器的已知图案测试覆盖全部方法、region 偏移、保存回读模板偏差 ≤ 2 px、灰度/二值化像素、无匹配、非法区域、recycle 和上限恢复, 各与未授权及 conformance 合计 8/8 通过。Debug 构建、IDE build、47 样例验证与 TypeScript 通过。screenshot-find-image 已改为实际申请授权并裁剪回读截图模板; 仍待手工授权后执行已知 UI 截屏链 Check, M14.2 和样例 stable 晋级暂不勾选。 -
M14.3 像素跨进程 (PFD): 事实: 桥响应为 JSON 文本, Binder 事务 1 MB 上限, 1080p 位图无法以 base64 走通。动作:
image.toBytes({ format: "png" | "rgba" })与readImage(path)大图路径改为宿主写入ParcelFileDescriptor/ashmem (INodeJsHostCapabilityCallback.onResponseBundle 携带 PFD, 键 additive), 插件侧Buffer零拷贝读取; 使 pngjs/jimp 等纯 JS 图像库可处理截图。Check: 1080p 截图toBytes("rgba")耗时 < 200 ms (真机记录);NpmEcosystemSmokeTest增 pngjs 解码截图用例。 — 2026-09-08 完成: 宿主19d1901ca; image/images.toBytes(handle, options 或格式字符串) 返回 native Buffer, PNG 或紧密排列的非预乘 sRGB RGBA8。沿用 readImage 的宿主句柄语义, 显式取像素时走 PFD; JSON 不携带像素。宿主写私有临时文件并解除目录项, 插件 dup/mmap + V8 BackingStore, Buffer.from(ArrayBuffer) 无像素复制。JNI/file 共用附件, 请求取消/超时/执行结束释放未消费 FD, Buffer 独立于图片句柄。UiAutomation 获取真实设备截图后统一绘制为 1080×1920 sRGB 夹具, 宿主提供 PNG/RGBA, 三 ABI 每种传输 8 次取样: arm64 JNI/file 中位观测值 20.0/45.2 ms, armv7 92.6/89.7 ms, x86_64 81.3/87.8 ms; 各次均低于 200 ms。PFD 单次传输 8,294,400 bytes, 三设备的 PNG 解码/通道/alpha/Buffer 生命周期用例各 2/2; 此独立传输验收不代替 M14.1 的 MediaProjection 手工授权 Check。npm corpus 增真实 pngjs 7.0.0 (开发机获取并核对 npm integrity, 设备离线), 21 个包及截图宽高/像素长度断言通过。桥接 5 + npm 1 + conformance 11 + plugin info/manifest 2 三 ABI 各 19/19; 含每模式 40 个持有 Buffer、16 次超时后再调用, FD 数 arm64 130→130 / x86_64 96→96 / armv7 56→56。三 ABI clang、Debug/JVM、IDE、样例/类型及 10 文件 API mirror 通过。catalog 1.4.0 为本地未发布产物, 旧快照未改; 能力集合仍为 48, 已记录宿主额外六项导致的既有 capability alignment 失败, 留待 M15 对齐。 2026-09-09 Release 补验: 非 debuggable 包下, 测试进程直接列出 /proc//fd 被 Android 拒绝。附件生命周期测试改读既有 getRuntimeInfo 的 runtime_process.fd_count, 必须 proc_fd_readable=true、计数 >0 且预热/二进制执行/测量始终同一工作进程; 保留 40 个 Buffer、16 次超时迟到回包与执行后 FD 增长断言。未新增生产诊断或改变 /proc 硬边界。JNI/file 两模式 FD 数分别保持小米 125→125、Sony G8441 50→50、16 KB AVD 92→92, 三端桥接全类各 6/6。 -
M14.4 OCR / barcode 端到端与样例转正: 动作:
ocr.recognizeText(captureScreen())与barcode.detect()接 M14.1 handle (dispatchOcr 已支持 handle :1985-2007); screenshot-find-image / ocr-automation / pro-parityscreenshot-ocr由 partial 升 stable (无 ML Kit 插件时保留可读 skip)。Check: 真机安装 ML Kit OCR 插件后识别到宿主界面已知文本;verifyNodePluginExamples通过; HOST-API 第二/八/九节更新,media_projection从 denied 表移除。2026-09-08 M14.4 实现记录: 宿主 19fce7984; 安装既有 ML Kit OCR / Barcode 插件, 小米 arm64 与 x86_64 的真实宿主画面经 UiAutomation 截屏、readImage、OCR/QR 识别得到 ROADMAP 2026 与 AutoJs6 Node Roadmap 2026。测试画面适配 320 px 小屏, 保持完整文本断言。指定不存在的 OCR engineId 返回 unavailable, 仅插件选择失败归入该分类, 识别过程错误仍保留失败。修正两个旧 fake transport 测试缺失的 capability 声明后, 两设备 OCR/Barcode/画面识别各 11/11 通过。ocr-automation 与 pro-parity screenshot-ocr 已改为申请授权并识别真实句柄, 仅权限拒绝/插件不可用输出 skip, finally 回收并停止; 47 样例及类型校验通过。HOST-API 第二/八/九节和十语言日志同步。MediaProjection 人工授权仍待用户操作, 不以 UiAutomation 代替此 Check, 本项与三个相关样例的 stable 晋级暂不勾选。
目标: 日常自动化脚本不再需要 "这个只能回 Rhino 写"。
-
M15.1 device 信息与控制面: 事实:
deviceMethods仅 isScreenOn / wakeUp / vibrate / isIgnoringBatteryOptimizations / openBatteryOptimizationSettings (NodeBridgeProtocol.kt:679)。动作: 只读 — width / height / density / densityDpi / brightness / brightnessMode / battery / isCharging / sdkInt / release / model / brand / product / board / bootloader / hardware / fingerprint / buildId / totalMem / availMem; 控制 — setBrightness / setBrightnessMode / keepScreenOn(timeout) / cancelKeepingAwake (WAKE_LOCK 在宿主) / setVolume 系 (media 桥补 set); 硬件标识符继续 blocked。Check: 一个用例串调全部只读方法断言类型与非空;keepScreenOn(5000)后 5 s 内isScreenOn为 true (真机)。 2026-09-08 M15.1 完成: 宿主 5b79a27ac。复用已有 device.info schema, 补充亮度/模式/电量/充电/内存和固件 Build 信息; 插件保留同步启动快照属性, 增加实时 info 与 20 个只读 getter。setBrightness / setBrightnessMode / keepScreenOn / cancelKeepingAwake 使用 device.power; 亮度写入检查 Android canWrite, 屏幕锁按执行独立持有, 定时或退出释放。media.setAudioStreamVolume 校验各流 min/max, Music/Notification/Alarm 便捷方法读写相同音量, Android 拒绝返回 permission-denied。小米 arm64 / Sony armv7 / x86_64 16 KB AVD 各 2/2: 串调只读字段, 硬件标识符缺席, 非法入参, 未声明 power 拒绝, 5 s 窗口内两次亮屏断言; dumpsys 记录退出时屏幕锁释放 (小米第二次 ACQ 19:03:51.737, REL 19:03:51.873)。AVD 另一次临时 WRITE_SETTINGS allow 下 1/1 通过, 日志 canWriteSettings=true, 随后恢复 default; 真机默认拒绝路径通过。三 ABI npm + conformance + info/manifest 各 14/14, 75 JVM、三 ABI clang、Debug 构建、47 样例和类型检查通过。顺带对齐宿主已有 console/files/pinyin 六项, host/plugin/catalog 均 54, 10 个 API mirror 文件通过; catalog 1.4.0 未发布, 老快照不变, Node 本地 console/fs/便捷模块行为不变。 -
M15.2 events 观察者 (推送): 事实: 通知 / toast / 按键真源 / 屏幕开关均无 Node 入口 (
input_observer仅 fake 源, 真源在 scheduled/background 启动面拒绝)。动作: 基于 M12.3 通道新增events桥:observeNotification(NotificationListener 权限门禁) /observeToast(无障碍) /observeKey(无障碍按键, 接管 input_observer 真源) /on("screen_on" | "screen_off" | "battery_changed")(广播); 能力名events.notification/events.key等按登记顺序。Check: 用例 — 脚本notifications.notify自身通知后events.on("notification")收到同 id; 按键用例在无障碍开启的真机手工补证 (与 M3.2 同口径)。 2026-09-08 M15.2 实现落库, 手工按键 Check 待补: 宿主 d8c6cbc9c。autojs6:events 提供通知/外部 Toast/非消费按键/屏幕与电池观察者, 使用 M12.3 JNI 推送和 file drainEvents 兼容路径, 每执行独立订阅并在关闭、服务断开或脚本退出时释放。Node 原生 events 不变; events 根声明不隐含 notification/toast/key 子能力; input_observer 真源复用按键总线, 已取消 scheduled/background 拒绝。小米 arm64 / Sony armv7 / x86_64 16 KB AVD 最终各 16/16 (新观察者 5 + 旧 input_observer 6 + 宿主 conformance 5); AVD 另一次已获通知访问权限的实跑收到 notifications.notify 发出的 id=151200。重复 instrumentation 曾因强停后的通知服务未重连失败, 最终基线在原权限状态通过, 不隐去该限制。ADB/UiAutomation/模拟器控制台按键均未得到系统送达, 最后一次宿主 keyBus.lastDispatchAtMillis=0, 因此不充当真机手工 Check; opt-in NodeKeyObservationInstrumentationTest 已备妥。临时 AVD 权限均恢复。三 ABI npm + conformance + info/manifest 各 14/14; 75 JVM、三 ABI clang、Debug、47 样例/类型和十语言文档通过, API mirror 10 文件及 host/plugin/catalog 58 项对齐。catalog 1.4.0 仍为未发布本地产物。 -
M15.3 app / dialogs / keys 扩面: 动作:
app补 openUrl / uninstall / sendEmail / intent(action, data, type, extras, flags) / startService / sendBroadcast / getInstalledApps / getPackageInfo;dialogs补 rawInput / singleChoice / multiChoice / progress(show/update/dismiss);keys新模块: notifications / quickSettings / lockScreen / takeScreenshot / splitScreen (无障碍全局动作),powerDialog一次性裁定放开或维持 blocked。Check: 每方法至少一条断言, 合并为 ≤ 2 个真机用例; HOST-API 表格与 d.ts 同步。 2026-09-08 M15.3 完成: 宿主 5c65a63e3。保留已有 openUrl/sendEmail/uninstall/intent, 补 startService/sendBroadcast/getInstalledApps/getPackageInfo; Intent 的 data/type/extras/flags 传到 Android, 服务不附带 Activity flag, 查询/派发分别要求显式 app.query/app.activity。dialogs 接入真实 Activity 窗口, 补 rawInput/singleChoice/multiChoice/progress.show/update/dismiss; 原 alert/confirm/input/select 也落到真实 provider, 关闭/超时/脚本退出释放, Activity 被销毁时返回对应取消值。keys 新增六个 Android 全局动作, powerDialog 决定开放电源菜单, 不选择关机或重启。小米 arm64 / Sony armv7 / x86_64 16 KB AVD 各 2/2 新增用例: 实际包列表/缺失包/系统过滤, 普通服务启动, 广播接收文本与整数, 六个 keys 在无障碍关闭时的权限拒绝; 八次窗口交互含 Activity 取消返回 -1, 进度更新/重复关闭和脚本退出零会话。全局动作的开启权限正向操作未在此自动化组执行。既有宿主 conformance 5/5 保持通过, 其中继续断言网址/邮件/卸载 Intent 描述符, 不执行删除应用或发送邮件; 三 ABI 插件 npm/conformance/info/manifest 各 14/14, 75 JVM、clang、Debug、47 样例、类型及十语言文档通过, 10 文件 mirror 和 59 项能力对齐。catalog 1.4.0 未发布。 -
M15.4 recorder 与 ui.overlay 转正: 事实:
recorder.start/stop返 provider missing (:2355-2370); overlay 自报p14_08_provider_poc(:887)。动作: recorder — RECORD_AUDIO 运行时权限门禁 + 前台披露通知 + 输出文件走 PFD/工作区路径 + 时长上限; ui.overlay — 悬浮窗生命周期 (脚本结束自动关闭已有 registry)、事件改推送 (M12.3)、update支持全部声明式属性, 去掉 POC 标记。Check: pro-paritymedia-recorder与overlay-floaty样例升 stable; 真机录 3 s 音频文件大小 > 0 且可被mediainfo.read解析。 2026-09-08 M15.4 实现落库, 真机录音 Check 待补: 宿主 21cf2e3de。recorder 接入每执行独立的 Android MediaRecorder, AAC/MPEG-4 单声道、作用域内 PFD 输出, 开始前检查 RECORD_AUDIO 并建立带停止按钮的 microphone 前台通知; 默认 60 s, 上限 300 s, 到时/停止/脚本结束释放编码器和描述符。ui.overlay 移除 POC 标记, 更新全部声明属性及内容树、窗口尺寸/位置/交互标志/透明度, 支持拖动及 click/move/update 推送, 退出关闭窗口。小米 arm64 / Sony armv7 / x86_64 16 KB AVD 新增各 2/2: 录音权限状态与拒绝、真实悬浮窗更新和推送; API 29+ 另外断言 Android 控件样式、点击回调、实际拖动坐标及退出零窗口, Sony API 28 不使用 WindowInspector。旧媒体/窗口测试补齐 capability 声明和新状态预期, 三台安装 MediaInfo 后各 7/7, 含实际 WAV 解析。三 ABI 插件 npm/conformance/info/manifest 各 14/14, 75 JVM、clang、Debug、47 样例/类型与十语言文档通过。overlay-floaty 已标 stable; media-recorder 已改为 3 s 真实录音示例, 但保持 partial。已准备 opt-in NodeAudioRecordingManualInstrumentationTest, 待用户麦克风授权及现场录音后检查非空文件/AAC 解析/通知释放; 尚未启动麦克风, 不以权限负例或 WAV 夹具替代录音 Check。 -
M15.5 特权输入注入决策 (root / Shizuku): 2026-09-08 决定不增加 RootAutomator 或 Shizuku 输入通道。无障碍 gesture/swipe 已覆盖常用触摸手势; 既有 shell.execRoot 在明确声明 shell.root 且设备实际具备 root 时可执行用户编写的 input/sendevent 命令。新 RootAutomator 需要维护设备事件节点映射、注入会话与取消清理, 当前没有已复现的功能缺口需要此层; Shizuku 则增加独立授权/服务依赖, 本阶段不引入。execShizuku 继续拒绝, 不增加能力项、依赖或全局权限。HOST-API 第八节同步, 文档决策 Check 完成; 不以此决策宣称 root 命令已在无 root 设备实跑。
目标: 常驻服务脚本运行时, 临时脚本立即可跑; Binder 线程不再被长驻脚本长期占用。
-
M16.1 方案决策: 2026-09-08 选择默认 2 槽 Android 进程池。既有对外 RUNTIME 组件及权限保持,
:nodejs_runtime只负责绑定与全局 FIFO 3 调度, 两个不导出的 Service 子类分别在:nodejs_runtime0/:nodejs_runtime1复用现有单活 Node/V8 生命周期、watchdog 与协作取消。宿主无需枚举新 action; 调度器按 executionId 路由取消与消息, 一个工作进程的重启不终止另一个。当前 C++ 全局互斥、进程级输入输出与 JS 缓存结构保持每进程单执行, 不实施同进程多 Environment。内存规划先按每个已预热空闲槽 128 MiB PSS、两槽 256 MiB PSS 预留, 这是待 M16.2 实测修正的容量预算, 不是 JS 堆硬上限; 实际脚本内存与 worker 开销另计, 记录 RSS 及 Android PSS 以免把共享库重复映射误算为物理增量。预热覆盖两槽, 忙槽不打断; 默认最多同时执行 2 个, 其余按现有容量排队。此项只完成决策 Check, 并发性能与内存实绩由 M16.2 验收。 -
M16.2 实施进程池: 2026-09-08 完成; 宿主契约镜像 0698a5b90。公开 RUNTIME 组件成为调度器, 两个不导出的工作 Service 复用原单活执行实现; 空闲槽优先, 全忙时全局 FIFO 3, 超额 BUSY, 取消排队请求不会执行源码。executionId 路由取消/stdin/host message, watchdog 和 idleExitMs 属于对应工作进程, prewarm 覆盖空闲槽。getRuntimeInfo 返回 slots (slotId/pid/active/queued/rss/ready), queuedExecutions 为全局等待数, 结果及事件回显 slotId; 顶层 pid 兼容表示第 0 槽, dispatcherPid 单列。小米 arm64 / Sony armv7 / x86_64 16 KB AVD 的 ConcurrentExecutionSmokeTest 均证明不同 PID 并发和第二槽 stdin 路由; 最后首 stdout 分别 211/498/437 ms。单槽预热 PSS 基线 56279/35644/56390 KiB, 两槽 + 调度器 PSS 151431/102998/155322 KiB, 增量 95152/67354/98932 KiB; 测量两槽包含常驻脚本, 未扣脚本本身开销。两槽总 PSS 均低于 M16.1 的 256 MiB 预留预算, RSS 按槽单列避免当作物理增量。三 ABI 的 12 类冒烟 (SerialQueue 增满载 FIFO/取消/容量断言) + 并发 + 3 s 强制重启隔离 + 空闲退出共 17 个用例均通过, info/manifest 2/2; 完整 conformance 首次有 9 条旧 callback PID 断言失败, 按输出来自调度器、module provider 仍来自工作进程修正后各 11/11。输入/并发补测各 6/6, 宿主 bridge conformance 各 5/5, 75 JVM、Debug 构建、10 文件 API mirror 与十语言文档通过。强制重启时另一槽的 setInterval 继续运行, 调度器 Binder 保持有效, 下一脚本使用新工作 PID。此实现仍使用同步 runScript, 长驻 Binder 占用由 M16.3 处理。 M16.2 冷进程补测: 初次 x86_64 与两项 Node 源码编译同时运行, 首输出 1752 ms 未达 1 s; 小米的测试卡住, JDB 读取 firstOutput-submitted=170 ms、inputAccepted.value=0, instrumentation 线程停在同步 runScript, 回调 Binder 线程空闲。原因是测试用 stdout 当作 stdin 就绪信号而提前投递, 且未设置执行超时。修正为等待 stdin_state=true、从测试线程投递并加 20 s 预算。暂停源码编译后, 三 ABI 并发 + 输入各 6/6; 首输出 192/418/959 ms, PSS 基线 57188/36558/56953 KiB, 池 151514/104447/154750 KiB。模拟器对开发机负载敏感, 不把 <1 s 解释为任意负载保证。调试器已恢复线程并解除连接, 源码编译已恢复。
-
M16.3 异步 runScript (contract v3): 2026-09-08 完成, 宿主 14dc50422。第六个事务 startScript 即时返回 accepted/executionId, 接受前登记执行与队列以支持立即取消; 终态 finished 携带完整 result, 在工作进程及调度器释放租约和工作区 FD 后发送。基础 contractVersion=2、maxContractVersion=3, 新宿主还要求 asyncScriptExecution 标记, 兼容只实现 postMessage 的早期 v3 插件。旧 runScript 保留, 其下游工作槽也改用异步事务。callback 保持同步 AIDL, 保留已发布回复协议与输出背压, 不改 oneway。调度器使用有界准入下的 5 个普通执行线程, 工作槽使用单个普通执行线程; 进程死亡解除等待, 不重放脚本。宿主保持总预算 + 5 s 兜底, 收到终态后才验证并回传工作区。 兼容性修正: 已发布宿主严格要求 maxConcurrentExecutions=1, 因而该字段保留每个 Node 进程的单活容量, 新增 processPoolMaxConcurrentExecutions=2 表达池总容量; 新宿主同时识别 processModel/capability。M16.2 原宿主 conformance 的 5 项结果包含因握手被拒而跳过的运行用例, 不计作端到端通过, 本项以实际运行重新验收。插件三 ABI 完整 12 类冒烟 + 并发/输入/取消重启/空闲退出/异步/完整 conformance/info/manifest 各 37/37, 75 JVM、Debug 构建、10 文件镜像与 59 项能力对齐通过。宿主三 ABI 新并发工作区 + bridge conformance 各 6/6; 验证两项运行、一项排队, 取消前文件尚未回传, 终态后两个独立项目文件写回且下一脚本回读成功。首次测试误用无 project.json 的单文件目录, 后按既有项目快照规则补夹具; 模拟器在重型源码编译并行时另有 30 s 桥超时, 暂停编译后全组通过, 保留负载限制。 小米现场 JDWP 快照: dispatcher PID 8313 有两个 Node-pool-execution 线程等待 CompletableFuture、一个等待全局队列, 五个 Binder 线程无执行 Java 栈; slot0 PID 8357 / slot1 PID 8376 各三个 Binder 线程空闲, Node 在 Node-runtime-execution 线程; 宿主 PID 9253 三个 Binder 线程空闲。所有线程均已 resume 并解除自建 forward。旧客户端实证使用宿主 0698a5b90 的原同步 NodeJsRuntimePluginHost 源码构建临时 Debug APK, 小米和 x86_64 的严格握手/常驻复用/bridge conformance 各 7/7 (0 ignored); 随后恢复当前宿主 APK, 异步工作区各 1/1。十语言日志和 35 生成文档通过, 未修改已发布快照或执行对外发布。
2026-09-09 完整 Release 基线: v1.3.0 / versionCode 135 / Node 24.5.0 的三 ABI 与 universal 共四份签名 APK 与配套 Release androidTest 一并离线构建; 修复上述 M12/M14 两个测试入口后, 26 类回归覆盖高频 12 类、并发/异步、输入、取消重启、完整 npm/conformance、info/manifest 等。小米 API35 与 x86_64 API36 / PAGE_SIZE=16384 各 OK (52 tests), 75.479/67.556 s; Sony G8441 API28 返回 OK (52 tests), 116.171 s, 其中 UnrestrictedFsSmokeTest 因 Android <11 的 Assume 跳过 1 项, 实际执行 51 项。此前 M16 三 ABI 37/37 的 Sony 结果也包含这一平台不适用项, 不解读为该权限路径已在 Android 9 执行。Inspector 与冷启动测量未纳入本次 Release 组; 原始两项失败日志保留, 修复后日志为 build/m17/m16-release-fixed-.txt。测试结束已关闭本次临时 AVD。
目标: 不再被上游 nodejs-mobile 产物节奏锁死; 能在安全发布后一周内出新 libnode。
-
M17.1 自建 libnode 管线: 事实: 24.5.0 (2025-07) 之后 24.x 已有多个安全发布, M10.1 因上游无 Android 产物而停摆;
tools/nodejs/runtime-build/已有容器脚本但sourceBuild: bootstrap_only; 兄弟仓 Bun Runtime 已做到 patched runtime 可复现构建 (提交 1944595)。动作: 钉容器 digest (Ubuntu LTS + NDK r28/r29 + Python/ninja), 提取 degaso/nodejs-mobile 相对官方 tag 的 Android 补丁集为tools/nodejs/runtime-build/patches/*.patch, 构建 3 ABI (-z max-page-size=16384), 校验libnode.exports.map全部符号存在, lock 记录 sha256/buildId/补丁集哈希。Check: 本机或手动 CI job 完整构建一次, 产物替换后冒烟组 12 用例 + conformance 全绿; 同输入两次构建 sha256 一致, 或记录不一致来源。 2026-09-09 构建进度: 官方目标更新为 24.20.0, Android 补丁从 degaso116bad1dc919702d4a701d49df26d960403ee4a4相对官方 24.5.0 提取并已应用到 24.20.0。Ubuntu 基础镜像 digest、实建 Docker image ID、NDK r28c / Clang 19.0.1 / host Clang 18.1.3 / Python 3.12.3 / ninja 1.11.1 及补丁 SHA-256 已记录; 约 1.7 GiB 的本地 Docker save 归档保留同一环境, 未发布镜像。三个独立 Linux 工作目录均已进入 V8 编译; 本次会话中断使容器以 255 退出, 无 OOM/编译错误记录, 已恢复增量构建。新增手动源码入口支持独立 ABI、相同输入续建和新目录复建; ELF 检查覆盖架构、16 KB LOAD、Build ID 与嵌入符号,--bridge另检查 adapter map 的autojs_node_get_runtime_api_v1(该 map 属桥接库, 不能用于裁掉原始 libnode 的 Node/V8 导出)。构建计划校验通过, 当前准确状态为building; 三 ABI 最终产物、独立复建比较与替换后设备回归尚未完成, 因此保持未勾选及默认 Node 24.5.0。 2026-09-09 源码构建修复: arm64/x86_64 首次在 Linux mksnapshot 链接时报 TryHandleSignal/RegisterDefaultTrapHandler 未定义, arm64 另缺 v8_internal_simulator_ProbeMemory; 两容器均非 OOM。原因是 GYP 的 OS=android 也用于宿主工具源文件选择, 而 Linux 编译器启用了宿主侧 trap handler。新增独立 0002-linux-host-trap-handlers.patch, 仅为 Linux host toolset 的 x64/arm64 V8 目标补 POSIX 实现, arm64 模拟执行另加 simulator 实现; 未改上游 Android target 策略, 也未恢复 fork 的全局禁用。生成的真实宿主编译命令下 5 个源文件 -fsyntax-only 通过, 三 ABI 均确认未向 Android target 添加这些源文件; 重新生成后复用已有目标文件, 两个 mksnapshot 已成功链接并继续 Node 本体编译。新补丁 SHA 与嵌入 build-plan SHA 已同步, 手动计划校验通过; 原始失败日志保留, 独立复建改在修复后的首份产物验收成功后启动。2026-09-09 管线验收完成: 三 ABI 的 Node 24.20 首份源码构建 (Linux host 链接修复后续建) 与独立干净复建, SHA-256/Build ID 全部一致。随后分别从各自的 24.20 工作目录维护构建 24.21, 更新 1,155 个源码文件、移除上游删除的 4 文件并加入 STORE 修复, 未在 first/repeat 间复制目标文件; 三 ABI 的 24.21 SHA-256/Build ID 也全部一致。此处是两份独立维护构建, 不声称两次全新干净的 24.21 构建。完整比较、源码/headers、三份补丁、NDK 与 Docker image ID 已回填 runtime-build.lock.json, sourceBuild=ready; 36 个动态嵌入符号、36 个直接导入及 adapter map 导出全部通过。24.21 候选在三台真机和 x86_64 AVD 的 Debug 52 项、Inspector/冷启动各 1 项与配套混淆 Release 52 项均通过; Sony API28 的 52 项报告含 1 个既有 SDK>=30 跳过。独立检出工作区对本次管线变更运行 verify-runtime-build-plan --fail-on-bootstrap-only 通过, 保留提交树的默认 Node 24.5, 后续由 M17.2 独立切换与收集发布物。全部源码容器已完成并退出, 临时 AVD 已关闭。
-
M17.2 晋级 24.x 最新 LTS: 动作: 用 M17.1 产物;
node_runtime_adapter_24_5.cpp(1,023 行) /node_runtime_api_v1.h按符号与 ABI 差异适配 (新增 adapter 文件而非改旧文件, 运行时按版本选择); 全量 androidTest + 3 台真机; runtime-kit / catalog 发新版本 (本地发布物)。Check:getRuntimeInfo报新版本; runtime-kitreleaseReady: true; CHANGELOGdependency条目 "升级 Node.js 24.5.0 → 24.x"。 2026-09-09 发布准备: 本地nodejs-api:1.4.0AAR 已产出并通过手动 publication 验证、契约 JVM 9/9 与 API mirror 10 文件 校验。保留已发布 1.3.0 / compat-v1 四事务快照, 新 compat-v3 快照明确追加postMessage=5、startScript=6; 校验原描述符及事务号保持前缀不变, 基础 contract=2、max=3。增加node24_20常量供新版使用, 宿主镜像提交637a1603f; 当前默认运行时仍为 24.5.0, 新 runtime-kit 与实际 Node 晋级等待 M17.1 产物验收。 2026-09-09 适配准备: 新增独立 node_runtime_adapter_24_20.cpp 与官方 24.20.0 的 122 份 Node/V8/libuv 头文件, 保留原 24.5 adapter 与默认 slot。CMake 按 slot 同时选择 adapter/头目录; 三个 ABI 的当前 compile_commands 参数下, 新头文件和 adapter 的离线 -fsyntax-only 共 30/30 通过。头文件逐字节等于已核对 SHA-256 的官方 archive, 完整上游 LICENSE 随源码保留。当前默认 24.5 的 签名 Release 构建与设备基线通过; 24.20 的真实链接、嵌入符号与设备验收仍等待源码产物, 不以语法检查代替晋级。手动源码入口同时为每个 ABI/run-id 设置 Docker 容器名, 便于设备计时测试期间暂停与恢复。2026-09-09 两 ABI 候选验收: arm64/x86_64 自建 libnode 已产出 (70,578,608 / 75,379,272 字节), SHA-256/Build ID 入 lock; 每份均有 36 个动态嵌入符号, 与新头文件链接的桥接库 36 个直接导入全部可解析, adapter C ABI 导出与 16 KB LOAD 通过。原生 CLI 在小米 arm64 和 16 KB x86_64 AVD 实跑 crypto/SQLite/worker/本地 fetch; 独立检出工作区的 Node 24.20 Debug 候选在小米 API 35、Sony XQ-AT72 API 31 与 x86_64 API 36/PAGE_SIZE=16384 完整 26 类各 52/52, Inspector 与冷启动各 1/1 (每端合计 54/54)。SimpleRun 新增实际 process.versions.node 与 getRuntimeInfo 版本一致断言, 三端均回报 24.20.0/node24_20; npm 21 包通过, 夹具检出问题的修正另见 M13.4。冷启动暖执行 P95 分别 200/231/463 ms, 不据单次样本承诺加速。已关闭临时 AVD、恢复源码编译, Sony XQ-AT72 的 All Files appop 恢复原 default。主工作区仍使用 24.5, 两 ABI APK 仅用于开发验证; armv7、独立源码复建比较、最终三 ABI Release/runtime-kit 仍待完成, M17.1/M17.2 保持未勾选。
2026-09-09 上游增量: 官方 发布索引 已列出 24.21.0 LTS (索引日期 2026-09-07), GitHub Release 实际 publishedAt=2026-09-08T21:51:09Z, 提交 955266bfdd854cd280dffd47548673914484e4c0。该版本已集成 OpenSSL 3.5.8 和 Undici 7.29.1, 因而本次最终晋级目标调整为 24.21.0; 已完成的 24.20 三 ABI 设备回归与正在完成的独立复建保留为管线基线, 不冒充 24.21 验收。官方源码/headers tar.xz 已分别通过发布校验值, 既有两份 Android/host 补丁在新源码上无 fuzz 应用成功。新增 node24_21 公共常量, 保留之前的槽位常量; 已暂存为新的不可变本地 nodejs-api:1.5.0 (不覆盖 1.4.0), publication、契约 JVM 9/9 与 API mirror 10 文件通过, AIDL 事务摘要不变。宿主常量镜像独立提交 0757cb296; 未修改宿主执行行为或对外发布。
2026-09-09 最终晋级完成: 默认 slot 切为
node24_21, 使用三 ABI 自建 Node 24.21.0 / OpenSSL 3.5.8, 新增独立node_runtime_adapter_24_21.cpp及官方 122 份头文件, 保留旧 adapter。实际 process.versions.node、getRuntimeInfo、PluginInfo、catalog、资源和十语言 README/CHANGELOG 一致。新本地 Runtime Kit 1.4.0 为releaseReady: true, 引用 catalog 1.4.0 与 nodejs-api 1.5.0; 原已发布 1.3.0 快照和先前本地 API 1.4.0 快照保持不变。源码管线消除了 M10.1 等待第三方 Android 二进制的阻塞, 其历史记录保留。 Node 24.21 新增的 OpenSSL STORE 密钥 URL 曾在小米实证绕过/proc边界; 三 ABI 源码加入 Android 专用最小拒绝补丁,crypto.createPrivateKey/crypto.sign的 URL 输入返回ERR_ACCESS_DENIED, 通过 node:fs 读取的密钥字节和已有 KeyObject 签名/验签继续成功。保留复现失败及修复日志, 回归纳入 BuiltinPassthroughSmokeTest。三 ABI 的 Debug/Release 桥各通过 36 个动态嵌入符号、36 个直接导入和 adapter C ABI 导出检查。 三台真机 (小米 API35、Sony XQ-AT72 API31、Sony G8441 API28) 与 x86_64 API36 AVD 均完成 Debug 26 类 OK (52 tests)、Inspector/冷启动各 1/1 和配套混淆 Release OK (52 tests); Sony API28 每组包含 1 个既有 SDK>=30 Assume 跳过, 实际执行 51 项。三 ABI 原生 CLI crypto/SQLite/worker/本地 fetch 通过; 小米宿主异步工作区 + 完整 bridge conformance 6/6, 宿主最终提交0757cb296。冷启动组暖执行 P95 为小米 182 / Sony XQ-AT72 234 / Sony G8441 531 / AVD 190 ms, 不将单次测量当作性能保证。 v1.3.0 / versionCode 145 四份正式签名候选 APK 与配套 Release 测试包已离线收集。四包逐一通过 apksigner、zipalign、CRC32、版本/ABI、完整许可证、所有实际 ELF 的 SHA-256/Build ID/LOAD 对齐、嵌入 kit/catalog 字节与 kit BuildConfig 摘要检查; native payload 与完整回归时相同。最终收集包在小米 arm64、Sony G8441 armv7、x86_64 AVD 与小米 universal 各通过 SimpleRun/NpmEcosystem/Info/Manifest 4/4, 合计 16/16, 无跳过。75 JVM、47 样例、TypeScript、59=59=59 能力对齐、10 文件 API mirror、API publication、35 生成文档和 Python 2/2 均通过。构建任务曾因 Release 测试变体不含 Debug 单测、根级任务误加 :app 前缀而在任务选择时失败, 已分开按正确任务路径执行通过, 不计作编译或设备失败。 16 KB 覆盖明确为 x86_64 AVD 的用户空间模拟: getconf PAGE_SIZE=16384, /proc/self/smaps KernelPageSize=4 kB。arm64 真机均为 4 KB; 未验证 16 KB arm64 实体设备。全部源码容器已完成退出, 临时 AVD 已关闭, Sony 临时 All Files appop 已恢复 default。完整日志与工件核验表在本机build/m17/node2421-*, 正式候选在app/releases/1.3.0/; 本次尚未 push/tag/创建 GitHub Release 或对外发布新 catalog/runtime-kit, 这些动作仍按通用约定第 2 条等待当次确认。M14/M15 人工验收与 M13.1 原行数指标不因运行时晋级而自动完成。 -
M17.3 体积与安装占用评估: 2026-09-08 完成下表评估, 保留压缩打包、
--with-intl=none和 inspector 后端。原计划的“安装 -110 MB”“small-icu -20 MB”不适用于当前实际产物: AGP 已 strip native 库, 未压缩 APK 自身也占安装空间, 当前运行时没有 ICU/Intl。Java 加载入口已是System.loadLibrary, C++dlopen("libnode.so")可复用已加载库, 无需修改加载实现; Gradle 旧注释已校正。未采纳新的瘦身开关。- 同一 M16.3 Debug 代码构建压缩/未压缩两组, 三 ABI 的原生 ZIP 条目分别为 DEFLATED/STORED; 每组每设备 force-stop 后测 1 次冷执行 + 20 次同进程新 isolate, 计时包含进程绑定、首次 readiness/prewarm 与首脚本。三个 Node 源码构建容器在两组测量期间暂停, 之后恢复; AVD 仍受主机调度影响。压缩测量三端各 1/1, 未压缩测量 + SimpleRun 三端各 2/2; 测后已恢复三端原压缩 APK。单次冷样本用于本轮取舍, 不构成稳定加速结论。
- 以下下载为实际 Debug APK MiB, 安装为
du -sk测得/data/app/...代码目录 MiB (含 APK/抽取库/当时已有 oat 等, 不含应用数据与测试 APK), 冷启动为 ms; 箭头表示压缩 → 未压缩。
| 方案 / 设备 | 下载体积 | 安装代码占用 | 冷启动 / 暖执行中位数 | 风险与决定 |
|---|---|---|---|---|
| APK 直接映射 / Xiaomi arm64, API 35 | 29.01 → 85.43 MiB | 113.46 → 85.51 MiB | 747 → 699 / 181 → 179 ms | 下载增加 56.42 MiB, 安装节省 27.95 MiB; 保留压缩 |
| APK 直接映射 / Sony armv7, API 28 | 27.91 → 77.42 MiB | 104.28 → 77.46 MiB | 990 → 1011 / 471 → 472 ms | 下载增加 49.52 MiB, 安装节省 26.82 MiB; 保留压缩 |
| APK 直接映射 / x86_64 AVD, API 36, 16 KB | 31.19 → 90.92 MiB | 121.04 → 90.92 MiB | 2961 → 2401 / 473 → 362 ms | 16 KB 直接映射可执行; 下载增加 59.73 MiB, 安装节省 30.11 MiB; 保留压缩 |
--with-intl=small-icu |
未另行构建测量; 相对当前 none 会新增 ICU | 无现成 ICU 可裁减 | 未测 | 三端 process.versions.icu 均缺失且 typeof Intl === 'undefined'; 保持 none, 需要 Intl 时另按功能需求评估 |
Release --without-inspector |
未另行构建测量 | 未测, 不宣称节省数值 | 未测 | M10.2 Debug 调试需要后端, 裁减需维护 Debug/Release 两套三 ABI 库; 当前不采用。默认脚本 process.features.inspector === false 是公开能力档位, 不能据此判断后端未编译 |
测量日志位于本机 build/m17/packaging-{compressed,uncompressed}-<serial>.txt, 代码目录占用与 APK ZIP 明细同目录留存; 它们是此次维护记录, 不挂默认构建门禁。Node 24.21 的最终 Release 测量补充如下。
2026-09-09 Node 24.21 最终签名候选 (v1.3.0 / build 145) 的实际下载体积如下; 仍为压缩 native 打包, 不据此推算安装占用或与上表 Debug 数据直接比较。
| APK | 实际字节 | MiB | CRC32 |
|---|---|---|---|
| arm64-v8a | 24,576,793 | 23.44 | 0A8FBC51 |
| armeabi-v7a | 23,760,115 | 22.66 | D69F0A04 |
| universal | 74,046,090 | 70.62 | 57085A26 |
| x86_64 | 26,123,832 | 24.91 | 53FCD1DA |
- M17.4 月度安全复查制度化: 2026-09-08 首次手动复查完成。每月首个维护工作日由维护者检查 Node 24.x 发布、Node 安全公告 与 OpenSSL 3.5 公告, 在下表追加当月一行, 保留检查日期、实际嵌入版本、影响判断与动作; 有影响即推进 M17.1/M17.2, 未产出并验收前不标“已晋级”。复查按月手动执行, 不加入 APK/PR 默认构建或设备网络流程; 下次为 2026-10 首个维护工作日。
| 复查日期 | 上游最新 24.x | 本插件版本 | 结论 |
|---|---|---|---|
| 2026-08-25 | 24.17.0 | 24.5.0 | 上游 Android 产物缺失, 阻塞 (M10.1) |
| 2026-09-04 | (待 M17.4 首次复查) | 24.5.0 | 立项 M17.1 自建管线解除阻塞 |
| 2026-09-08 | 影响, 尚未晋级。Node 6 月安全发布 与 7 月安全发布 修复 TLS/HTTP2/DNS/crypto 等原生入口问题; 24.5.0 早于修复版本 24.17.0/24.18.1, 本插件已开放相关模块, 不能用桥权限代替修复。 | 当前 24.5.0; 本次源码目标为 24.20.0 LTS, 2026-08-26 | M17.1 三 ABI 源码构建与 M17.2 设备晋级处理中。OpenSSL 2026-08-25 公告 的修复版本为 3.5.8; 24.20.0 官方源码 VERSION.dat 仍为 3.5.7, 因此不能将 Node 升级等同于全部 OpenSSL 公告已修复。该组涉及 OpenSSL QUIC/CMS/CMP/DTLS/RPK/EVP_Cipher 特定入口, 本次未单独证明插件可达性, 保留依赖版本受影响判断并跟踪上游集成。 |
| 2026-09-09 | 24.21.0 LTS, 含 OpenSSL 3.5.8 / Undici 7.29.1 | 已本地晋级 24.21.0 / OpenSSL 3.5.8 | M17.1/M17.2 三 ABI 源码与独立复建比较、三台真机 + x86_64 AVD 及最终四包验收完成, 解除旧 Android 产物阻塞。嵌入 OpenSSL 已达到上一行公告的修复版本; 本地额外修复实证 STORE 密钥 URL 绕过文件边界。该结论针对本次已核对版本与回归, 不声明所有漏洞或所有路径均已穷尽; 对外发布待用户当次确认, 下次月度复查仍为 2026-10。 |
- ❌ 不再新增任何 probe / 能力目录 / 所有权策略 / 哈希锁类基础设施。
- ❌ 不做请求级多层防御性校验 (同一个值不在 Java/C++/JS 三层各验一遍)。
- ❌ 不追求发布工件的可复现性证明链 (哈希锁), 版本号 + git tag 足够。(M17.1 的 "同输入两次构建一致" 是自建管线的质量检查, 不是对外证明链, 不与本条冲突。)
- ❌ 不为未发生过的异常写处理代码; 异常发生后针对该异常修复并附一个最小回归用例。
- ❌ (2026-09-04 增补) 不做设备端 npm registry 下载 (M9.3 决策); 不做 V8 startup snapshot (M10.3 决策, 除非新实机证据); 不做 hardened sandbox / 隔离进程用户代码沙箱 (安全交给 Android 权限, hardened-sandbox / sandboxed-script 样例按 M11.7 处理); 不做 native addon (
.node) 加载 (Android 无生态产物,process.dlopen保持禁用); 不做远程 inspector 监听 (仅 localhost + adb forward)。
- 完整 ESM linker 与 live-binding 循环依赖 — 2026-08-27 完成:ESM entry 与
dynamic
import()已从 snapshot 式 partial transform 切换到 V8vm.SourceTextModule/vm.SyntheticModule;受控 resolver、packageexports/imports、module source overlay、JSON import attribute 与工作目录边界继续 作为解析权威。模块 record 在递归 link 前进入 canonical cache,由 V8 负责 instantiate/evaluate、TDZ、top-level await、export cell、re-export 与循环图。NodeRuntimePluginAndroidConformanceTest#x3d_08_esmCyclePreservesLiveBindingsThroughReExport在 API 35 Xiaomi 23046RP50C 上输出initial=1、updated=42,并断言原生诊断esm_linker=vm_source_text_module、esm_live_bindings=true;完整 conformance 类 10/10 通过。Release 三 ABI + universal 构建通过;本轮 APK 的 versionCode 为 61, 构建脚本随后按既有规则把version.properties推进至下一构建号 62。 CommonJSrequire(esm)的同步 adapter 明确保留为互操作边界,不冒充 ESM live binding。该项对宿主 Binder contract 仅新增 native payload additive keys, 不修改 AIDL transaction、workspace schema 或请求版本。 - T5-1 运行时 TypeScript 按需编译 — 2026-08-29 完成: module-source provider
独立升级为 additive v3, 运行时在快照未命中时只从 execution-scoped 私有 workspace
no-follow 精确读取 lowercase
.ts/.mts/.cts, 将源码通过 PFD + byte count + SHA-256 交回宿主编译。v3 compile 使用独立 30 s transport budget, 普通 v1/v2 operation 仍为 5 s; 旧 provider 回退保持 snapshot not-found。成功 JS 只进入可变的 null-prototype execution module table, 响应生成路径与编译期间源文件 identity 均再次校验; path escape, symlink, declaration, generated collision 与 extensionless ambiguity 继续 fail closed。 native payload 新增 on-demand count/source-bytes, Host provider 同时报告 compile/failure count。最终 versionCode 63 的 arm64 APK 在 API 35 Xiaomi 23046RP50C 与宿主配套完成 3/3 真机验收: 运行期.mts成功执行, TS2322 返回稳定可读诊断, 动态异常栈回映到late-stack.mts:3且不含.mjs帧。runtime contract 仍为 2, AIDL transaction 与 workspace schema 均未改变。