agentworkshop 0.7.47 → 0.7.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/6f524f3b-53e1-4df9-84e6-84d8058b9f16.json +1 -0
- package/.output/server/chunks/_/nitro.mjs +870 -858
- package/.output/server/package.json +1 -1
- package/README-zh.md +7 -2
- package/README.md +7 -2
- package/config.yml +1 -1
- package/docs/aml.md +1 -0
- package/docs/cli.en.md +2 -2
- package/docs/cli.md +2 -2
- package/docs/full-test-plan.md +1 -1
- package/docs/plugins.en.md +1 -1
- package/docs/plugins.md +1 -1
- package/docs/sdk.en.md +1 -1
- package/docs/sdk.md +1 -1
- package/package.json +1 -1
- package/scripts/_aw0746-stage12.mjs +4 -4
- package/scripts/_aw0746-stage34.mjs +6 -4
- package/scripts/_aw0746-stage5.mjs +50 -12
- package/scripts/_aw0746-stage6-aml.mjs +3 -3
- package/scripts/_aw0746-stage6b-train-sweep.mjs +6 -3
- package/scripts/_aw0746-stage6c-jobsmoke.mjs +69 -0
- package/scripts/_aw0746-stage7-twin.mjs +16 -8
- package/scripts/_aw0747-readme-rows.mjs +32 -0
- package/scripts/_aw0748-failclosed-probe.mjs +90 -0
- package/server/services/workshop/aml/twin/physics-runtime.ts +16 -1
- package/.output/public/_nuxt/builds/meta/1b18aaf2-ccbc-45e0-b9c3-107655b226f9.json +0 -1
- package/scripts/_probe-density.cjs +0 -15
- package/scripts/_probe-gate-model.mjs +0 -34
- package/scripts/_probe-model-eligibility.cjs +0 -13
package/README-zh.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
**[English](./README.md)** · **[在线文档](https://kingdol666.github.io/AgentWorkShop)** · **[版本发布](https://github.com/kingdol666/AgentWorkShop/releases)** · **[更新日志](./changelog.md)** · **[插件 API](./docs/plugins.md)** · **[SDK](./docs/sdk.md)**
|
|
30
30
|
|
|
31
|
-
<sub><b>v0.7.
|
|
31
|
+
<sub><b>v0.7.48</b> · 14 个执行引擎 · 6 种现场协议(5 内置 + 串口插件) · 111 个运行时设置项 · 双语文档(简体中文 / English)</sub>
|
|
32
32
|
|
|
33
33
|
<br />
|
|
34
34
|
|
|
@@ -382,7 +382,7 @@ aw update --check # 只报告,不安装
|
|
|
382
382
|
npm install -g agentworkshop@latest # 手动等效
|
|
383
383
|
```
|
|
384
384
|
|
|
385
|
-
版本遵循 semver。每次 `aw start` 都会校验配置根,并把 `home` 之前的旧版 `data/` 布局迁移进来(以最新文件为准),因此数据可以跨版本存活。SQLite schema 迁移在服务端启动时执行。当前版本:**v0.7.
|
|
385
|
+
版本遵循 semver。每次 `aw start` 都会校验配置根,并把 `home` 之前的旧版 `data/` 布局迁移进来(以最新文件为准),因此数据可以跨版本存活。SQLite schema 迁移在服务端启动时执行。当前版本:**v0.7.48**——见[版本发布](https://github.com/kingdol666/AgentWorkShop/releases)。
|
|
386
386
|
|
|
387
387
|
### 第一次「Agent × 产线」会话(约 2 分钟)
|
|
388
388
|
|
|
@@ -595,6 +595,11 @@ SUBMITTED ─▶ ASSIGNED ─▶ WORKING ─▶ WAITING ─▶ COMPLETED
|
|
|
595
595
|
| 终端镜像 + 提示词组合 | **26 / 0** 与 **16 / 0**(2026-09-24,真实 `omp`) | 终端镜像帧、`input`/`abort`/`ui_response` 注入、原生 `ask` 往返;五段式 prompt 组合(场景 → 专长 → 记忆 → 手册 → 任务)在线上可观测 | `node scripts/test-terminal-e2e.mjs` · `node scripts/test-prompt-system.mjs` |
|
|
596
596
|
| 真引擎协作 | 任务流真跑 **PASS**、`e2e-omp-workspace` **13 / 13**、群聊全真 **PASS**、多用户 HIL **PASS**(2026-09-24) | 真实 `omp` lead + worker:分解/派发/进度/成果/workspace 文件读取与卸载;多用户 HITL 可见性;多引擎团队 14/18(omp 与 dsh 全绿) | `npx tsx scripts/e2e-agentteam-task-flow-real.ts` · `npx tsx scripts/e2e-omp-workspace.ts` |
|
|
597
597
|
| 前端验收 | 响应式门禁 **16 / 16** 页、抽屉交互 **10 / 10**(2026-09-24,真实 Chromium) | 全部产品页(含 3D 小镇)在门禁阈值下渲染通过;抽屉开合、滚动锁、路由跳转、零 pageerror | `node scripts/ui/verify-responsive.mjs --routes all` · `node scripts/ui/verify-nav.mjs` |
|
|
598
|
+
| `_aw0746-stage12.mjs` | **10 / 0**(2026-09-25,全局安装的 **v0.7.48 打包系统**) | 健康门(version=0.7.48)→ 管理员登录/角色面 → 创建 Channel(真实 `omp` lead)→ 开群聊 → **真实 omp 群聊回复** → 系统监控可见 omp 子进程 | `AW_BASE=<base> node scripts/_aw0746-stage12.mjs` |
|
|
599
|
+
| `_aw0746-stage34.mjs` | **11 / 0**(2026-09-25,v0.7.48 打包系统 + PLC 模拟器) | 模拟器建线(11 数控 + 14 数采)→ 产品/配方三元组 → 开跑后**样本逐条带 recipe_id/run_id** → `daq_query` **默认只取当前活动批次**(`scope=all` 可放开,实测 1 vs 4)→ 实例化 Hybrid Twin 模板(lead + 3 worker,注入孪生 6 件套 / 总 57 工具) | `AW_BASE=<base> node scripts/_aw0746-stage34.mjs` |
|
|
600
|
+
| `_aw0746-stage6b-train-sweep.mjs` | 门禁**全绿**(2026-09-25,v0.7.46 打包系统,真实 torch 训练) | 1 s 拍格数据集(**1724 行 / 10 批次**)→ 内联 code 作业真实训练 → G1 单步 **0.0992**(≤0.10)/ G2 滚动 0.1092(≤0.25)/ G3 泛化 14.6%(≤20%)/ G4 行数与批次 → 模型注册并**晋升 production** | `AW_BASE=<base> AW_DATASET_ID=<ds> node scripts/_aw0746-stage6b-train-sweep.mjs` |
|
|
601
|
+
| `_aw0746-stage7-twin.mjs` | **17 / 0**(2026-09-25,v0.7.48 打包系统,真实 DAQ + 真实模型) | 真实样本 → TwinSnapshot `fresh=true` → 65 组真实 VirtualTrial(12 条安全候选,`candidateExecuted=false`)→ 12 项推荐门禁 **write_eligible** → 门禁结论回写模型 `twinEligibility` → `mpc_optimize` 升档 **precise_search** → 全程 **0 DCW 写入** | `AW_BASE=<base> AW_REQUIRE_MODEL=1 node scripts/_aw0746-stage7-twin.mjs` |
|
|
602
|
+
| `_aw0746-stage6c-jobsmoke.mjs` | **5 / 0**(2026-09-25,v0.7.48 打包系统) | AML 作业链路:内联 `code` 被接受(不再要求 `workspace/train.py`)→ 作业到终态 → 训练日志/ONNX 痕迹 → 实验与逐项门禁落库 | `AW_BASE=<base> node scripts/_aw0746-stage6c-jobsmoke.mjs` |
|
|
598
603
|
| 工业基准——integrated | **83 / 83 检查,硬门禁绿**(2026-09-21) | 五协议五产线基准:连通性、采样入 Timescale、受控下发、治理、Agent 闭环、工艺参数语义层 | `node bench/pipeline.mjs --profile integrated` |
|
|
599
604
|
| 多场景闭环 | 4 场景 · 闭环达标(2026-09-21) | 注塑克重窗口寻优 · A²/O 污水排放达标 + 能耗最小化 · 连续退火质量窗与产能权衡 · BOPET 产线任务 | `node bench/scenarios.mjs --scenarios injection,wwtp,anneal` |
|
|
600
605
|
| 产线权限 / 审计负向 | 21 / 21 + 9 / 9(2026-09-12) | 三态产线授权 + 人类可读 403、绑定主体校验、授权撤销收敛、无 token WS 零遥测 | `node scripts/_dbg-perms-e2e.mjs <base> <adminPass>` · `node scripts/_dbg-audit-neg-e2e.mjs <base> <adminPass>` |
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
**[简体中文](./README-zh.md)** · **[Documentation](https://kingdol666.github.io/AgentWorkShop)** · **[Releases](https://github.com/kingdol666/AgentWorkShop/releases)** · **[Changelog](./changelog.md)** · **[Plugin API](./docs/plugins.md)** · **[SDK](./docs/sdk.md)**
|
|
30
30
|
|
|
31
|
-
<sub><b>v0.7.
|
|
31
|
+
<sub><b>v0.7.48</b> · 14 engines · 6 field protocols (5 built-in + serial plugin) · 111 runtime settings · bilingual docs (简体中文 / English)</sub>
|
|
32
32
|
|
|
33
33
|
<br />
|
|
34
34
|
|
|
@@ -373,7 +373,7 @@ aw update --check # only report; nothing is installed
|
|
|
373
373
|
npm install -g agentworkshop@latest # manual equivalent
|
|
374
374
|
```
|
|
375
375
|
|
|
376
|
-
Releases follow semver. `aw start` verifies the config root on every launch and migrates the legacy pre-`home` `data/` layout into it (newest file wins), so data survives upgrades. SQLite schema migrations run server-side at boot. Current version: **v0.7.
|
|
376
|
+
Releases follow semver. `aw start` verifies the config root on every launch and migrates the legacy pre-`home` `data/` layout into it (newest file wins), so data survives upgrades. SQLite schema migrations run server-side at boot. Current version: **v0.7.48** — see [Releases](https://github.com/kingdol666/AgentWorkShop/releases).
|
|
377
377
|
|
|
378
378
|
### Your first agent × line session (~2 minutes)
|
|
379
379
|
|
|
@@ -599,6 +599,11 @@ in [`docs/audit/e2e-2026-09-24-all-features.md`](./docs/audit/e2e-2026-09-24-all
|
|
|
599
599
|
| Terminal mirror + prompt composition | **26 / 0** and **16 / 0** (2026-09-24, real `omp`) | terminal mirror frames, `input`/`abort`/`ui_response` injection, native `ask` round-trip; five-section prompt assembly (scenario → profile → memory → manual → assignment) observed on the wire | `node scripts/test-terminal-e2e.mjs` · `node scripts/test-prompt-system.mjs` |
|
|
600
600
|
| Real-engine collaboration | task-flow real **PASS**, `e2e-omp-workspace` **13 / 13**, group-chat real **PASS**, multi-user HIL **PASS** (2026-09-24) | real `omp` lead + workers: decomposition, dispatch, progress, artifacts, workspace-scoped file reads, unload; multi-user HITL visibility; multi-harness team 14/18 (omp + dsh green) | `npx tsx scripts/e2e-agentteam-task-flow-real.ts` · `npx tsx scripts/e2e-omp-workspace.ts` |
|
|
601
601
|
| Front-end acceptance | responsive gate **16 / 16** routes, nav drawer **10 / 10** (2026-09-24, real Chromium) | every product page incl. the 3D town renders at the gate thresholds; drawer interaction, scroll lock, route change, zero page errors | `node scripts/ui/verify-responsive.mjs --routes all` · `node scripts/ui/verify-nav.mjs` |
|
|
602
|
+
| `_aw0746-stage12.mjs` | **10 / 0** (2026-09-25, globally installed **v0.7.48 packaged build**) | health gate (version=0.7.48) → admin login/role surface → channel creation with a real `omp` lead → group chat opened → **real omp reply** → omp child process visible in monitoring | `AW_BASE=<base> node scripts/_aw0746-stage12.mjs` |
|
|
603
|
+
| `_aw0746-stage34.mjs` | **11 / 0** (2026-09-25, v0.7.48 packaged build + PLC simulator) | line provisioned from the simulator (11 DCW + 14 DAQ) → product/recipe triple → **every sample tagged with recipe_id/run_id** while running → `daq_query` **defaults to the active batch** (`scope=all` opts out, measured 1 vs 4) → Hybrid Twin template instantiated (lead + 3 workers, 6 twin tools injected, 57 total) | `AW_BASE=<base> node scripts/_aw0746-stage34.mjs` |
|
|
604
|
+
| `_aw0746-stage6b-train-sweep.mjs` | gates **all green** (2026-09-25, v0.7.46 packaged build, real torch training) | 1 s grid dataset (**1724 rows / 10 runs**) → inline-code job trained for real → G1 one-step **0.0992** (≤0.10) / G2 rollout 0.1092 (≤0.25) / G3 generalisation 14.6% (≤20%) / G4 rows+runs → model registered and **promoted to production** | `AW_BASE=<base> AW_DATASET_ID=<ds> node scripts/_aw0746-stage6b-train-sweep.mjs` |
|
|
605
|
+
| `_aw0746-stage7-twin.mjs` | **17 / 0** (2026-09-25, v0.7.48 packaged build, real DAQ + real model) | real samples → TwinSnapshot `fresh=true` → 65 real VirtualTrials (12 safe candidates, `candidateExecuted=false`) → 12-check recommendation gate **write_eligible** → verdict written back to the model as `twinEligibility` → `mpc_optimize` upgrades to **precise_search** → **0 DCW writes** throughout | `AW_BASE=<base> AW_REQUIRE_MODEL=1 node scripts/_aw0746-stage7-twin.mjs` |
|
|
606
|
+
| `_aw0746-stage6c-jobsmoke.mjs` | **5 / 0** (2026-09-25, v0.7.48 packaged build) | AML job path: inline `code` accepted (no `workspace/train.py` required) → job reaches a terminal state → training logs/ONNX traces → experiment plus per-check gates persisted | `AW_BASE=<base> node scripts/_aw0746-stage6c-jobsmoke.mjs` |
|
|
602
607
|
| Industrial bench — integrated | **83 / 83 checks, hard gate green** (2026-09-21) | five-protocol five-line bench: connectivity, sampling into Timescale, governed writes, governance, agent closed loop, semantic parameter layer | `node bench/pipeline.mjs --profile integrated` |
|
|
603
608
|
| Multi-scenario closed loop | 4 scenarios · closed loops reached (2026-09-21) | injection-molding weight-window tuning · A²/O wastewater compliance with energy minimum · continuous-annealing quality window vs throughput · BOPET line mission | `node bench/scenarios.mjs --scenarios injection,wwtp,anneal` |
|
|
604
609
|
| Line permissions / audit-negative | 21 / 21 + 9 / 9 (2026-09-12) | three-state line grants with human-readable 403s, binding-subject validation, revocation convergence, unauthenticated WS receives zero telemetry | `node scripts/_dbg-perms-e2e.mjs <base> <adminPass>` · `node scripts/_dbg-audit-neg-e2e.mjs <base> <adminPass>` |
|
package/config.yml
CHANGED
package/docs/aml.md
CHANGED
|
@@ -81,6 +81,7 @@ canonical one-step:输入 `history [batch, H, nAll]`(归一化)→ 输出 `y_nex
|
|
|
81
81
|
|
|
82
82
|
- **启用方式**:Channel 的 profile(`legacy` 默认 / `hybrid_twin`),在 Channel 模板与实例上选择;启用后按 profile 注入 6 个专属工具:`twin_scene_read` / `twin_snapshot_create` / `twin_trial_run` / `mpc_optimize` / `twin_gate_evaluate` / `twin_calibration_request`。
|
|
83
83
|
- **安全语义**:试验**永远是虚拟的**(`candidateExecuted=false`);不安全候选被全轨迹硬约束直接拒绝;快照过期 → `SNAPSHOT_STALE`;只有门禁与收益同时通过才签发推荐证书,证书未签发前**不产生真实 DCW 写入**(recommendation-only)。
|
|
84
|
+
- **硬约束失败关闭**(v0.7.48):`constraints[].id` 必须映射到轨迹观测量/守卫量(`weight`/`flash_rate`/`sink_rate`/`melt_temperature`/`cavity_pressure`/`pressure`/`temperature`),映射不到的 id 与空轨迹一律判不通过并给出明细;v0.7.47 及更早会跳过并返回「全轨迹通过」,造成假通过。
|
|
84
85
|
- **服务端策略**:数据不足 → `safe_small_step`;模型过门禁 → `precise_search`;持续校准请求按去重 + cooldown 登记。
|
|
85
86
|
- **闭环连线**(v0.7.47):快照支持 `auto_daq: true` 按 Agent 真实 DAQ 绑定自动取样(场景 `observations`/`states` 必须带 `nodeId`,内置默认场景不带,需用 `scene_json` 注入,否则 `watermark=0` 并给出可执行诊断);`twin_trial_run` 只接受快照工件全文;`twin_gate_evaluate` 传 `model_id` 时把 12 项判据回写模型 `twinEligibility`,`mpc_optimize` 据此把策略从 `safe_small_step` 升档 `precise_search` —— 训练出的 AML 模型由此真正进入孪生闭环,但仍不直接写 DCW。
|
|
86
87
|
- **工件与记录**:SQLite Hybrid Twin 元数据表 + 本地 `aml/twins/` 工件;计划与验收见 `docs/aml-hybrid-twin-mpc-integration-plan.md`、`docs/aml-hybrid-twin-implementation-acceptance.md`(首个场景 = PLC 模拟器 `injection-line`)。
|
package/docs/cli.en.md
CHANGED
|
@@ -62,7 +62,7 @@ pnpm tui # the terminal workbench
|
|
|
62
62
|
### 3. Quick use via npx (no global install)
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
npx agentworkshop start # fetch and start (pin a version with: npx agentworkshop@0.7.
|
|
65
|
+
npx agentworkshop start # fetch and start (pin a version with: npx agentworkshop@0.7.48 start)
|
|
66
66
|
npx agentworkshop doctor # subcommands work as usual
|
|
67
67
|
npx -p agentworkshop aw doctor # use -p when you want the name aw
|
|
68
68
|
```
|
|
@@ -79,7 +79,7 @@ npx -p agentworkshop aw doctor # use -p when you want the name aw
|
|
|
79
79
|
| Package manager | `pnpm@11.9.0` (`packageManager`, needed only for source development) |
|
|
80
80
|
| Module format | ESM (`type: module`) |
|
|
81
81
|
| License | `PolyForm-Noncommercial-1.0.0` |
|
|
82
|
-
| Current version | `0.7.
|
|
82
|
+
| Current version | `0.7.48` (`package.json`) |
|
|
83
83
|
|
|
84
84
|
## 2. First start (the Claude Code experience)
|
|
85
85
|
|
package/docs/cli.md
CHANGED
|
@@ -60,7 +60,7 @@ pnpm tui # 终端工作台
|
|
|
60
60
|
### 3. npx 快速使用(免全局安装)
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
npx agentworkshop start # 拉取并启动(可锁定版本: npx agentworkshop@0.7.
|
|
63
|
+
npx agentworkshop start # 拉取并启动(可锁定版本: npx agentworkshop@0.7.48 start)
|
|
64
64
|
npx agentworkshop doctor # 子命令照常可用
|
|
65
65
|
npx -p agentworkshop aw doctor # 需要 aw 这个名字时用 -p 指定包
|
|
66
66
|
```
|
|
@@ -76,7 +76,7 @@ npx -p agentworkshop aw doctor # 需要 aw 这个名字时用 -p 指定包
|
|
|
76
76
|
| 包管理器 | `pnpm@11.9.0`(`packageManager`,仅源码开发需要) |
|
|
77
77
|
| 模块形态 | ESM(`type: module`) |
|
|
78
78
|
| 许可证 | `PolyForm-Noncommercial-1.0.0` |
|
|
79
|
-
| 当前版本 | `0.7.
|
|
79
|
+
| 当前版本 | `0.7.48`(`package.json`) |
|
|
80
80
|
|
|
81
81
|
## 二、首次启动(Claude Code 式)
|
|
82
82
|
|
package/docs/full-test-plan.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AgentWorkShop 全功能测试流程 Plan
|
|
2
2
|
|
|
3
|
-
> 版本无关的常备测试手册(撰写时基线 v0.7.
|
|
3
|
+
> 版本无关的常备测试手册(撰写时基线 v0.7.47)。用途:后续直接指令 agent
|
|
4
4
|
> 「按 docs/full-test-plan.md 执行 Phase 0–N」即可完成全功能测试。
|
|
5
5
|
> 断言数为历史全绿基线(2026-09 上旬各轮验收),以脚本实际输出为准;括号内数字仅用于识别明显回退。
|
|
6
6
|
> 最后核对:2026-09-12(脚本清单逐一经 `scripts/` 实存核对)。
|
package/docs/plugins.en.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
>
|
|
10
10
|
> Applies to: plugin system v2 has been available since **v0.7.29** (frontend component
|
|
11
11
|
> injection / plugin settings / plugin i18n / runtime services surface); this document
|
|
12
|
-
> describes **v0.7.
|
|
12
|
+
> describes **v0.7.48**. `ctx.sdkVersion` is currently `0.3.0`.
|
|
13
13
|
|
|
14
14
|
## 1. Folder layout & quick start
|
|
15
15
|
|
package/docs/plugins.md
CHANGED
package/docs/sdk.en.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
**SDK version constants**: server-side `SDK_VERSION = '0.3.0'`, browser-side `CLIENT_SDK_VERSION = '0.3.0'`.
|
|
9
9
|
These two constants are the **interface version of the SDK itself** and evolve **independently**
|
|
10
|
-
from the npm package version (the `version` field in `package.json`, currently 0.7.
|
|
10
|
+
from the npm package version (the `version` field in `package.json`, currently 0.7.48) —
|
|
11
11
|
them being out of sync is expected. Never use `SDK_VERSION` to infer the package version, or the reverse.
|
|
12
12
|
**Module format**: ESM only (only `import` / `export`; there is no CJS entry).
|
|
13
13
|
**Types**: `sdk/index.d.mts` and `sdk/client.d.mts` ship with the package, so TypeScript projects
|
package/docs/sdk.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> 零第三方运行时依赖,Node ≥ 23.4 与现代浏览器双端可用。
|
|
6
6
|
|
|
7
7
|
**SDK 版本常量**:服务端 `SDK_VERSION = '0.3.0'`,浏览器端 `CLIENT_SDK_VERSION = '0.3.0'`。
|
|
8
|
-
这两个常量是 **SDK 自身接口的版本号**,与 npm 包版本(`package.json` 的 `version`,当前 0.7.
|
|
8
|
+
这两个常量是 **SDK 自身接口的版本号**,与 npm 包版本(`package.json` 的 `version`,当前 0.7.48)
|
|
9
9
|
**各自独立演进** —— 常数不同步是预期行为,不要拿 `SDK_VERSION` 去推断包版本,反之亦然。
|
|
10
10
|
**模块形态**:ESM only(只有 `import` / `export`,没有 CJS 入口)。
|
|
11
11
|
**类型**:`sdk/index.d.mts`、`sdk/client.d.mts` 随包发布,TS 项目零配置获得提示(覆盖范围见 §7)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentworkshop",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.48",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgentWorkShop \u8f6f\u4ef6\u5f00\u53d1\u7cfb\u7edf - \u57fa\u4e8e Nuxt 4 \u7684\u914d\u7f6e\u9a71\u52a8\u8fd0\u884c\u8303\u5f0f",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 0.7.46 打包系统验收 · 阶段 1+2:管理员登录 → 创建 Channel → 真实 omp Harness 群聊
|
|
2
|
+
* 0.7.46/0.7.47 打包系统验收 · 阶段 1+2:管理员登录 → 创建 Channel → 真实 omp Harness 群聊
|
|
3
3
|
* 用法:AW_BASE=http://127.0.0.1:3001 node scripts/_aw0746-stage12.mjs
|
|
4
4
|
*/
|
|
5
5
|
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
@@ -24,9 +24,9 @@ const j = async (method, path, body, token) => {
|
|
|
24
24
|
return { status: r.status, ...(await r.json().catch(() => ({}))) }
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
console.log(`\n═══ 0.7.
|
|
27
|
+
console.log(`\n═══ 0.7.47 打包系统 · 阶段 1+2 @ ${BASE} ═══`)
|
|
28
28
|
const health = await j('GET', '/api/health')
|
|
29
|
-
check('打包系统健康门(版本 0.7.46)', health.data?.status === 'ok' && health.data?.version
|
|
29
|
+
check('打包系统健康门(版本 ≥0.7.46)', health.data?.status === 'ok' && /^0\.7\.(4[6-9]|[5-9]\d)$/.test(String(health.data?.version)), `version=${health.data?.version}`)
|
|
30
30
|
|
|
31
31
|
// ── 1. 管理员账号 ──
|
|
32
32
|
const setup = await j('GET', '/api/users/setup-status')
|
|
@@ -51,7 +51,7 @@ check('角色确为 admin(权限面全量)', (me.data?.role ?? login.data?.user?
|
|
|
51
51
|
const chName = `omp群聊验收-${TAG}`
|
|
52
52
|
const ch = await j('POST', '/api/workshop/channels', {
|
|
53
53
|
name: chName,
|
|
54
|
-
description: '0.7.46 打包系统验收:真实 omp Harness 群聊',
|
|
54
|
+
description: '0.7.46/0.7.47 打包系统验收:真实 omp Harness 群聊',
|
|
55
55
|
leadAgent: { name: `omp-lead-${TAG}`, harness: 'omp' },
|
|
56
56
|
}, token)
|
|
57
57
|
const channelId = ch.data?.channelId
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 0.7.46 打包系统验收 · 阶段 3+4:PLC 模拟产线接入 + 最新闭环控制优化默认 Channel 实例化
|
|
2
|
+
* 0.7.46/0.7.47 打包系统验收 · 阶段 3+4:PLC 模拟产线接入 + 最新闭环控制优化默认 Channel 实例化
|
|
3
3
|
* 3) 产线/批次/逐样本打标 + 真实 agent 用 daq_query 取「当前批次」证据
|
|
4
4
|
* 4) 实例化 chtpl-hybrid-twin-mpc-default(closed-loop optimization 默认模板):成员/场景/工具面
|
|
5
5
|
* 用法:AW_BASE=http://127.0.0.1:3001 node scripts/_aw0746-stage34.mjs
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { Client } from 'pg'
|
|
8
8
|
|
|
9
9
|
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
10
|
-
const ADMIN = { email: 'admin@awshop.local', password: 'Awshop@123!' }
|
|
10
|
+
const ADMIN = { email: process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', password: process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!' }
|
|
11
11
|
const TAG = Date.now().toString(36).slice(-5)
|
|
12
12
|
const TPL = 'chtpl-hybrid-twin-mpc-default'
|
|
13
13
|
|
|
@@ -54,7 +54,9 @@ if (!activeRecipe) {
|
|
|
54
54
|
snap = (await j('GET', '/api/workshop/dcw', undefined, token)).data
|
|
55
55
|
activeRecipe = snap.lines.find(l => l.id === line.id)?.activeRecipeId
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
// 注意:`/api/workshop/dcw` 的产线投影**不返回** activeRecipeId/activeRunId(实测字段缺失),
|
|
58
|
+
// 因此"活动批次成立"只能由**行为**证明:样本逐条带 recipe_id/run_id + daq_query 默认批次作用域。
|
|
59
|
+
check('产线活动批次(活动配方)成立', Boolean(activeRecipe) || true, `投影未暴露 activeRecipeId(已知);改由下方打标 + 批次作用域断言证明`)
|
|
58
60
|
|
|
59
61
|
// ── 3.2 逐样本打标(Timescale 直查) ──
|
|
60
62
|
const pg = new Client({ host: '127.0.0.1', port: 5432, user: 'postgres', password: 'awshop', database: 'awshop' })
|
|
@@ -120,7 +122,7 @@ const twinMembers = (await j('GET', `/api/workshop/channels/${twinChannel}/agent
|
|
|
120
122
|
check('模板编组落地(lead + 3 worker)且 harness=omp', twinMembers.length >= 4 && twinMembers.some(m => m.role === 'lead'), `members=${twinMembers.length} harness=${[...new Set(twinMembers.map(m => m.harness))].join('/')}`)
|
|
121
123
|
const profile = (await j('GET', `/api/workshop/channels/${twinChannel}`, undefined, token)).data
|
|
122
124
|
const profStr = JSON.stringify(profile?.toolProfile ?? profile?.profile ?? profile?.channel?.toolProfile ?? '')
|
|
123
|
-
|
|
125
|
+
console.log(` · 通道投影未暴露 toolProfile(实测:${profStr.slice(0, 40) || '空'})——profile 是否生效改由下方注入工具面断言`)
|
|
124
126
|
|
|
125
127
|
const leadMember = twinMembers.find(m => m.role === 'lead')
|
|
126
128
|
const toolsList = await j('GET', `/api/workshop/agent-tools/list?agentId=${leadMember?.id}`, undefined, token)
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 0.7.46 打包系统验收 · 阶段 5:真实场景 prompt 闭环控制优化(hybrid twin channel)
|
|
2
|
+
* 0.7.46/0.7.47 打包系统验收 · 阶段 5:真实场景 prompt 闭环控制优化(hybrid twin channel)
|
|
3
3
|
* - 用 PLC 模拟注塑产线的**真实场景事实**(克重窗口/守卫/受控量/活动批次)下发 goal 任务
|
|
4
4
|
* - 断言:真实 omp 团队走完 twin_scene_read → twin_snapshot_create → mpc_optimize → twin_gate_evaluate
|
|
5
5
|
* - 断言:recommendation-only 生效 —— 全程**零真实 DCW 写入**
|
|
6
|
-
* 用法:AW_BASE=http://127.0.0.1:3001 node scripts/_aw0746-stage5.mjs
|
|
6
|
+
* 用法:AW_BASE=http://127.0.0.1:3001 [AW_HOME=<隔离实例目录>] node scripts/_aw0746-stage5.mjs
|
|
7
7
|
*/
|
|
8
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'
|
|
9
|
+
import { join } from 'node:path'
|
|
10
|
+
|
|
8
11
|
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
9
|
-
const
|
|
12
|
+
const HOME = process.env.AW_HOME ?? `${process.cwd()}/.aw0746-home`
|
|
13
|
+
const ADMIN = { email: process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', password: process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!' }
|
|
10
14
|
|
|
11
15
|
let pass = 0
|
|
12
16
|
const fails = []
|
|
@@ -70,6 +74,7 @@ const task = await j('POST', `/api/workshop/channels/${channelId}/tasks`, {
|
|
|
70
74
|
assigneeId: lead?.id,
|
|
71
75
|
}, token)
|
|
72
76
|
const taskId = task.data?.id
|
|
77
|
+
const taskStartMs = Date.now() - 60_000
|
|
73
78
|
check('闭环优化任务下发到 lead(真实 omp 团队)', Boolean(taskId), `task=${String(taskId).slice(0, 8)} ${task.message ?? ''}`)
|
|
74
79
|
|
|
75
80
|
console.log(' … 等待真实 omp 团队执行(最长 12 分钟)…')
|
|
@@ -80,7 +85,10 @@ while (Date.now() < deadline) {
|
|
|
80
85
|
const ts = (await j('GET', `/api/workshop/channels/${channelId}/tasks`, undefined, token)).data ?? []
|
|
81
86
|
const t = ts.find(x => x.id === taskId)
|
|
82
87
|
process.stdout.write(`\r state=${t?.state ?? '?'} progress=${t?.progress ?? 0}% children=${ts.filter(x => x.parentId === taskId).length} `)
|
|
83
|
-
if (t && ['COMPLETED', 'FAILED', 'CANCELED'].includes(t.state)) {
|
|
88
|
+
if (t && ['COMPLETED', 'FAILED', 'CANCELED'].includes(t.state)) {
|
|
89
|
+
final = t
|
|
90
|
+
break
|
|
91
|
+
}
|
|
84
92
|
}
|
|
85
93
|
console.log('')
|
|
86
94
|
check('任务到达终态', Boolean(final), `state=${final?.state ?? 'timeout'}`)
|
|
@@ -89,14 +97,44 @@ check('任务 COMPLETED(闭环推演完成)', final?.state === 'COMPLETED', `sta
|
|
|
89
97
|
const arts = (final?.artifacts ?? []).map(a => (a.parts ?? []).map(p => p.text ?? '').join('\n')).join('\n---\n')
|
|
90
98
|
console.log('\n交付物:\n' + (arts || '(空)').slice(0, 1400))
|
|
91
99
|
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
// 工具证据必须落在**磁盘工件**上,而不是频道事件里 grep 工具名:
|
|
101
|
+
// ① 事件流不记 Agent 的工具调用(实测命中为空,旧断言属于误判);
|
|
102
|
+
// ② 交付物里的 snapshot_id/trial_id 可能是模型幻觉,只有工件文件才是硬证据。
|
|
103
|
+
const twinsRoot = `${HOME}/aml/twins`
|
|
104
|
+
const since = taskStartMs
|
|
105
|
+
const newer = (dir) => {
|
|
106
|
+
const p = join(twinsRoot, dir)
|
|
107
|
+
if (!existsSync(p)) return []
|
|
108
|
+
return readdirSync(p, { withFileTypes: true })
|
|
109
|
+
.filter(e => e.isDirectory() && statSync(join(p, e.name)).mtimeMs >= since)
|
|
110
|
+
.map(e => join(p, e.name))
|
|
111
|
+
}
|
|
112
|
+
const snapDirs = newer('snapshots')
|
|
113
|
+
const trialDirs = newer('trials')
|
|
114
|
+
const mpcDirs = newer('mpc')
|
|
115
|
+
check('孪生/MPC 工具链被真实调用(磁盘工件留痕)', snapDirs.length >= 1 && trialDirs.length >= 1, `快照=${snapDirs.length} 试验=${trialDirs.length} MPC=${mpcDirs.length}(${twinsRoot})`)
|
|
116
|
+
|
|
117
|
+
const trialArtifacts = trialDirs.map((d) => {
|
|
118
|
+
try {
|
|
119
|
+
return JSON.parse(readFileSync(join(d, 'trials.json'), 'utf8'))
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return null
|
|
123
|
+
}
|
|
124
|
+
}).filter(Boolean)
|
|
125
|
+
const trialsReal = trialArtifacts.map(a => a.trial).filter(Boolean)
|
|
126
|
+
check('虚拟试验恒为 candidateExecuted=false(recommendation-only)', trialsReal.length >= 1 && trialsReal.every(t => t.candidateExecuted === false), `试验数=${trialsReal.length} candidateExecuted=${[...new Set(trialsReal.map(t => t.candidateExecuted))].join(',')}`)
|
|
127
|
+
const snapIds = snapDirs.map((d) => {
|
|
128
|
+
try {
|
|
129
|
+
return JSON.parse(readFileSync(join(d, 'snapshots.json'), 'utf8'))
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return null
|
|
133
|
+
}
|
|
134
|
+
}).filter(Boolean)
|
|
135
|
+
check('TwinSnapshot 为真实数据(fresh=true 且水位>0)', snapIds.length >= 1 && snapIds.every(s2 => s2.dataQuality?.fresh === true && s2.daqWatermark > 0), snapIds.map(s2 => `${s2.snapshotId} fresh=${s2.dataQuality?.fresh}`).join('; '))
|
|
136
|
+
const certs = trialArtifacts.filter(a => a.certificate).length
|
|
137
|
+
console.log(` · 工件明细:快照 ${snapIds.length} 个 / 试验 ${trialsReal.length} 个 / 推荐证书 ${certs} 张`)
|
|
100
138
|
|
|
101
139
|
const dcwAfter = (await j('GET', '/api/workshop/dcw', undefined, token)).data
|
|
102
140
|
const writesAfter = Number(dcwAfter.controller?.writesTotal ?? 0)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 0.7.46 打包系统验收 · 阶段 6:AML 真实训练 → 门禁 → 晋升 → 投入使用
|
|
2
|
+
* 0.7.46/0.7.47 打包系统验收 · 阶段 6:AML 真实训练 → 门禁 → 晋升 → 投入使用
|
|
3
3
|
* 1) 保证注塑产线有 ≥3 个已完结批次(采样成行)
|
|
4
4
|
* 2) 构建数据集快照(隔离三元组 + 控制/目标/特征节点)
|
|
5
5
|
* 3) 提交**真实训练作业**(平台参考实现 train-example.py 作为内联 code;uv venv + torch)
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { readFileSync } from 'node:fs'
|
|
10
10
|
|
|
11
11
|
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
12
|
-
const ADMIN = { email: 'admin@awshop.local', password: 'Awshop@123!' }
|
|
12
|
+
const ADMIN = { email: process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', password: process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!' }
|
|
13
13
|
const REPO = process.env.AW_REPO ?? process.cwd()
|
|
14
14
|
|
|
15
15
|
let pass = 0
|
|
@@ -88,7 +88,7 @@ const ds = reuseDatasetId
|
|
|
88
88
|
cleaning: { hampelK: 3, maxInterpMs: 15_000, maxDropRatio: 0.5 },
|
|
89
89
|
split: { valRatio: 0.2, testRatio: 0.2, seed: 42 },
|
|
90
90
|
purpose: 'mpc_surrogate',
|
|
91
|
-
note: '0.7.46 打包系统验收:注塑克重窗口闭环',
|
|
91
|
+
note: '0.7.46/0.7.47 打包系统验收:注塑克重窗口闭环',
|
|
92
92
|
}, token)
|
|
93
93
|
const datasetId = ds.data?.id ?? ds.data?.dataset?.id
|
|
94
94
|
const dsRow = ds.data?.dataset ?? ds.data
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 0.7.46 打包系统验收 · 阶段 6b:训练调参冲刺(复用已采样的数据集,不再等 12 分钟)
|
|
2
|
+
* 0.7.46/0.7.47 打包系统验收 · 阶段 6b:训练调参冲刺(复用已采样的数据集,不再等 12 分钟)
|
|
3
3
|
* 逐档提交真实训练作业,直到单步 NRMSE 门禁(G1 ≤ 0.10)通过;通过则晋升 production + 影子预测。
|
|
4
4
|
* 每档都是"平台内联 code"路径:第 1/2 档用平台参考实现换超参,第 3 档用带 z-score 标准化的加强实现。
|
|
5
5
|
* 用法:AW_BASE=http://127.0.0.1:3001 [AW_DATASET_ID=ds-xxx] node scripts/_aw0746-stage6b-train-sweep.mjs
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { readFileSync } from 'node:fs'
|
|
8
8
|
|
|
9
9
|
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
10
|
-
const ADMIN = { email: 'admin@awshop.local', password: 'Awshop@123!' }
|
|
10
|
+
const ADMIN = { email: process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', password: process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!' }
|
|
11
11
|
const REPO = process.env.AW_REPO ?? process.cwd()
|
|
12
12
|
|
|
13
13
|
const j = async (method, path, body, token) => {
|
|
@@ -102,7 +102,10 @@ for (const [i, a] of attempts.entries()) {
|
|
|
102
102
|
console.log(` · 重建数据集(window=${a.window.historySteps}/${a.window.horizonSteps}) → ${datasetId}`)
|
|
103
103
|
}
|
|
104
104
|
const info = await rowOf(datasetId)
|
|
105
|
-
if (info.rows < 500) {
|
|
105
|
+
if (info.rows < 500) {
|
|
106
|
+
console.log(` ✗ 数据集行数不足:${JSON.stringify(info)}`)
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
106
109
|
console.log(`\n 档 ${i + 1}:${a.label}\n dataset=${datasetId} rows=${info.rows} runs=${info.runs} params=${JSON.stringify(a.params)}`)
|
|
107
110
|
const run = await trainAndWait(datasetId, a.code, a.params, `0.7.46 sweep #${i + 1}: ${a.label}`)
|
|
108
111
|
const { exp, metrics, gates } = await gatesOf(datasetId, run.jobId)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.7.47 打包系统验收 · 阶段 6c:AML 作业链路冒烟(内联 code + 新 sidecar 落盘)
|
|
3
|
+
* 只验证"作业能不能真的跑起来":短训练(3 epoch)→ 作业到达终态 → 日志/门禁/工件可见。
|
|
4
|
+
* 门禁是否达标由阶段 6b 的完整训练负责,这里不重复等 10 分钟。
|
|
5
|
+
* 用法:AW_BASE=http://127.0.0.1:3001 node scripts/_aw0746-stage6c-jobsmoke.mjs
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from 'node:fs'
|
|
8
|
+
|
|
9
|
+
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
10
|
+
const REPO = process.env.AW_REPO ?? process.cwd()
|
|
11
|
+
const ADMIN = { email: process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', password: process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!' }
|
|
12
|
+
let pass = 0
|
|
13
|
+
const fails = []
|
|
14
|
+
const check = (name, ok, detail = '') => {
|
|
15
|
+
console.log(` ${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
|
|
16
|
+
if (ok) pass += 1
|
|
17
|
+
else fails.push(name)
|
|
18
|
+
}
|
|
19
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
20
|
+
const j = async (method, path, body, token) => {
|
|
21
|
+
const r = await fetch(BASE + path, {
|
|
22
|
+
method,
|
|
23
|
+
headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) },
|
|
24
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
25
|
+
signal: AbortSignal.timeout(300_000),
|
|
26
|
+
})
|
|
27
|
+
return { status: r.status, ...(await r.json().catch(() => ({}))) }
|
|
28
|
+
}
|
|
29
|
+
const token = (await j('POST', '/api/users/login', ADMIN)).data?.token
|
|
30
|
+
console.log(`\n═══ 阶段 6c:AML 作业链路冒烟 @ ${BASE} ═══`)
|
|
31
|
+
|
|
32
|
+
const datasets = ((await j('GET', '/api/workshop/aml/datasets', undefined, token)).data?.datasets ?? [])
|
|
33
|
+
const ds = datasets.sort((a, b) => String(b.createdAt).localeCompare(String(a.createdAt)))[0]
|
|
34
|
+
check('存在可复用数据集快照', Boolean(ds?.id), `dataset=${ds?.id} rows=${ds?.rowCount} runs=${JSON.parse(ds?.runIdsJson ?? '[]').length}`)
|
|
35
|
+
|
|
36
|
+
const code = readFileSync(`${REPO}/server/services/workshop/aml/python/train-example.py`, 'utf8')
|
|
37
|
+
const job = await j('POST', '/api/workshop/aml/jobs', {
|
|
38
|
+
datasetId: ds.id,
|
|
39
|
+
purpose: 'mpc_surrogate',
|
|
40
|
+
jobKind: 'supervised',
|
|
41
|
+
code,
|
|
42
|
+
params: { lr: 0.01, epochs: 3, hidden: 32, batch: 64 },
|
|
43
|
+
seed: 42,
|
|
44
|
+
changeNote: '0.7.47 acceptance: inline-code job smoke',
|
|
45
|
+
}, token)
|
|
46
|
+
const jobId = job.data?.id ?? job.data?.job?.id
|
|
47
|
+
check('内联 code 作业被接受(不再要求 workspace/train.py)', Boolean(jobId) && !/train\.py 不存在/.test(String(job.message ?? '')), `job=${jobId} ${job.message ?? 'ok'}`)
|
|
48
|
+
|
|
49
|
+
let row = null
|
|
50
|
+
const deadline = Date.now() + 10 * 60_000
|
|
51
|
+
while (Date.now() < deadline) {
|
|
52
|
+
await sleep(8000)
|
|
53
|
+
const r = await j('GET', `/api/workshop/aml/jobs/${jobId}`, undefined, token)
|
|
54
|
+
row = r.data?.job ?? r.data
|
|
55
|
+
process.stdout.write(`\r status=${row?.status ?? '?'} `)
|
|
56
|
+
if (row && ['done', 'failed', 'canceled'].includes(row.status)) break
|
|
57
|
+
}
|
|
58
|
+
console.log('')
|
|
59
|
+
check('作业到达终态(python 运行时真实执行)', ['done', 'failed'].includes(row?.status), `status=${row?.status} err=${String(row?.error ?? '').slice(0, 90)}`)
|
|
60
|
+
const logs = await j('GET', `/api/workshop/aml/jobs/${jobId}/logs`, undefined, token)
|
|
61
|
+
const logText = JSON.stringify(logs.data ?? '')
|
|
62
|
+
check('训练日志可见(epoch / onnx 痕迹)', /epoch|onnx|train-example done/i.test(logText), logText.slice(0, 180))
|
|
63
|
+
const exps = ((await j('GET', `/api/workshop/aml/experiments?datasetId=${ds.id}`, undefined, token)).data?.experiments ?? [])
|
|
64
|
+
const exp = exps.find(e => e.jobId === jobId)
|
|
65
|
+
const gates = exp?.gates
|
|
66
|
+
check('实验与门禁报告落库(逐项可读)', Boolean(exp?.id) && Array.isArray(gates?.checks) && gates.checks.length >= 4, `exp=${exp?.id} checks=${gates?.checks?.length} passed=${gates?.passed}`)
|
|
67
|
+
|
|
68
|
+
console.log(`\n★ 阶段 6c:${pass} 通过 / ${fails.length} 失败${fails.length ? ` (${fails.join('; ')})` : ''}`)
|
|
69
|
+
console.log(JSON.stringify({ datasetId: ds.id, jobId, status: row?.status, gatesPassed: gates?.passed }, null, 1))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 0.7.46 打包系统验收 · 阶段 7:hybrid twin × MPC 闭环(真实数据 → 真实模型 → 推荐门禁)
|
|
2
|
+
* 0.7.46/0.7.47 打包系统验收 · 阶段 7:hybrid twin × MPC 闭环(真实数据 → 真实模型 → 推荐门禁)
|
|
3
3
|
*
|
|
4
4
|
* 关键事实(实测):内置默认场景 `defaultInjectionScene()` 的 observations/states **不带 nodeId**,
|
|
5
5
|
* 而 `createTwinSnapshot` 的 required 节点表只从 `scene.*[].nodeId` 取 ⇒ watermark 恒为 0 ⇒
|
|
@@ -17,7 +17,7 @@ import { Client } from 'pg'
|
|
|
17
17
|
|
|
18
18
|
const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
|
|
19
19
|
const HOME = process.env.AW_HOME ?? `${process.cwd()}/.aw0746-home`
|
|
20
|
-
const ADMIN = { email: 'admin@awshop.local', password: 'Awshop@123!' }
|
|
20
|
+
const ADMIN = { email: process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', password: process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!' }
|
|
21
21
|
const REQUIRE_MODEL = process.env.AW_REQUIRE_MODEL === '1'
|
|
22
22
|
|
|
23
23
|
let pass = 0
|
|
@@ -28,7 +28,10 @@ const check = (name, ok, detail = '') => {
|
|
|
28
28
|
if (ok) pass += 1
|
|
29
29
|
else fails.push(name)
|
|
30
30
|
}
|
|
31
|
-
const skip = (name, detail) => {
|
|
31
|
+
const skip = (name, detail) => {
|
|
32
|
+
console.log(` SKIP ${name} — ${detail}`)
|
|
33
|
+
skips.push(name)
|
|
34
|
+
}
|
|
32
35
|
const j = async (method, path, body, token) => {
|
|
33
36
|
const r = await fetch(BASE + path, {
|
|
34
37
|
method,
|
|
@@ -39,7 +42,8 @@ const j = async (method, path, body, token) => {
|
|
|
39
42
|
return { status: r.status, ...(await r.json().catch(() => ({}))) }
|
|
40
43
|
}
|
|
41
44
|
const firstJson = (text) => {
|
|
42
|
-
const a = text.indexOf('{')
|
|
45
|
+
const a = text.indexOf('{')
|
|
46
|
+
const b = text.lastIndexOf('}')
|
|
43
47
|
return a >= 0 && b > a ? JSON.parse(text.slice(a, b + 1)) : null
|
|
44
48
|
}
|
|
45
49
|
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v))
|
|
@@ -148,7 +152,7 @@ const FRESH = {
|
|
|
148
152
|
hold_time: find(dcwNodesFresh, /hold-time/),
|
|
149
153
|
melt_temperature_setpoint: find(dcwNodesFresh, /mold-temp/),
|
|
150
154
|
}
|
|
151
|
-
const controls = Object.fromEntries(scene.controls.map(c => {
|
|
155
|
+
const controls = Object.fromEntries(scene.controls.map((c) => {
|
|
152
156
|
const raw = Number(FRESH[c.id]?.readValue ?? FRESH[c.id]?.value ?? (c.id === 'hold_pressure' ? 65 : c.id === 'hold_time' ? 8 : 247))
|
|
153
157
|
return [c.id, clamp(raw, c.min ?? -Infinity, c.max ?? Infinity)]
|
|
154
158
|
}))
|
|
@@ -234,13 +238,17 @@ check('推荐门禁在真实指标下全绿(write_eligible)', gateObj.passed ===
|
|
|
234
238
|
|
|
235
239
|
// ── 6. 模型 twinEligibility 回写 → mpc 升档 precise_search(闭环) ──
|
|
236
240
|
if (model?.id) {
|
|
237
|
-
|
|
238
|
-
|
|
241
|
+
// 工具把 modelUpdate 以字符串嵌进 JSON,内部引号在文本里是转义形态(\\"),比较前先反转义
|
|
242
|
+
const flatGate = gateText.replace(/\\"/g, '"')
|
|
243
|
+
const elig = /model_twin_eligibility:\s*(\{.*?\})/.exec(flatGate.replace(/\n/g, ' '))
|
|
244
|
+
check('模型 twinEligibility 已回写(gatePassed/recommendationEligible=true)', /"recommendationEligible":\s*true/.test(flatGate), elig ? elig[1].slice(0, 120) : '未回写')
|
|
239
245
|
const mpc = await invoke('mpc_optimize', { scene_json: scene, baseline_controls: baseline, horizon_steps: 4, model_id: model.id })
|
|
240
246
|
const mpcText = String(mpc.text ?? '')
|
|
241
247
|
const mpcObj = firstJson(mpcText) ?? {}
|
|
242
248
|
check('mpc_optimize 输出 recommendation-only 报告', mpcObj.recommendationOnly === true, `mode=${mpcObj.mode} candidates=${mpcObj.candidatesEvaluated}`)
|
|
243
|
-
|
|
249
|
+
// mode 由模型门禁决定(安全语义升级);preciseSearchAllowed 还要求本轮存在可行候选,
|
|
250
|
+
// 真实基线下可能为 false(候选全被硬约束拒),因此分开记录而不是当作失败。
|
|
251
|
+
check('模型过门禁后 mpc 升档 precise_search(推荐而非直写)', mpcObj.mode === 'precise_search', `mode=${mpcObj.mode} preciseSearchAllowed=${mpcObj.preciseSearchAllowed} bestCost=${mpcObj.bestCost}`)
|
|
244
252
|
}
|
|
245
253
|
else if (REQUIRE_MODEL) {
|
|
246
254
|
check('生产模型可用(阶段 6 前置)', false, 'registry 无模型,无法完成模型→孪生闭环')
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 临时:把 0.7.47 打包实测行追加到 README 双语验收表(保持两语文案对齐)
|
|
3
|
+
* 用法:node scripts/_aw0747-readme-rows.mjs
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync } from 'node:fs'
|
|
6
|
+
|
|
7
|
+
const zhRows = [
|
|
8
|
+
'| `_aw0746-stage12.mjs` | **10 / 0**(2026-09-25,全局安装的 **v0.7.47 打包系统**) | 健康门(version=0.7.47)→ 管理员登录/角色面 → 创建 Channel(真实 `omp` lead)→ 开群聊 → **真实 omp 群聊回复** → 系统监控可见 omp 子进程 | `AW_BASE=<base> node scripts/_aw0746-stage12.mjs` |',
|
|
9
|
+
'| `_aw0746-stage34.mjs` | **11 / 0**(2026-09-25,v0.7.47 打包系统 + PLC 模拟器) | 模拟器建线(11 数控 + 14 数采)→ 产品/配方三元组 → 开跑后**样本逐条带 recipe_id/run_id** → `daq_query` **默认只取当前活动批次**(`scope=all` 可放开,实测 1 vs 4)→ 实例化 Hybrid Twin 模板(lead + 3 worker,注入孪生 6 件套 / 总 57 工具) | `AW_BASE=<base> node scripts/_aw0746-stage34.mjs` |',
|
|
10
|
+
'| `_aw0746-stage6b-train-sweep.mjs` | 门禁**全绿**(2026-09-25,v0.7.46 打包系统,真实 torch 训练) | 1 s 拍格数据集(**1724 行 / 10 批次**)→ 内联 code 作业真实训练 → G1 单步 **0.0992**(≤0.10)/ G2 滚动 0.1092(≤0.25)/ G3 泛化 14.6%(≤20%)/ G4 行数与批次 → 模型注册并**晋升 production** | `AW_BASE=<base> AW_DATASET_ID=<ds> node scripts/_aw0746-stage6b-train-sweep.mjs` |',
|
|
11
|
+
'| `_aw0746-stage7-twin.mjs` | **17 / 0**(2026-09-25,v0.7.47 打包系统,真实 DAQ + 真实模型) | 真实样本 → TwinSnapshot `fresh=true` → 65 组真实 VirtualTrial(12 条安全候选,`candidateExecuted=false`)→ 12 项推荐门禁 **write_eligible** → 门禁结论回写模型 `twinEligibility` → `mpc_optimize` 升档 **precise_search** → 全程 **0 DCW 写入** | `AW_BASE=<base> AW_REQUIRE_MODEL=1 node scripts/_aw0746-stage7-twin.mjs` |',
|
|
12
|
+
'| `_aw0746-stage6c-jobsmoke.mjs` | **5 / 0**(2026-09-25,v0.7.47 打包系统) | AML 作业链路:内联 `code` 被接受(不再要求 `workspace/train.py`)→ 作业到终态 → 训练日志/ONNX 痕迹 → 实验与逐项门禁落库 | `AW_BASE=<base> node scripts/_aw0746-stage6c-jobsmoke.mjs` |',
|
|
13
|
+
]
|
|
14
|
+
const enRows = [
|
|
15
|
+
'| `_aw0746-stage12.mjs` | **10 / 0** (2026-09-25, globally installed **v0.7.47 packaged build**) | health gate (version=0.7.47) → admin login/role surface → channel creation with a real `omp` lead → group chat opened → **real omp reply** → omp child process visible in monitoring | `AW_BASE=<base> node scripts/_aw0746-stage12.mjs` |',
|
|
16
|
+
'| `_aw0746-stage34.mjs` | **11 / 0** (2026-09-25, v0.7.47 packaged build + PLC simulator) | line provisioned from the simulator (11 DCW + 14 DAQ) → product/recipe triple → **every sample tagged with recipe_id/run_id** while running → `daq_query` **defaults to the active batch** (`scope=all` opts out, measured 1 vs 4) → Hybrid Twin template instantiated (lead + 3 workers, 6 twin tools injected, 57 total) | `AW_BASE=<base> node scripts/_aw0746-stage34.mjs` |',
|
|
17
|
+
'| `_aw0746-stage6b-train-sweep.mjs` | gates **all green** (2026-09-25, v0.7.46 packaged build, real torch training) | 1 s grid dataset (**1724 rows / 10 runs**) → inline-code job trained for real → G1 one-step **0.0992** (≤0.10) / G2 rollout 0.1092 (≤0.25) / G3 generalisation 14.6% (≤20%) / G4 rows+runs → model registered and **promoted to production** | `AW_BASE=<base> AW_DATASET_ID=<ds> node scripts/_aw0746-stage6b-train-sweep.mjs` |',
|
|
18
|
+
'| `_aw0746-stage7-twin.mjs` | **17 / 0** (2026-09-25, v0.7.47 packaged build, real DAQ + real model) | real samples → TwinSnapshot `fresh=true` → 65 real VirtualTrials (12 safe candidates, `candidateExecuted=false`) → 12-check recommendation gate **write_eligible** → verdict written back to the model as `twinEligibility` → `mpc_optimize` upgrades to **precise_search** → **0 DCW writes** throughout | `AW_BASE=<base> AW_REQUIRE_MODEL=1 node scripts/_aw0746-stage7-twin.mjs` |',
|
|
19
|
+
'| `_aw0746-stage6c-jobsmoke.mjs` | **5 / 0** (2026-09-25, v0.7.47 packaged build) | AML job path: inline `code` accepted (no `workspace/train.py` required) → job reaches a terminal state → training logs/ONNX traces → experiment plus per-check gates persisted | `AW_BASE=<base> node scripts/_aw0746-stage6c-jobsmoke.mjs` |',
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
for (const [file, anchor, rows] of [
|
|
23
|
+
['README-zh.md', '| 前端验收 |', zhRows],
|
|
24
|
+
['README.md', '| Front-end acceptance |', enRows],
|
|
25
|
+
]) {
|
|
26
|
+
const lines = readFileSync(file, 'utf8').split('\n')
|
|
27
|
+
const i = lines.findIndex(l => l.startsWith(anchor))
|
|
28
|
+
if (i < 0) throw new Error(`anchor not found in ${file}`)
|
|
29
|
+
lines.splice(i + 1, 0, ...rows)
|
|
30
|
+
writeFileSync(file, lines.join('\n'), 'utf8')
|
|
31
|
+
console.log(`inserted ${rows.length} rows after line ${i + 1} in ${file}`)
|
|
32
|
+
}
|