@zaalipro/dsh-workflows 0.1.0-rc.3
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/LICENSE +21 -0
- package/NOTICE.md +224 -0
- package/README.i18n.yaml +4 -0
- package/README.md +109 -0
- package/README.zh.md +109 -0
- package/cordis.patch.yml +10 -0
- package/docs/architecture.i18n.yaml +4 -0
- package/docs/architecture.md +177 -0
- package/docs/architecture.zh.md +177 -0
- package/docs/testing.i18n.yaml +4 -0
- package/docs/testing.md +125 -0
- package/docs/testing.zh.md +125 -0
- package/docs/user-guide.i18n.yaml +4 -0
- package/docs/user-guide.md +351 -0
- package/docs/user-guide.zh.md +351 -0
- package/lib/client-types/WorkflowMemberInspector.d.ts +28 -0
- package/lib/client-types/WorkflowMemberInspector.d.ts.map +1 -0
- package/lib/client-types/WorkflowMemberInspector.js +181 -0
- package/lib/client-types/WorkflowMemberInspector.js.map +1 -0
- package/lib/client-types/WorkflowRunPanel.d.ts +43 -0
- package/lib/client-types/WorkflowRunPanel.d.ts.map +1 -0
- package/lib/client-types/WorkflowRunPanel.js +130 -0
- package/lib/client-types/WorkflowRunPanel.js.map +1 -0
- package/lib/client-types/WorkflowsDashboard.d.ts +49 -0
- package/lib/client-types/WorkflowsDashboard.d.ts.map +1 -0
- package/lib/client-types/WorkflowsDashboard.js +942 -0
- package/lib/client-types/WorkflowsDashboard.js.map +1 -0
- package/lib/client-types/adapter.d.ts +60 -0
- package/lib/client-types/adapter.d.ts.map +1 -0
- package/lib/client-types/adapter.js +117 -0
- package/lib/client-types/adapter.js.map +1 -0
- package/lib/client-types/chat-renderer.d.ts +10 -0
- package/lib/client-types/chat-renderer.d.ts.map +1 -0
- package/lib/client-types/chat-renderer.js +11 -0
- package/lib/client-types/chat-renderer.js.map +1 -0
- package/lib/client-types/contract.d.ts +210 -0
- package/lib/client-types/contract.d.ts.map +1 -0
- package/lib/client-types/contract.js +37 -0
- package/lib/client-types/contract.js.map +1 -0
- package/lib/client-types/controller.d.ts +83 -0
- package/lib/client-types/controller.d.ts.map +1 -0
- package/lib/client-types/controller.js +705 -0
- package/lib/client-types/controller.js.map +1 -0
- package/lib/client-types/index.d.ts +19 -0
- package/lib/client-types/index.d.ts.map +1 -0
- package/lib/client-types/index.js +730 -0
- package/lib/client-types/index.js.map +1 -0
- package/lib/client-types/locales.d.ts +257 -0
- package/lib/client-types/locales.d.ts.map +1 -0
- package/lib/client-types/locales.js +270 -0
- package/lib/client-types/locales.js.map +1 -0
- package/lib/client-types/slot-components.d.ts +38 -0
- package/lib/client-types/slot-components.d.ts.map +1 -0
- package/lib/client-types/slot-components.js +22 -0
- package/lib/client-types/slot-components.js.map +1 -0
- package/lib/client-types/store.d.ts +69 -0
- package/lib/client-types/store.d.ts.map +1 -0
- package/lib/client-types/store.js +135 -0
- package/lib/client-types/store.js.map +1 -0
- package/lib/client-types/workflow-definition.d.ts +52 -0
- package/lib/client-types/workflow-definition.d.ts.map +1 -0
- package/lib/client-types/workflow-definition.js +135 -0
- package/lib/client-types/workflow-definition.js.map +1 -0
- package/lib/client.js +11064 -0
- package/lib/client.js.map +1 -0
- package/lib/compat-engine/index.js +1926 -0
- package/lib/compat-engine/index.js.map +1 -0
- package/lib/compat-engine/worker.cjs +1500 -0
- package/lib/compat-engine/worker.cjs.map +1 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1709 -0
- package/lib/typert.remote-client.d.ts +57 -0
- package/lib/typert.remote-client.js +1662 -0
- package/lib/types/commands/aliases.d.ts +4 -0
- package/lib/types/commands/aliases.d.ts.map +1 -0
- package/lib/types/commands/aliases.js +25 -0
- package/lib/types/commands/aliases.js.map +1 -0
- package/lib/types/commands/index.d.ts +66 -0
- package/lib/types/commands/index.d.ts.map +1 -0
- package/lib/types/commands/index.js +550 -0
- package/lib/types/commands/index.js.map +1 -0
- package/lib/types/commands/parser.d.ts +17 -0
- package/lib/types/commands/parser.d.ts.map +1 -0
- package/lib/types/commands/parser.js +45 -0
- package/lib/types/commands/parser.js.map +1 -0
- package/lib/types/config.d.ts +71 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +109 -0
- package/lib/types/config.js.map +1 -0
- package/lib/types/index.d.ts +41 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +483 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/invariant.d.ts +21 -0
- package/lib/types/invariant.d.ts.map +1 -0
- package/lib/types/invariant.js +85 -0
- package/lib/types/invariant.js.map +1 -0
- package/lib/types/registry/definition.d.ts +24 -0
- package/lib/types/registry/definition.d.ts.map +1 -0
- package/lib/types/registry/definition.js +189 -0
- package/lib/types/registry/definition.js.map +1 -0
- package/lib/types/registry/index.d.ts +100 -0
- package/lib/types/registry/index.d.ts.map +1 -0
- package/lib/types/registry/index.js +899 -0
- package/lib/types/registry/index.js.map +1 -0
- package/lib/types/registry/names.d.ts +19 -0
- package/lib/types/registry/names.d.ts.map +1 -0
- package/lib/types/registry/names.js +69 -0
- package/lib/types/registry/names.js.map +1 -0
- package/lib/types/registry/remote.d.ts +15 -0
- package/lib/types/registry/remote.d.ts.map +1 -0
- package/lib/types/registry/remote.js +128 -0
- package/lib/types/registry/remote.js.map +1 -0
- package/lib/types/registry/roots.d.ts +44 -0
- package/lib/types/registry/roots.d.ts.map +1 -0
- package/lib/types/registry/roots.js +118 -0
- package/lib/types/registry/roots.js.map +1 -0
- package/lib/types/registry/types.d.ts +62 -0
- package/lib/types/registry/types.d.ts.map +1 -0
- package/lib/types/registry/types.js +2 -0
- package/lib/types/registry/types.js.map +1 -0
- package/lib/types/registry/watchers.d.ts +70 -0
- package/lib/types/registry/watchers.d.ts.map +1 -0
- package/lib/types/registry/watchers.js +152 -0
- package/lib/types/registry/watchers.js.map +1 -0
- package/lib/types/remote-events.d.ts +42 -0
- package/lib/types/remote-events.d.ts.map +1 -0
- package/lib/types/remote-events.js +21 -0
- package/lib/types/remote-events.js.map +1 -0
- package/lib/types/run-recorder.d.ts +44 -0
- package/lib/types/run-recorder.d.ts.map +1 -0
- package/lib/types/run-recorder.js +356 -0
- package/lib/types/run-recorder.js.map +1 -0
- package/lib/types/supervisor/canned-validate.d.ts +25 -0
- package/lib/types/supervisor/canned-validate.d.ts.map +1 -0
- package/lib/types/supervisor/canned-validate.js +122 -0
- package/lib/types/supervisor/canned-validate.js.map +1 -0
- package/lib/types/supervisor/completion-notice.d.ts +49 -0
- package/lib/types/supervisor/completion-notice.d.ts.map +1 -0
- package/lib/types/supervisor/completion-notice.js +281 -0
- package/lib/types/supervisor/completion-notice.js.map +1 -0
- package/lib/types/supervisor/cursors.d.ts +68 -0
- package/lib/types/supervisor/cursors.d.ts.map +1 -0
- package/lib/types/supervisor/cursors.js +158 -0
- package/lib/types/supervisor/cursors.js.map +1 -0
- package/lib/types/supervisor/engine-compat.d.ts +48 -0
- package/lib/types/supervisor/engine-compat.d.ts.map +1 -0
- package/lib/types/supervisor/engine-compat.js +116 -0
- package/lib/types/supervisor/engine-compat.js.map +1 -0
- package/lib/types/supervisor/index.d.ts +183 -0
- package/lib/types/supervisor/index.d.ts.map +1 -0
- package/lib/types/supervisor/index.js +2040 -0
- package/lib/types/supervisor/index.js.map +1 -0
- package/lib/types/supervisor/parallel-compat.d.ts +36 -0
- package/lib/types/supervisor/parallel-compat.d.ts.map +1 -0
- package/lib/types/supervisor/parallel-compat.js +180 -0
- package/lib/types/supervisor/parallel-compat.js.map +1 -0
- package/lib/types/supervisor/remote.d.ts +25 -0
- package/lib/types/supervisor/remote.d.ts.map +1 -0
- package/lib/types/supervisor/remote.js +478 -0
- package/lib/types/supervisor/remote.js.map +1 -0
- package/lib/types/supervisor/storage/bounded-file.d.ts +41 -0
- package/lib/types/supervisor/storage/bounded-file.d.ts.map +1 -0
- package/lib/types/supervisor/storage/bounded-file.js +186 -0
- package/lib/types/supervisor/storage/bounded-file.js.map +1 -0
- package/lib/types/supervisor/storage/details-codec.d.ts +14 -0
- package/lib/types/supervisor/storage/details-codec.d.ts.map +1 -0
- package/lib/types/supervisor/storage/details-codec.js +359 -0
- package/lib/types/supervisor/storage/details-codec.js.map +1 -0
- package/lib/types/supervisor/storage/index.d.ts +26 -0
- package/lib/types/supervisor/storage/index.d.ts.map +1 -0
- package/lib/types/supervisor/storage/index.js +100 -0
- package/lib/types/supervisor/storage/index.js.map +1 -0
- package/lib/types/supervisor/storage/lease.d.ts +34 -0
- package/lib/types/supervisor/storage/lease.d.ts.map +1 -0
- package/lib/types/supervisor/storage/lease.js +289 -0
- package/lib/types/supervisor/storage/lease.js.map +1 -0
- package/lib/types/supervisor/storage/manifest-codec.d.ts +10 -0
- package/lib/types/supervisor/storage/manifest-codec.d.ts.map +1 -0
- package/lib/types/supervisor/storage/manifest-codec.js +335 -0
- package/lib/types/supervisor/storage/manifest-codec.js.map +1 -0
- package/lib/types/supervisor/storage/manifest-store.d.ts +99 -0
- package/lib/types/supervisor/storage/manifest-store.d.ts.map +1 -0
- package/lib/types/supervisor/storage/manifest-store.js +1606 -0
- package/lib/types/supervisor/storage/manifest-store.js.map +1 -0
- package/lib/types/supervisor/storage/manifest-types.d.ts +269 -0
- package/lib/types/supervisor/storage/manifest-types.d.ts.map +1 -0
- package/lib/types/supervisor/storage/manifest-types.js +2 -0
- package/lib/types/supervisor/storage/manifest-types.js.map +1 -0
- package/lib/types/supervisor/storage/private-root.d.ts +143 -0
- package/lib/types/supervisor/storage/private-root.d.ts.map +1 -0
- package/lib/types/supervisor/storage/private-root.js +860 -0
- package/lib/types/supervisor/storage/private-root.js.map +1 -0
- package/lib/types/supervisor/storage/recovery.d.ts +14 -0
- package/lib/types/supervisor/storage/recovery.d.ts.map +1 -0
- package/lib/types/supervisor/storage/recovery.js +126 -0
- package/lib/types/supervisor/storage/recovery.js.map +1 -0
- package/lib/types/supervisor/storage/run-files.d.ts +67 -0
- package/lib/types/supervisor/storage/run-files.d.ts.map +1 -0
- package/lib/types/supervisor/storage/run-files.js +346 -0
- package/lib/types/supervisor/storage/run-files.js.map +1 -0
- package/lib/types/supervisor/types.d.ts +295 -0
- package/lib/types/supervisor/types.d.ts.map +1 -0
- package/lib/types/supervisor/types.js +3 -0
- package/lib/types/supervisor/types.js.map +1 -0
- package/lib/types/supervisor/value-view.d.ts +19 -0
- package/lib/types/supervisor/value-view.d.ts.map +1 -0
- package/lib/types/supervisor/value-view.js +183 -0
- package/lib/types/supervisor/value-view.js.map +1 -0
- package/lib/types/tool/index.d.ts +86 -0
- package/lib/types/tool/index.d.ts.map +1 -0
- package/lib/types/tool/index.js +810 -0
- package/lib/types/tool/index.js.map +1 -0
- package/lib/types/tool/schema.d.ts +158 -0
- package/lib/types/tool/schema.d.ts.map +1 -0
- package/lib/types/tool/schema.js +137 -0
- package/lib/types/tool/schema.js.map +1 -0
- package/lib/types/types.d.ts +9 -0
- package/lib/types/types.d.ts.map +1 -0
- package/lib/types/types.js +3 -0
- package/lib/types/types.js.map +1 -0
- package/lib/types/user-questions.d.ts +9 -0
- package/lib/types/user-questions.d.ts.map +1 -0
- package/lib/types/user-questions.js +91 -0
- package/lib/types/user-questions.js.map +1 -0
- package/package.json +273 -0
- package/skills/create-workflow/SKILL.md +166 -0
- package/vendor/workflow-engine/LICENSE +21 -0
- package/vendor/workflow-engine/README.md +1 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# 测试与发布验收
|
|
2
|
+
|
|
3
|
+
[English](testing.md) | 中文
|
|
4
|
+
|
|
5
|
+
本参考把自动化证明与最终人工发布决策分开。绿色 unit suite 绝不能替代下列 official-prerequisite、assembled、packed-consumer、browser、race、provider 或 manual boundary。
|
|
6
|
+
|
|
7
|
+
## 自动化 gate
|
|
8
|
+
|
|
9
|
+
使用冻结的 `pnpm@11.7.0` install,并从 package checkout 运行命令。每个命令在首次失败时非零退出;其后的文字是 CI 或 release log 必须保留的 success marker。
|
|
10
|
+
|
|
11
|
+
### Build、type、lint、coverage 与 docs
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pnpm run build && printf 'package build PASS\n'
|
|
15
|
+
pnpm run typecheck && printf 'package typecheck PASS\n'
|
|
16
|
+
pnpm run lint && printf 'package lint PASS\n'
|
|
17
|
+
pnpm run test:coverage && printf 'package coverage PASS\n'
|
|
18
|
+
node scripts/verify-docs.mjs
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Documentation command 准确输出 `documentation verification passed`。它检查完整 English/Chinese pair 及记录的 blob hash、local file 与 heading fragment、单个 trailing LF、当前 compatibility prose,以及必需的 installation、architecture、testing、user 和 Agent Note coverage。
|
|
22
|
+
|
|
23
|
+
### Keyless assembled snapshot
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pnpm exec vitest run tests/keyless-snapshot.spec.ts --reporter=dot && printf 'RD5 keyless snapshot PASS\n'
|
|
27
|
+
pnpm exec vitest run tests/dashboard-snapshot.client.spec.tsx --reporter=dot && printf 'RD6 dashboard snapshots PASS\n'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`tests/keyless-snapshot.spec.ts` 是 source-resolved fixture:它把官方 `tool-workflow/*` event 送进 `ConversationNodeAssembler`,证明 append/prepend/full-replay 一致,把 Interrupted Chat node 映射为 cancelled,并检查 completion-notice footer。它不启动官方 assembled snapshot harness,也不比较 reviewed Session/stdout JSONL;`examples/workflows-keyless/` 输入仍是后续 assembled gate。Dashboard snapshot 固定 accessible empty、live、terminal、interrupted、disclosure 和 member-outcome semantic,而不是 CSS hash。
|
|
31
|
+
|
|
32
|
+
### Package policy 与 exact packed consumer
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
pnpm exec vitest run tests/verify-package.spec.ts --reporter=dot && printf 'RD3 package policy PASS\n'
|
|
36
|
+
pnpm exec vitest run tests/packed-consumer.spec.ts --reporter=dot && printf 'RD8 packed consumer PASS\n'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Standalone packed-consumer test 只执行一次 `pnpm pack --json`,记录 SHA-256,并把完全相同的绝对 tarball 交给 `scripts/verify-package.mjs --tarball`。发布时由 `scripts/check-release.mjs` 独占 pack ownership,并把同一 artifact 交给 `scripts/packed-consumer.mjs`;generic unit command 排除会自行 pack 的 spec。缺少 skill、client bundle、evaluator 或 required peer asset 会在任何 consumer Session 开始前失败。Runner 以 scripts disabled 安装该 artifact,再安装 pinned consumer-only TypeScript/Node type 以及精确的预构建官方 CLI,import 所有 JavaScript 与 strict NodeNext export,并通过 lazy-CJS seam 加载 `lib/client.js`。所有声明的 Host、Client、Cordis 与 React peer 仍保留精确 compatibility declaration,但都标记为 optional:隔离的 `autoInstallPeers: true` probe 不得 materialize 其中任何一个,而 standalone import/type probe 会显式提供 peer。真实 Web 与 headless profile cycle 必须保留官方 `autoInstallPeers: false`,不得包含 profile-local peer package,所有 peer 都必须通过 healed official fallback 解析,并且 agent-loop 与 agent-presets 解析到的 `dsh-scope` realpath 必须完全相同。随后每个 profile 执行两次 bounded activation/teardown sentinel boot(第二次证明 lease 已释放),再 remove 并验证 manifest restoration。Source-tree runtime fallback、用 `--help` 充当 activation evidence、split Host graph,或发布期间第二次 pack 都是失败。
|
|
40
|
+
|
|
41
|
+
### 自动化 Chromium
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
pnpm exec vitest run tests/browser-smoke.spec.ts --reporter=dot && printf 'RD10 browser automation PASS\n'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`tests/browser-smoke.spec.ts` 当前只覆盖 `scripts/browser-smoke.mjs` helper boundary:absolute argument、loopback readiness JSON、stdin teardown,以及与 caller workspace 隔离。它并不用 Chromium 驱动 slash discovery、disclosure 或 1,199/767/320 px layout。该 product journey 属于下面的最终 Ego Lite checklist,而不是 helper 已经覆盖的替代。
|
|
48
|
+
|
|
49
|
+
### Lifecycle、storage 与 Client stress
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pnpm exec vitest run tests/race-stress.spec.ts --reporter=dot && printf 'RD11 host race stress PASS\n'
|
|
53
|
+
pnpm exec vitest run tests/storage-stress.spec.ts --reporter=dot && printf 'RD12 storage stress PASS\n'
|
|
54
|
+
pnpm exec vitest run tests/client-race-stress.client.spec.ts --reporter=dot && printf 'RD13 client race stress PASS\n'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
这些 deterministic repeated suite 覆盖 aggregate cancellation、pending durable admission、pause/stop/teardown、worker death、completion cohort、advisory-lease contention、link/inode substitution、interrupted publication、stale gate/control/page response、reconnect generation、invalidation overflow 与 cross-Agent authorization。它们断言不存在 orphan worker、child、scratch operation、timer、watcher、controller、request、cursor、selection 或 unhandled rejection。Donor aggregate-cancellation scenario 必须单独以及在 aggregate suite 中重复通过;一次成功 rerun 绝不能免除失败。
|
|
58
|
+
|
|
59
|
+
### Opt-in real provider
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
pnpm exec vitest run tests/real-provider.spec.ts --reporter=dot && printf 'RD14 real provider gate PASS\n'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
存在 `DEEPSEEK_API_KEY` 时,该文件准确启动两个名为 `alpha` 与 `beta` 的 logical child,分别验证 `alpha.txt` 中独立的 `alpha` byte 和 `beta.txt` 中独立的 `beta` byte,验证最终 result `{"alpha":"alpha","beta":"beta"}`,并在 `finally` 中 dispose 每个 child、worker、Agent、Host、lease 和 temporary directory。它只通过官方 provider configuration 读取 `DEEPSEEK_BASE_URL`。任何 value、credential 或 model transcript 都不会进入 log 或 artifact。
|
|
66
|
+
|
|
67
|
+
没有 key 时,只有该文件注册一个 skipped test,reason 准确为 `DEEPSEEK_API_KEY is not set`。其他 package、platform、workflow 或 storage lane 都不能 self-skip。
|
|
68
|
+
|
|
69
|
+
### 精确 official Host checkout
|
|
70
|
+
|
|
71
|
+
Packed consumer 与 CI checkout 官方 DeepSeek Harness `0.1.1-rc.2` commit `b150a551b8d465e31e418e1b2eaf5e79bbb7d28e`。Package build 与 test 针对 `0.1.1-rc.2` development dependency 编译;不使用 Harness source patch 或 fork checkout。Package-owned evaluator build、strict NodeNext consumer、add/boot/remove profile cycle 与 removal 后的 stock boot 都是 blocking release evidence。
|
|
72
|
+
|
|
73
|
+
### 最终自动化 aggregate
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
pnpm run check:release
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
成功时准确以 `release checks passed` 结束。Orchestrator 按顺序运行 clean/frozen-install verification、build、typecheck、lint、owned-source aggregate coverage、snapshot、documentation、package policy、一次 immutable pack 与 packed consumer(`official-host-probe` 加真实 Web/headless add/boot/remove)、browser helper boundary、三个 stress suite 和 opt-in provider file。它不会 publish、启动 Ego Lite 或录制 GIF。Packed profile cycle 针对官方 `0.1.1-rc.2` 是 blocking gate;Chromium product journey 仍是最终 Ego Lite acceptance。
|
|
80
|
+
|
|
81
|
+
## Coverage policy
|
|
82
|
+
|
|
83
|
+
`pnpm run test:coverage` 对 owned package integration source 强制执行真实的 aggregate floor:**80% statement、80% branch、80% function 与 80% line**。它显式只 instrument `src/**/*.{ts,tsx}` 并排除 type-only declaration,因此未被 import 的 owned source 仍计入,而 generated `lib/` 与 `scripts/` 下的 release helper 不会意外进入 denominator。不再声明逐文件 100%;8 月 23 日 baseline 为 85.35% statement/line、80.69% branch 与 84.98% function。该命令排除 packed-consumer、browser-smoke、snapshot、stress 和 real-provider lane。已保存的 `coverage-all` report 并不是 generated `lib/` 加 dependency 的 100%(最近一次约为 57%);它不能替代 owned-source aggregate gate。Test 覆盖 deterministic clock 与 barrier、每个 error/cancellation branch、effect disposal、HMR registration、authorization 和 external world state,而不依赖 self-reported success。
|
|
84
|
+
|
|
85
|
+
唯一不 instrument 的 artifact 是 generated 或 browser-delivery product,而不是 handwritten Host behavior 的例外:
|
|
86
|
+
|
|
87
|
+
| Exclusion | 为何不作为 owned runtime source instrument | 必需证据 |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `vendor/workflow-engine/*.ts` 与 emitted `lib/compat-engine/*` | 带 attribution 的 MIT compatibility evaluator,使用独立 process/worker protocol gate | `tests/compat-engine.spec.ts`、supervisor replay/gate/budget/scratch suite、packed artifact verification 与 live profile smoke |
|
|
90
|
+
| `lib/typert.host.*` 与 `lib/typert.remote-client.*` | 从 decorated Host source 生成 | `tests/build-artifacts.spec.ts`、Remote API test、packed import 与 browser mount smoke |
|
|
91
|
+
| `lib/client.js`、emitted Client declaration/map 与 Lightning CSS output | Generated bundle product | Client component/controller spec、dashboard semantic snapshot、packed serving 与 `tests/browser-smoke.spec.ts` |
|
|
92
|
+
| `src/client/css-modules.d.ts` | 无 executable statement 的 type-only generated-facing declaration | Client TSC 加 build suite source assertion |
|
|
93
|
+
| CSS module visual branch | Style 不进入 JavaScript statement coverage | source token assertion、jsdom semantic snapshot,以及 GUI behavior 改变时最终 Ego Lite real-flow GIF。CI 中的 Automated Chromium 只门禁 `scripts/browser-smoke.mjs`;layout、light/dark 与 reduced-motion 仍是人工 Ego Lite。 |
|
|
94
|
+
|
|
95
|
+
Handwritten Client TypeScript 仍由其 Client test project 覆盖;generated output 不建立并行 coverage denominator。增加其他 exclusion 必须提供相应 real-browser evidence 和显式 testing-policy change。
|
|
96
|
+
|
|
97
|
+
## CI platform matrix
|
|
98
|
+
|
|
99
|
+
Blocking Ubuntu 24.04 job 运行 Node `22.19.0`、`24` 和 `26`;每个 job 使用 frozen lockfile,并覆盖 build、typecheck、lint、docs、package policy 以及分配的 unit/coverage/snapshot gate。Node 24 还拥有 macOS 14、Windows Server 2022、Chromium helper、race-stress 和 release-pack/packed-consumer job。Packed lane checkout 官方 `0.1.1-rc.2` commit `b150a551b8d465e31e418e1b2eaf5e79bbb7d28e`;不应用 Harness patch,只 pack 一次并保留一个 digest 和 artifact path,而且要求 Web 与 headless 的 live add/boot/remove。
|
|
100
|
+
|
|
101
|
+
Windows 运行每个支持的 definition、manifest、scratch、retention、recovery 与 subprocess case。它明确断言 junction/hard-link behavior,以及可工作的 native advisory locking 或已记录的 `WORKFLOW_STORAGE_UNSUPPORTED` result;它绝不静默 skip workflow、把 job 标记为 `continue-on-error`,或在没有断言准确 branch 时把 platform limitation 当作成功。
|
|
102
|
+
|
|
103
|
+
CI 只能在失败后上传 reviewed snapshot、browser、stress 和 pack diagnostic。它绝不上传 DSH home、credential、secret-lane model transcript 或 unrestricted scratch store。Action 固定到完整 commit SHA,permission 默认 read-only,job 有 timeout,而且只有 real-provider file 可因 key 缺失而 skip。
|
|
104
|
+
|
|
105
|
+
## Real-provider secret 与 cleanup policy
|
|
106
|
+
|
|
107
|
+
CI 只在可用时把 `DEEPSEEK_API_KEY` 传给隔离的 provider job。Test 不打印 key 或 base URL,也不把它们复制到 child prompt、session log、screenshot、archive 或 failure diagnostic。Provider error 可以命名 display handle 和 provider failure,绝不能包含 internal run UUID 或 credential material。
|
|
108
|
+
|
|
109
|
+
所有 live resource 都创建在 isolated workspace 与 DSH home 内。`finally` 会 stop 或 settle run、dispose child catalog entry、worker handle、Agent 和 Host、释放 permanent-anchor lease,并且即使 provider failure 或 timeout 也会移除 temporary directory。
|
|
110
|
+
|
|
111
|
+
## Final manual Web acceptance
|
|
112
|
+
|
|
113
|
+
这是 release checklist,不是 coding task、CI step 或 automated Chromium 的替代。只有全部自动化 gate 通过后,才使用安装了完全相同 tested tarball 的真实官方 `0.1.1-rc.2` Web profile 和 real server/model flow 执行。
|
|
114
|
+
|
|
115
|
+
- [ ] 启动 tarball-installed real server,确认 package activation 没有 source checkout fallback。
|
|
116
|
+
- [ ] 使用 **Ego Lite** 完成 smoke journey。全程复用它的 task space;绝不 wipe 或 reset 任何 user session、cookie、browser storage 或 daily-browser state。
|
|
117
|
+
- [ ] 确认 `/create-workflow`、`/workflow`、`/workflows` 和 saved alias 出现;启动两个 run,观察 immediate acknowledgement、display-name numbering、live phase/member/progress update,以及仍可用的 composer。
|
|
118
|
+
- [ ] 打开并关闭 run disclosure 和 `Inspect · N members`;检查真实 text/Markdown 与 JSON outcome、log、result 和 scratch artifact。验证 user-visible 或 accessible text 中没有 internal UUID。
|
|
119
|
+
- [ ] 运行 resumable gate、Pause、Resume、Stop 和符合条件的 Save;确认 stale-revision 与 budget-limited error 保持可见且 actionable。
|
|
120
|
+
- [ ] 检查 focus restoration、keyboard control、screen-reader label、light/dark/reduced-motion behavior 和没有水平 overflow 的 narrow mobile drill-down。
|
|
121
|
+
- [ ] 确认每个符合条件的 run 只有一个 completion notice,而且仅打开 dashboard 不产生重复 `workflows · Completed` row。
|
|
122
|
+
- [ ] 任何 product-visible GUI change 都要从这个 **real PR server/model flow** 录制并保留 GIF,展示 launch、live update、member outcome inspection、control 和 narrow layout。Mocked 或 source-only GIF 不是 release evidence。
|
|
123
|
+
- [ ] 验证完成后,**只关闭 Ego Lite task space**。不要 wipe session、cookie、storage 或不相关 tab/space。
|
|
124
|
+
|
|
125
|
+
在 release evidence 中记录 tested tarball SHA-256、official Host build identity、platform、automated aggregate log、manual result 和 GIF location。即使 automated suite 为绿色,任何失败的 manual item 也会阻止 release。
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# User guide
|
|
2
|
+
|
|
3
|
+
English | [中文](user-guide.zh.md)
|
|
4
|
+
|
|
5
|
+
This tutorial takes a Web or headless user from installation to one saved JavaScript definition, one validation smoke, a background run, detailed inspection, controls, and recovery. A **saved definition** is authoring input on disk; a **live or retained run** is an immutable admitted execution record. `/workflows` lists saved definitions (Start) and live or retained runs.
|
|
6
|
+
|
|
7
|
+
## 1. Install on a compatible Harness
|
|
8
|
+
|
|
9
|
+
Use official DeepSeek Harness `0.1.1-rc.2` with plugin `0.1.0-rc.3`. Ensure `pnpm` is on the service user's `PATH`; `0.1.0-rc.8` and unverified later Harness releases are unsupported.
|
|
10
|
+
|
|
11
|
+
Install a pinned release tag, or the exact tested tarball from a durable absolute path:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
dsh plugin --profile web add github:zaalipro/dsh-workflows#v0.1.0-rc.3
|
|
15
|
+
dsh plugin --profile headless add /absolute/path/zaalipro-dsh-workflows-0.1.0-rc.3.tgz
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
After npm publication, `dsh plugin --profile <profile> add @zaalipro/dsh-workflows@0.1.0-rc.3` is equivalent.
|
|
19
|
+
|
|
20
|
+
Restart the profile. Web gains the dashboard and durable Chat renderer in addition to Host behavior; headless gains registry, supervisor, commands, questions, recorder, and model tool without loading browser code. Removal is covered in the [package README](../README.md#installation).
|
|
21
|
+
|
|
22
|
+
## 2. Create a project definition
|
|
23
|
+
|
|
24
|
+
In a Session whose cwd belongs to the intended project, enter:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
/create-workflow review workspace changes, verify every finding, and write a report
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The command replies exactly:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
Opened the workflow authoring skill.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The command steers that same leading `/create-workflow` user message. The packaged skill is user-invocable, so the compatible Host injects its trusted instructions into that next model step deterministically instead of relying on the model to choose the skill from its catalog.
|
|
37
|
+
|
|
38
|
+
The packaged skill asks for intent, inputs, fan-out, evidence, failure tolerance, final artifact, maximum agents, a lowercase kebab name, and project or user scope. Choose **project** to save `review-changes.workflow.json` under the nearest Git root's `.dsh/workflows` directory. If no Git root exists, the Session cwd is the project root. Choose **user** to save under `$DSH_HOME/workflows`.
|
|
39
|
+
|
|
40
|
+
Definitions resolve with first-wins precedence: configured bundled root, project root, then user root. A higher-precedence same-name definition can keep a newly saved lower-precedence file shadowed. Files must be flat, regular, UTF-8, at most the configured 1 MiB default, and named with a valid lowercase kebab stem.
|
|
41
|
+
|
|
42
|
+
The saved envelope has exactly `meta` and `script`; metadata remains JSON data and the body remains plain JavaScript:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"meta": {
|
|
47
|
+
"name": "review-changes",
|
|
48
|
+
"description": "Review workspace changes and verify every finding",
|
|
49
|
+
"whenToUse": "Before requesting merge",
|
|
50
|
+
"phases": [
|
|
51
|
+
{ "title": "Review", "detail": "Collect bounded evidence" },
|
|
52
|
+
{ "title": "Verify", "detail": "Challenge every retained finding" },
|
|
53
|
+
{ "title": "Report", "detail": "Publish the final artifact" }
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"script": "phase(\"Review\");\n// JavaScript body omitted here; see the complete pattern below."
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Phase titles in `phase(title)` and `agent(..., { phase })` must match metadata titles exactly. Metadata declares presentation; it is never evaluated as host code.
|
|
61
|
+
|
|
62
|
+
## 3. Understand the validation smoke
|
|
63
|
+
|
|
64
|
+
The authoring skill asks the model-facing workflow tool to validate and save the proposed inline source with representative args. `save_scope` defaults to `project`; choose `user` for `$DSH_HOME/workflows`. A user-scope save does not require a Session cwd.
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"script": "<plain JavaScript workflow body>",
|
|
69
|
+
"meta": {
|
|
70
|
+
"name": "review-changes",
|
|
71
|
+
"description": "Review workspace changes and verify every finding"
|
|
72
|
+
},
|
|
73
|
+
"args": { "targets": ["src", "tests"] },
|
|
74
|
+
"validate_only": true,
|
|
75
|
+
"save_scope": "project"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
A successful result has status `validated`, creates no child, run id, directory, display ordinal, dashboard row, completion notice, or durable workflow event, and states:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
Validated one args-selected path with canned agent results; other branches, live tools, and live schema responses were not covered.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The engine parses the **entire** script first, then executes only the path selected by those args with canned schema-shaped agent outputs and an in-memory scratch capability. A gate ends the smoke successfully as `would pause: <message>`. Treat this as syntax, hook-contract, and one-path evidence—not proof of all branches or real provider behavior. Fix any filename/line diagnostic and rerun validation before saving.
|
|
86
|
+
|
|
87
|
+
## 4. Launch a background run
|
|
88
|
+
|
|
89
|
+
The canonical command accepts one saved name and an optional JSON object:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
/workflow review-changes {"targets":["src","tests"]}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
It returns without waiting for agents:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
Started workflow "review-changes" in the background. Open /workflows to watch it.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
When no ordinary slash command collides, the saved definition also has a named alias:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
/review-changes {"targets":["src","tests"]}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
If an ordinary command owns `/review-changes`, that command keeps it and the workflow receives the first free repeated-prefix alias, such as `/workflow-review-changes`; canonical `/workflow review-changes` always works. The first run is `review-changes`, then `review-changes-2`, `review-changes-3`, and so on. These display names are the only handles used by human commands and titles.
|
|
108
|
+
|
|
109
|
+
Bare `/workflow` opens a definition picker in Web and returns this usage in headless:
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
Launch or control a workflow.
|
|
113
|
+
|
|
114
|
+
Usage:
|
|
115
|
+
/workflow <name> [<json-args>]
|
|
116
|
+
/workflow pause <display-name>
|
|
117
|
+
/workflow resume <display-name>
|
|
118
|
+
/workflow stop <display-name>
|
|
119
|
+
/workflow save <display-name>
|
|
120
|
+
|
|
121
|
+
Examples:
|
|
122
|
+
/workflow review-changes {"target":"origin/main...HEAD"}
|
|
123
|
+
/workflow pause review-changes
|
|
124
|
+
/workflow resume review-changes
|
|
125
|
+
/workflow stop review-changes-2
|
|
126
|
+
/workflow save review-changes
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Arguments must be one JSON object. Arrays and scalars fail before launch; malformed trailing text is not repaired or forwarded to the model.
|
|
130
|
+
|
|
131
|
+
## 5. Open the run dashboard
|
|
132
|
+
|
|
133
|
+
In Web, submit exact bare:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
/workflows
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This browser-only slash action opens the dialog labelled `Workflows`; it invokes neither Host command execution nor the model and creates no command Chat row. `/workflows` with arguments or attachments does not open the overlay; it is refused locally with its draft and attachments intact. Dashboard chrome and Chat labels follow the host locale: the package registers English and Chinese dictionaries, English is the fallback, and the close control uses the same `Close workflows` accessible name as the visible label. Inspector headings (`Pending`, `JSON outcome`, and the rest of criterion 11.4) and the exact criterion 11.4/11.11 error strings stay English.
|
|
140
|
+
|
|
141
|
+
The dashboard lists saved definitions with a Start control, then the run navigator (display name, status, current phase, agents spent/total, running and settled member counts, a bounded terminal summary, and retained-run loaded/total disclosure). Active runs sort oldest-first and history sorts by newest settlement. `Load more` fetches the next authorized bounded page; only terminal rows are eligible for deterministic oldest-first retention eviction, never active rows or display ordinal history.
|
|
142
|
+
|
|
143
|
+
At widths of at least 1,200 px, navigator, execution detail, and inspector are independently scrollable panes. Below 1,200 px, navigation and one detail pane remain. Below 768 px, use explicit **Runs -> Execution -> Inspector** drill-down; the same flow works without horizontal page overflow at 320 px.
|
|
144
|
+
|
|
145
|
+
## 6. Inspect execution and members
|
|
146
|
+
|
|
147
|
+
Select a run, then open its run disclosure to see declared/current phases, status, progress, controls, logs, terminal result or error, artifacts, and retention disclosure. Open `Inspect · N members` to reveal the member roster. Running and abnormal groups remain open; a completed clean phase can be collapsed without losing detail.
|
|
148
|
+
|
|
149
|
+
Member lifecycle states are **queued/pending**, **running**, **completed**, **failed**, and **cancelled**. An ordinary child failure is a settled failed member whose script-visible result is JSON `null`; infrastructure failure instead fails the logical run. Select a member to load one distinct outcome presentation:
|
|
150
|
+
|
|
151
|
+
- `Pending`—the member has no settled outcome yet.
|
|
152
|
+
- `JSON outcome`—the complete retained JSON value, including an actual JSON `null`.
|
|
153
|
+
- `Text outcome`—complete Markdown or plain text.
|
|
154
|
+
- `Value outcome`—a retained JSON primitive other than `null`.
|
|
155
|
+
- `Truncated outcome`—a deterministic preview plus retained and total UTF-8 byte counts.
|
|
156
|
+
- `No outcome produced`—the member settled without an output value.
|
|
157
|
+
- `Outcome evicted`—retention deliberately removed the full detail while preserving that fact.
|
|
158
|
+
|
|
159
|
+
`Child transcript unavailable` is separate from the retained outcome: the direct one-shot child address may have disappeared while the outcome remains inspectable. `Unable to load member outcome` with `Retry` is a request failure; prior successful pages and detail remain visible. Child navigation refreshes the current direct-child catalog before opening a transcript and refuses stale or foreign addresses.
|
|
160
|
+
|
|
161
|
+
Logs load in stable index order. Result absence, JSON `null`, truncation, eviction, and request failure render as different facts. Scratch artifacts list safe single-component names and sizes; opening one fetches bounded UTF-8 chunks, and `Load more` continues from a byte cursor adjusted to a complete code-point boundary. A changed, invalid UTF-8, or unsafe artifact fails inline without clearing previously loaded run detail.
|
|
162
|
+
|
|
163
|
+
## 7. Respond to gates
|
|
164
|
+
|
|
165
|
+
`await_user(kind, message)` and `pause(kind, message)` both park a run and surface one `Workflow · <display-name>` question with `Resume workflow`, but their replay semantics differ:
|
|
166
|
+
|
|
167
|
+
- `await_user` acknowledges and resumes the same live engine attempt. The satisfied gate commits, so a later journal replay skips it.
|
|
168
|
+
- `pause` is an uncommitted condition. Acknowledgement starts replay, and the same condition asks again if it remains true.
|
|
169
|
+
|
|
170
|
+
Dismissing, withdrawing, aborting, or answering an obsolete question leaves the run parked. The package resumes only an exact live Session/Agent/logical-run/execution/gate/generation tuple; a late answer cannot resume a newer attempt or another run.
|
|
171
|
+
|
|
172
|
+
## 8. Pause, resume, stop, and save
|
|
173
|
+
|
|
174
|
+
Use dashboard buttons, guarded P/R/X/S shortcuts, or display-name commands:
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
/workflow pause review-changes
|
|
178
|
+
/workflow resume review-changes
|
|
179
|
+
/workflow stop review-changes-2
|
|
180
|
+
/workflow save review-changes
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Successful command replies are exact:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
Paused workflow "review-changes". Open /workflows to resume or stop it.
|
|
187
|
+
Resumed workflow "review-changes". Open /workflows to watch it.
|
|
188
|
+
Stopped workflow "review-changes-2".
|
|
189
|
+
Saved workflow "review-changes" to <path>.
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Pause stops new work, cancels and drains the current attempt, then publishes `paused` only after a quiescent checkpoint is retained. Resume uses the immutable admitted script and args, not later edits to `script.js`; matching committed hooks replay for zero additional spend. Stop cancels admitted children and scratch operations, pairs their endings, discards replay authority, and publishes terminal `cancelled` after cleanup.
|
|
193
|
+
|
|
194
|
+
Save is available only for a non-built-in, unnumbered, non-Interrupted run with a safe live editable projection. A built-in or numbered handle requires an edited copy with a new unique `meta.name`; a lower-precedence saved file may remain shadowed. Save targets project scope by default or the explicit supported user scope.
|
|
195
|
+
|
|
196
|
+
Every dashboard control carries the currently visible revision, disables duplicate submission, and merges the authoritative returned row. If another update wins first, no control side effect occurs and the dashboard says:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
workflow run changed; refresh it before applying a control
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Every other non-domain control failure shows `Unable to update workflow. Retry.` with a labelled `Retry`, while abort and stale-selection failures remain quiet.
|
|
203
|
+
|
|
204
|
+
## 9. Handle budgets, completion, and process exit
|
|
205
|
+
|
|
206
|
+
`budget()` returns `{ total, spent, reserved: 0, remaining }`. The default total is 128 and an admitted run may use an absolute cap from 1 through 1,024. Spend is cumulative across same-process attempts; journal replay and schema-correction retries spend zero. Declarative `parallel()` panels preflight all unreplayed jobs atomically, while arbitrary thunks admit each concrete `agent()` call because their future count is unknowable.
|
|
207
|
+
|
|
208
|
+
When the cap stops a run, the dashboard shows **Budget limited** and offers Stop but no human Resume. Resume through the model tool only, using this explicitly internal reference shape:
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"resume_from_run_id": "<internal-run-id>",
|
|
213
|
+
"agent_budget": 256
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The absolute `agent_budget` must be greater than the old total and no greater than 1,024. Human commands, dashboard Resume, or an absent/equal/lower/excessive cap return `workflow "<display-name>" requires a higher agent_budget to resume` without starting another attempt. Internal run ids belong only in this model-tool exchange, never in screenshots, command text, titles, notices, or accessibility labels.
|
|
218
|
+
|
|
219
|
+
An eligible terminal run attempts one bounded owner completion notice, preferring `scratch/report.md` to the inline result and ending `Open /workflows to inspect the run.` It is at-most-once delivery: a crash can omit a claimed notice, never duplicate it.
|
|
220
|
+
|
|
221
|
+
After Host process death, startup recovery changes any retained active run to **Interrupted**, changes running members to cancelled, shows `Process exited before workflow settlement.`, and exposes inspection only. No journal, checkpoint, Agent, script/args authority, gate, or child handle crosses processes; an Interrupted run cannot Resume or Save. Launch a new run from the saved definition after checking whether any uncommitted external effect already happened.
|
|
222
|
+
|
|
223
|
+
## 10. Author replay-safe JavaScript
|
|
224
|
+
|
|
225
|
+
The worker exposes `args`; `agent`; thunk or declarative `parallel`; `pipeline`; `phase`; `log`; `complete`; `budget`; `pause`; `await_user`; `read_scratch_file`; and `write_scratch_file`. `agent(prompt, opts)` accepts exactly `label`, `phase`, `schema`, `provider`, and `model`. Stock workers have no native `complete`, so this package injects it.
|
|
226
|
+
|
|
227
|
+
Structured schemas support `type`, `properties`, `required`, `additionalProperties`, `items`, `minItems`, `maxItems`, `enum`, `const`, and `oneOf`. `minItems` and `maxItems` are inclusive array-length bounds. Each bound must be a non-negative safe integer (negative zero, fractions, and non-numbers are invalid), may appear only on a `type: 'array'` node, must satisfy `minItems <= maxItems`, and is forbidden beside `oneOf`. The package validates the authored schema before any child starts, removes only these two forward-compatible keywords from the copy sent to stock RC2, and post-validates the returned structured value against the authored bounds. Unsupported options such as `fork_context`, unsupported schemas, invalid calls, and infrastructure failures are fatal; ordinary child failures or schema-invalid child values return `null`.
|
|
228
|
+
|
|
229
|
+
This complete body guards nullable outputs, keeps verification fail-closed, sorts and filters deterministically, bounds a log preview explicitly, synchronizes phase titles, and publishes a report:
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
const rawTargets = Array.isArray(args.targets) ? args.targets : []
|
|
233
|
+
const targets = [...new Set(rawTargets)]
|
|
234
|
+
.filter(target => typeof target === 'string' && target.length > 0)
|
|
235
|
+
.sort((left, right) => left.localeCompare(right))
|
|
236
|
+
|
|
237
|
+
if (targets.length === 0) {
|
|
238
|
+
complete({ ok: false, reason: 'no valid targets', findings: [] })
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
phase('Review')
|
|
242
|
+
const reviews = await parallel(targets.map(target => ({
|
|
243
|
+
label: `review-${target}`,
|
|
244
|
+
phase: 'Review',
|
|
245
|
+
prompt: `Review ${target}. Inspect the workspace; return at most 20 evidence-backed findings.`,
|
|
246
|
+
schema: {
|
|
247
|
+
type: 'object',
|
|
248
|
+
properties: {
|
|
249
|
+
findings: {
|
|
250
|
+
type: 'array',
|
|
251
|
+
maxItems: 20,
|
|
252
|
+
items: {
|
|
253
|
+
type: 'object',
|
|
254
|
+
properties: {
|
|
255
|
+
path: { type: 'string' },
|
|
256
|
+
summary: { type: 'string' },
|
|
257
|
+
evidence: { type: 'string' },
|
|
258
|
+
},
|
|
259
|
+
required: ['path', 'summary', 'evidence'],
|
|
260
|
+
additionalProperties: false,
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
required: ['findings'],
|
|
265
|
+
additionalProperties: false,
|
|
266
|
+
},
|
|
267
|
+
})))
|
|
268
|
+
|
|
269
|
+
if (reviews.some(review => review === null)) {
|
|
270
|
+
complete({ ok: false, reason: 'a reviewer failed', findings: [] })
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const findings = reviews
|
|
274
|
+
.flatMap(review => review.findings)
|
|
275
|
+
.filter(finding => targets.some(target => finding.path === target || finding.path.startsWith(`${target}/`)))
|
|
276
|
+
.sort((left, right) => left.path.localeCompare(right.path) || left.summary.localeCompare(right.summary))
|
|
277
|
+
|
|
278
|
+
const preview = JSON.stringify(findings)
|
|
279
|
+
log(preview.length <= 2_000 ? preview : `${preview.slice(0, 2_000)}… [truncated]`)
|
|
280
|
+
|
|
281
|
+
phase('Verify')
|
|
282
|
+
const verification = await agent(
|
|
283
|
+
`Challenge every finding against the workspace. Reject unsupported claims.\n${JSON.stringify(findings)}`,
|
|
284
|
+
{
|
|
285
|
+
label: 'verifier',
|
|
286
|
+
phase: 'Verify',
|
|
287
|
+
schema: {
|
|
288
|
+
type: 'object',
|
|
289
|
+
properties: {
|
|
290
|
+
verified: { type: 'boolean' },
|
|
291
|
+
reason: { type: 'string' },
|
|
292
|
+
},
|
|
293
|
+
required: ['verified', 'reason'],
|
|
294
|
+
additionalProperties: false,
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
if (verification === null || verification.verified !== true) {
|
|
300
|
+
complete({ ok: false, reason: verification?.reason ?? 'verification failed', findings: [] })
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
phase('Report')
|
|
304
|
+
const report = [
|
|
305
|
+
'# Verified review',
|
|
306
|
+
'',
|
|
307
|
+
...findings.map(finding => `- **${finding.path}** — ${finding.summary}\n - Evidence: ${finding.evidence}`),
|
|
308
|
+
'',
|
|
309
|
+
].join('\n')
|
|
310
|
+
await write_scratch_file('report.md', report)
|
|
311
|
+
complete({ ok: true, findings, report: 'report.md' })
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`complete(value)` accepts the first lossless JSON value and makes every later hook ineffective even if script code catches its internal sentinel. `return value` also settles the run. Scratch names are one component matching `^[A-Za-z0-9][A-Za-z0-9._-]*$`; defaults allow 4,096 operations, 64 pending, 64 files, 1 MiB per file, and 8 MiB total. `phase`/`log` events are each bounded to 64 KiB UTF-8.
|
|
315
|
+
|
|
316
|
+
Replay-capable runs remove `Date`, `Math.random`, `Atomics`, `SharedArrayBuffer`, `WeakRef`, and `FinalizationRegistry`. Deterministic Math functions remain. Every effectful agent prompt must be safely repeatable because an effect whose result was not committed can run again. A script has no `workflow()` hook: nested workflows are unsupported; express orchestration with agents, `parallel`, and `pipeline` inside one run.
|
|
317
|
+
|
|
318
|
+
## 11. Keyboard, mobile, and accessibility
|
|
319
|
+
|
|
320
|
+
Opening `/workflows` moves focus into a labelled modal card over the conversation (not a full-page takeover). The chrome around the card is dimmed and inert; click that chrome, Close, or Escape to dismiss. Tab and Shift+Tab stay inside the card, escaped focus is recovered, and the invoking composer is restored on close when it still exists. Status always uses text in addition to color, progress and updates use semantic status/live regions, and member rows are real controls with visible `:focus-visible` treatment.
|
|
321
|
+
|
|
322
|
+
P/R/X/S activate Pause/Resume/Stop/Save only when the dialog owns focus, no modifier or key repeat is present, the target is not editable, and the selected run currently allows that action. Hidden or unavailable actions never fire. Narrow-screen controls are at least 44 px in both dimensions, long labels and results wrap, and reduced-motion preference removes nonessential transitions.
|
|
323
|
+
|
|
324
|
+
## 12. Troubleshooting
|
|
325
|
+
|
|
326
|
+
### Incompatible Harness
|
|
327
|
+
|
|
328
|
+
Symptom: activation reports an unsupported Host face or version. Install official `0.1.1-rc.2` with plugin `0.1.0-rc.3`; do not widen the peer range or assume a later Harness version is compatible.
|
|
329
|
+
|
|
330
|
+
### Storage is already owned
|
|
331
|
+
|
|
332
|
+
Symptom: `workflow storage root is already owned by another live process`. Stop the other cooperating Harness process and retry. Never delete or age `.workflow-storage.lock`; the kernel releases its advisory lease when the owner exits. `safe workflow storage is unavailable on <platform>` means the required native lease is unsupported, not that an unlocked fallback is safe.
|
|
333
|
+
|
|
334
|
+
### Registry is disabled or a definition is missing
|
|
335
|
+
|
|
336
|
+
`workflow registry is disabled` means listing is inert and Save is intentionally unavailable. `no saved workflow named "<name>"` means no winning definition exists in the current Session cwd's bundled/project/user view. Check the flat filename, root, scope, watcher diagnostic, and precedence; `/workflows` cannot answer definition questions because it lists runs.
|
|
337
|
+
|
|
338
|
+
### Malformed definition or arguments
|
|
339
|
+
|
|
340
|
+
A definition must be valid UTF-8 JSON with exactly `{ meta, script }`, known metadata/phase fields, a string script, and a filename stem equal to `meta.name`. Discovery names the offending path and fails the complete observation. Command parse errors are exact:
|
|
341
|
+
|
|
342
|
+
```text
|
|
343
|
+
trailing args for "review-changes" must be one JSON object — {bad
|
|
344
|
+
trailing args for "review-changes" must be a JSON object (wrap arrays/scalars in a field)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Fix the source; the package never guesses, evaluates metadata, or silently omits the file.
|
|
348
|
+
|
|
349
|
+
### Run, control, or transcript is unavailable
|
|
350
|
+
|
|
351
|
+
`workflow "<display-name>" was not found in this Session` deliberately reveals no cross-Session data. `workflow "<display-name>" was interrupted by process exit and cannot resume` requires a new launch. A stale control uses the revision message shown above. `Child transcript unavailable` means the current direct one-shot child catalog no longer authorizes navigation; inspect the retained member outcome instead. A request-level error keeps loaded detail and offers `Retry`.
|