@zq-silk/yui 0.15.8 → 0.15.9

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.
Files changed (74) hide show
  1. package/ARCHITECTURE.md +2 -0
  2. package/ARCHITECTURE.zh-CN.md +151 -0
  3. package/README.md +211 -14
  4. package/dist/artifacts/artifactCapability.js +74 -0
  5. package/dist/artifacts/artifactCommitLock.js +249 -0
  6. package/dist/artifacts/artifactPaths.js +151 -0
  7. package/dist/artifacts/gitArtifactRef.js +146 -0
  8. package/dist/artifacts/managedGit.js +332 -0
  9. package/dist/artifacts/taskArtifactRepository.js +277 -0
  10. package/dist/cli/commandCatalog.js +14 -10
  11. package/dist/cli.js +67 -0
  12. package/dist/commands/operatorCommands.js +33 -2
  13. package/dist/commands/taskActivationCommands.js +22 -0
  14. package/dist/commands/taskCommands.js +342 -79
  15. package/dist/context/runContextPack.js +28 -16
  16. package/dist/context/taskContext.js +26 -3
  17. package/dist/controller/controller.js +8 -2
  18. package/dist/kernel/builtinCapabilities.js +32 -24
  19. package/dist/message/message.js +56 -0
  20. package/dist/plugins/pluginService.js +11 -3
  21. package/dist/resources/projectResource.js +0 -48
  22. package/dist/resources/projectResourceService.js +3 -81
  23. package/dist/setup/setupCommand.js +3 -8
  24. package/dist/storage/migrations/artifactsToGit.js +338 -0
  25. package/dist/storage/migrations/submitIntent.js +126 -0
  26. package/dist/storage/sqliteSchema.js +37 -3
  27. package/dist/storage/sqliteStore.js +1 -21
  28. package/dist/storage/storageVersions.js +1 -1
  29. package/dist/storage/storeRpc.js +1 -1
  30. package/dist/task/taskActivation.js +26 -0
  31. package/dist/task/taskActivationService.js +85 -69
  32. package/dist/task/taskSubmission.js +236 -0
  33. package/dist/web/assets/client/app.js +3 -2
  34. package/dist/web/assets/client/taskSurface.js +96 -7
  35. package/dist/web/webServer.js +18 -3
  36. package/dist/web/webTaskSurface.js +6 -6
  37. package/dist/workItem/workItem.js +14 -10
  38. package/docs/agent-result-consumption.md +2 -0
  39. package/docs/agent-result-consumption.zh-CN.md +81 -0
  40. package/docs/agent-runtime-drivers.md +2 -0
  41. package/docs/agent-runtime-drivers.zh-CN.md +77 -0
  42. package/docs/architecture/README.md +44 -32
  43. package/docs/architecture/README.zh-CN.md +43 -0
  44. package/docs/architecture/capabilities-and-resources.md +118 -79
  45. package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
  46. package/docs/managed-turn-and-session-runtime.md +2 -0
  47. package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
  48. package/docs/observability/README.md +2 -0
  49. package/docs/observability/README.zh-CN.md +71 -0
  50. package/docs/plugin-sdk.md +320 -217
  51. package/docs/plugin-sdk.zh-CN.md +293 -0
  52. package/docs/provider-runtime.md +2 -0
  53. package/docs/provider-runtime.zh-CN.md +132 -0
  54. package/docs/release-workflow.md +2 -0
  55. package/docs/release-workflow.zh-CN.md +237 -0
  56. package/docs/roles-and-configuration.md +2 -0
  57. package/docs/roles-and-configuration.zh-CN.md +96 -0
  58. package/docs/sqlite-control-plane-design.md +2 -0
  59. package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
  60. package/docs/task-dag-semantics.md +80 -57
  61. package/docs/task-dag-semantics.zh-CN.md +59 -0
  62. package/docs/task-delivery.md +2 -0
  63. package/docs/task-delivery.zh-CN.md +82 -0
  64. package/docs/task-local-identity.md +2 -0
  65. package/docs/task-local-identity.zh-CN.md +58 -0
  66. package/docs/testing/verification-levels.md +2 -0
  67. package/docs/testing/verification-levels.zh-CN.md +69 -0
  68. package/i18n/README.zh-CN.md +199 -10
  69. package/package.json +2 -1
  70. package/skills/yui-leader/SKILL.md +88 -331
  71. package/skills/yui-leader/references/execution.md +303 -0
  72. package/skills/yui-leader/references/planning.md +109 -0
  73. package/skills/yui-leader/references/task-plugins.md +8 -4
  74. package/skills/yui-operator/SKILL.md +16 -3
@@ -1,46 +1,61 @@
1
- # 独立插件 SDK
2
-
3
- 独立目录可以通过现有 `capability` 入口贡献 Task-local 能力,无需修改 Yui
4
- 安装目录。当前受认证的 Leader 可以管理自己 Task 的插件,global Operator
5
- 仍可管理指定 Task 的插件;Worker/Reviewer 保持调用和读取权限,不获得管理
6
- 或自行授信权限。本 SDK 不实现 Endpoint 注册或自动升级。
7
-
8
- Store 持久保存用户希望启用/停用的选择,以及对应的确切验证产物引用;
9
- Host 是实际实例和引用生命周期的唯一权威。Controller 重启后仍能读取选择及
10
- 报告,但必须显式重新激活。不存在独立的可写 `active=true` 账本、自动执行
11
- 作者代码、市场、签名平台或恢复 worker。
12
-
13
- ## 入口与环境
14
-
15
- 所有管理操作复用原 Controller、CapabilityRegistry、InstanceHost 和身份入口。
16
- 在已认证 managed Leader/Operator Session 中使用以下能力;普通终端不能靠声明
17
- `scope:user` 获权。开发 checkout 必须使用其绝对 `output/dev/bin/yui`,
18
- 并明确选择自己的隔离 Home,不能用全局安装验证。
19
-
20
- | 能力 | 输入(Task 由 `--task` 绑定) | 可观察结果 |
1
+ <p align="right"><strong>English</strong> | <a href="./plugin-sdk.zh-CN.md">简体中文</a></p>
2
+
3
+ # Standalone plugin SDK
4
+
5
+ A standalone directory can contribute Task-local capabilities through the
6
+ existing `capability` ingress without modifying the Yui installation. The
7
+ currently authenticated Leader can manage its own Task's plugins, and the global
8
+ Operator can still manage a named Task's plugins; a Worker/Reviewer keeps call
9
+ and read access but gains no management or self-trust authority. This SDK does
10
+ not implement Endpoint registration or automatic upgrades.
11
+
12
+ The Store persists the user's enable/disable selection and the exact
13
+ validation-artifact reference it points to; the Host is the sole authority for
14
+ the live instances and reference lifecycle. After a Controller restart the
15
+ selection and reports are still readable, but activation must be explicit. There
16
+ is no separate writable `active=true` ledger, no automatic execution of author
17
+ code, and no marketplace, signing platform or recovery worker.
18
+
19
+ ## Ingress and environment
20
+
21
+ All management operations reuse the original Controller, CapabilityRegistry,
22
+ InstanceHost and identity ingress. Use the capabilities below inside an
23
+ authenticated managed Leader/Operator Session; an ordinary terminal cannot gain
24
+ authority by declaring `scope:user`. A development checkout must use its absolute
25
+ `output/dev/bin/yui` and explicitly select its own isolated Home; the global
26
+ installation cannot validate it.
27
+
28
+ | Capability | Input (Task bound by `--task`) | Observable result |
21
29
  | --- | --- | --- |
22
- | `plugin.create` | `preparationId, id, kind` | 新目录、manifest、示例;不执行作者代码 |
23
- | `plugin.scan` | `preparationId, directory` | 数据型扫描的 manifest、文件名、SHA-256 |
24
- | `plugin.validate` | `preparationId, directory` | 不可变 validation ID、源码/产物摘要、环境和已执行检查 |
25
- | `plugin.validation` | `validationId` | 报告摘要,不启动代码;本 Task 的 `task:read` 调用者可读 |
26
- | `plugin.inspect` | `id` | 本 Task 的期望选择、实际选择、Host 引用及最近管理失败;不加载代码 |
27
- | `plugin.list` | `{}` | 本 Task 全部显式选择的当前视图,含已停用选择 |
28
- | `plugin.activate` | `validationId` | 通过准入后保存启用选择,准备并发布实例,返回当前视图 |
29
- | `plugin.disable` | `id` | 保存停用选择,停止新调用,等待实际引用排空和 dispose |
30
-
31
- `directory` 可以是环境内的相对路径或绝对规范路径,但不能是环境根、外部
32
- 路径或经 symlink 到达的目录。先通过 `environment.prepare/adopt`
33
- 明确采用一个 writable 环境。scratch 是独立目录所有权,**不是 OS 沙箱**;
34
- 用户目录还需要具体 Resource grant。每次新动作复核采用记录、Task
35
- 当前状态、目录 identity、资源意图及现行 Resource grant。
36
- 环境复核与主线原生执行使用同一 `resolveExecutionEnvironment`,要求现行 grant
37
- 包含该 preparation 的采用记录。撤权后仅签发一个新 grant 不会隐式重新采用旧环境。
38
-
39
- SDK 的实际构建、候选和活实例引用会阻止公开 `environment.release`。
40
- 先停用并排空;环境释放不会删除用户目录,也不会强删非空 scratch。
41
- 插件停用不删除源码或验证证据,不提供自动卸载/GC。
42
-
43
- 示例(`T`、`P`、`V` 分别替换为实际 Task、adopted preparation、validation ID):
30
+ | `plugin.create` | `preparationId, id, kind` | New directory, manifest and sample; no author code runs |
31
+ | `plugin.scan` | `preparationId, directory` | Data-only scan: manifest, file names, SHA-256 |
32
+ | `plugin.validate` | `preparationId, directory` | Immutable validation ID, source/artifact digests, environment and executed checks |
33
+ | `plugin.validation` | `validationId` | Report summary without starting code; readable by a `task:read` caller in this Task |
34
+ | `plugin.inspect` | `id` | This Task's desired selection, actual selection, Host references and most recent management failure; loads no code |
35
+ | `plugin.list` | `{}` | Current view of every explicit selection in this Task, including disabled ones |
36
+ | `plugin.activate` | `validationId` | On admission, saves the enabled selection, prepares and publishes the instance, and returns the current view |
37
+ | `plugin.disable` | `id` | Saves the disabled selection, stops new calls, and waits for actual references to drain and dispose |
38
+
39
+ `directory` may be a relative path inside the environment or an absolute
40
+ canonical path, but not the environment root, an external path, or a directory
41
+ reached through a symlink. First adopt a writable environment explicitly through
42
+ `environment.prepare/adopt`. Scratch is independent directory ownership, **not an
43
+ OS sandbox**; a user directory still needs a specific Resource grant. Every new
44
+ action rechecks the adoption record, the Task's current status, the directory
45
+ identity, the resource intent and the current Resource grant. Environment
46
+ rechecks and mainline native execution share one `resolveExecutionEnvironment`,
47
+ which requires the current grant to include that preparation's adoption record.
48
+ Issuing a single new grant after revocation does not implicitly re-adopt an old
49
+ environment.
50
+
51
+ The SDK's actual build, candidate and live instance references block a public
52
+ `environment.release`. Disable and drain first; releasing an environment never
53
+ deletes a user directory and never force-removes a non-empty scratch. Disabling a
54
+ plugin does not delete source or validation evidence, and there is no automatic
55
+ uninstall/GC.
56
+
57
+ Example (replace `T`, `P` and `V` with the actual Task, adopted preparation and
58
+ validation IDs):
44
59
 
45
60
  ```text
46
61
  <checkout>/output/dev/bin/yui capability call plugin.create --task T --request-id create-1 --input '{"preparationId":"P","id":"demo","kind":"declarative"}'
@@ -51,70 +66,108 @@ SDK 的实际构建、候选和活实例引用会阻止公开 `environment.relea
51
66
  <checkout>/output/dev/bin/yui capability call plugin.disable --task T --request-id disable-1 --input '{"id":"demo"}'
52
67
  ```
53
68
 
54
- `requestId` 对有副作用的能力必填,但 SDK 不另建通用幂等账本。验证重做生成新
55
- 报告,激活重做采用新 generation;发生通信错误后先查当前事实再决定是否重试。
56
-
57
- ## 原 Task 中的自扩展
58
-
59
- Leader 先通过稳定 `capability search/describe` 读取当前目录和契约,判断复用、
60
- 组合或临时脚本是否足够;不强制另建插件开发 Task,也不要求注册所有脚本。
61
- 选择插件时,沿上述入口创建、验证、修复、激活。下一次桥调用即可发现并调用
62
- 新增能力,不需要热改原生工具 schema、替换自身 Endpoint 或重启 Controller。
63
-
64
- Task-local 管理权限不等于执行信任:可执行包仍逐阶段核对下面定义的精确
65
- `plugin.execute` grant,源码改变后不会继承旧摘要授权。资源、网络、全局
66
- 配置及核心 namespace 的边界不变;已有授权充分时不重复批准,缺少新权限则
67
- 报告具体缺口,不冒充 Operator 或自己签发 grant。
68
-
69
- 验证失败由 Agent 保存原错误并判断修复;不可把 unknown/部分效果自动重跑。
70
- 使用新增能力取得实际业务结果后,通过 `artifact.save` 保存独立内容,并在
71
- Task 结果中保留引用。`artifact.read` 不依赖插件仍活跃。加载成功或保留插件
72
- 源码不是业务闭环完成证据。协议夹具能验证工程边界,但不能证明真实 Agent
73
- 自主选择、编写和修复成功;真实场景验证遵循项目的资源授权边界。
74
-
75
- ## 期望选择与实际实例
76
-
77
- `plugin.inspect/list` 属于 `task:read`,不 acquire、初始化或恢复插件,也不消费
78
- grant 或写入 Store。当前视图中:
79
-
80
- - `desired` 是持久选择,包含 enabled、固定 validationId、内部 revision、
81
- 选择时间及可选 lastFailure。version/digest 从不可变验证报告派生,不重复保存。
82
- - `actual` 是当前 Controller 为新调用选中的 Host 实现及其验证引用;没有选择
83
- 或不能 acquire 时为 null。它不是子进程健康检查,也不证明当前 grant 仍有效。
84
- - `instances` 来自 Host 的未完成释放实例观察:确切 implementation、实际引用数、
85
- 是否接受新 acquire。停用后 actual 可以为 null,但这里仍有排空中的旧引用。
86
- - `needsActivation` 只比较期望启用选择与实际选择,不是独立工作状态或自动任务。
87
-
88
- 首次查询一个未配置插件得到 `desired: null`。停用未知插件也保存明确的 disabled
89
- 选择,但没有 validationId;停用已配置插件保留原验证引用。所有 scope 均为 Task,
90
- 查询其他 Task 不泄漏本 Task 的选择。
91
-
92
- 激活先检查输入、验证记录归属、当前源码/环境、契约/依赖和权限;未通过准入的
93
- 请求不创建或更改意图。可执行 grant 的消费和启用选择在同一事务提交;事务失败
94
- 不执行作者代码、不发布实例,grant 消费也回滚。之后初始化或发布失败,则保留
95
- 已合法接受的期望 B、失败原因以及原实际 A,让 Agent 决定重试、更换或停用。
96
-
97
- 失败的 activate/disable 仍返回 `kind: failed`,不是伪装成功;在能够读取状态时,
98
- 其 `value` 附带上述当前视图。最近的管理失败按原意图 revision 记录,迟到结果
99
- 不能覆盖新的选择。revision 由内部事务递增,调用者不需要携带 expected token。
100
- 每次新的明确选择清除上次管理失败;已有 AgentRun/报告与业务 receipt 不受影响。
101
-
102
- 停用先提交 disabled,再同步移除新调用入口,等待原引用排空;清理失败不反转
103
- disabled。若持久提交失败,原实例仍保持可用,不能宣称已停用。发布成功后的
104
- 诊断读取失败也不能卸载已经发布的新实例。错误后应查询当前事实,而不是自动重试。
105
- 同一插件有并发管理动作时,操作结果中的精确 provider 指该次操作的实例,
106
- 附带的当前视图则可能已经反映更晚的显式选择。
107
-
108
- 重启只保留选择和已有失败诊断,不从旧报告猜测过去是否启用,不自动重放操作,
109
- 也不伪称历史实际实例仍运行。原来期望 B 但运行 A 的情形重启后表现为
110
- desired=B、actual=null;再次显式激活 B 必须重新通过现行授权和环境检查。
111
-
112
- ## 包合同
113
-
114
- 目录扫描仅解析数据,不 import 作者代码。当前包最多 256 个 UTF-8 文件、
115
- 合计 4 MiB;拒绝 symlink、特殊文件和二进制依赖。所有文件都进入摘要及
116
- 验证产物,包括依赖,因此应提供小型、自包含、非秘密的目录,而不是包含
117
- 凭据、用户资料或整个开发环境的树。
69
+ `requestId` is required for capabilities with side effects, but the SDK builds no
70
+ general idempotency ledger. Re-validating produces a new report and re-activating
71
+ adopts a new generation; after a communication error, read the current facts
72
+ before deciding whether to retry.
73
+
74
+ ## Self-extension inside the original Task
75
+
76
+ The Leader first reads the current catalog and contracts through the stable
77
+ `capability search/describe` to judge whether reuse, composition or an ad-hoc
78
+ script is enough; it is not forced to create a separate plugin-development Task or
79
+ to register every script. When it chooses a plugin, it creates, validates,
80
+ repairs and activates it through the ingress above. The next bridge call can
81
+ discover and invoke the new capability without hot-patching the native tool
82
+ schema, replacing its own Endpoint or restarting the Controller.
83
+
84
+ Task-local management authority is not execution trust: an executable package
85
+ still checks the exact `plugin.execute` grant defined below phase by phase, and a
86
+ changed source does not inherit an old digest's authorization. The boundaries
87
+ around resources, network, global configuration and the core namespace are
88
+ unchanged; when existing authority is sufficient it is not re-approved, and when a
89
+ new permission is missing the specific gap is reported rather than impersonating
90
+ the Operator or self-issuing a grant.
91
+
92
+ On validation failure the Agent preserves the original error and judges the fix;
93
+ an unknown or partial effect must not be auto-rerun. After using a new capability
94
+ to obtain a real business result, save independent content as a file artifact
95
+ through `artifact.save` (it commits the `relativePath` into the Task's local Git
96
+ repository) and keep the returned `commit + relativePath` reference in the Task
97
+ result. `artifact.read` does not
98
+ depend on the plugin staying active. A successful load or a retained plugin source
99
+ is not evidence that the business loop is complete. Protocol fixtures can validate
100
+ the engineering boundary but cannot prove that a real Agent autonomously chose,
101
+ wrote and repaired it; real-scenario validation follows the project's
102
+ resource-authorization boundary.
103
+
104
+ ## Desired selection and actual instance
105
+
106
+ `plugin.inspect/list` are `task:read`: they do not acquire, initialize or recover
107
+ a plugin, and they consume no grant and write no Store. In the current view:
108
+
109
+ - `desired` is the persistent selection — enabled, the pinned validationId, an
110
+ internal revision, the selection time and an optional lastFailure. Version and
111
+ digest are derived from the immutable validation report, not stored again.
112
+ - `actual` is the Host implementation the current Controller selects for new
113
+ calls and its validation reference; it is null when there is no selection or it
114
+ cannot be acquired. It is not a child-process health check and does not prove
115
+ the current grant is still valid.
116
+ - `instances` come from the Host's observation of not-yet-released instances: the
117
+ exact implementation, the actual reference count and whether it still accepts
118
+ new acquires. After disable, `actual` can be null while a draining old
119
+ reference is still listed here.
120
+ - `needsActivation` only compares the desired enabled selection with the actual
121
+ selection; it is not an independent work state or an automatic task.
122
+
123
+ The first query of an unconfigured plugin returns `desired: null`. Disabling an
124
+ unknown plugin still saves an explicit disabled selection but with no
125
+ validationId; disabling a configured plugin keeps the original validation
126
+ reference. Every scope is the Task, and querying another Task never leaks this
127
+ Task's selection.
128
+
129
+ Activation first checks the input, the validation record's ownership, the current
130
+ source/environment, the contract/dependencies and permissions; a request that
131
+ fails admission neither creates nor changes intent. The executable grant's
132
+ consumption and the enabled selection commit in one transaction; if the
133
+ transaction fails, no author code runs, no instance is published, and the grant
134
+ consumption rolls back. If initialization or publication fails afterward, the
135
+ legally accepted desired B, the failure reason and the original actual A are
136
+ retained, letting the Agent decide to retry, replace or disable.
137
+
138
+ A failed activate/disable still returns `kind: failed` rather than faking
139
+ success; when state can be read, its `value` carries the current view above. The
140
+ most recent management failure is recorded against the intended revision, and a
141
+ late result cannot overwrite a newer selection. The revision is incremented by
142
+ the internal transaction, so the caller carries no expected token. Each new
143
+ explicit selection clears the previous management failure; existing
144
+ AgentRun/reports and business receipts are unaffected.
145
+
146
+ Disable commits `disabled` first, then synchronously removes the entry point for
147
+ new calls and waits for the original references to drain; a cleanup failure does
148
+ not reverse `disabled`. If the durable commit fails, the original instance stays
149
+ available and cannot be claimed as disabled. A diagnostic read that fails after a
150
+ successful publication also cannot unload the newly published instance. After an
151
+ error, query the current facts instead of retrying automatically. When a plugin
152
+ has concurrent management actions, the exact provider in an operation result
153
+ refers to that operation's instance, while the attached current view may already
154
+ reflect a later explicit selection.
155
+
156
+ A restart keeps only the selection and existing failure diagnosis: it does not
157
+ guess from an old report whether the plugin used to be enabled, does not replay
158
+ operations automatically, and does not pretend a historical actual instance is
159
+ still running. A case that desired B but ran A appears after restart as
160
+ desired=B, actual=null; activating B again must re-pass the current authorization
161
+ and environment checks.
162
+
163
+ ## Package contract
164
+
165
+ A directory scan only parses data; it does not import author code. The current
166
+ package allows at most 256 UTF-8 files totaling 4 MiB; it rejects symlinks,
167
+ special files and binary dependencies. Every file, including dependencies, enters
168
+ the digest and validation artifact, so provide a small, self-contained,
169
+ non-secret directory rather than a tree that contains credentials, user data or a
170
+ whole development environment.
118
171
 
119
172
  ```json
120
173
  {
@@ -138,40 +191,52 @@ desired=B、actual=null;再次显式激活 B 必须重新通过现行授权和
138
191
  }
139
192
  ```
140
193
 
141
- `id` 为小写字母开头、仅小写字母/数字/连字符的单段名字。能力名使用 Registry
142
- 的点分名字;核心 namespace(包括 `context`)和 Provider 身份不能覆盖。
143
- Provider ID 由可信根按 Task + plugin ID 产生。不同 Provider 的同名能力保留
144
- 原 Registry 歧义规则,不按加载顺序覆盖;调用时可明确 `--provider/--version`。
194
+ `id` is a single segment that starts with a lowercase letter and uses only
195
+ lowercase letters, digits and hyphens. A capability name uses the Registry's
196
+ dotted name; the core namespace (including `context`) and Provider identity
197
+ cannot be overridden. The Provider ID is produced by a trusted root from the Task
198
+ plus plugin ID. Same-named capabilities from different Providers keep the
199
+ Registry's ambiguity rule and are not overridden by load order; a call can
200
+ specify `--provider/--version` explicitly.
145
201
 
146
- `required` 是准确的 `{name, contractVersion}` 依赖,不是版本求解器。依赖缺失、
147
- 不可用、歧义或成环时拒绝激活。schema 使用 Registry 现有有界方言,未知关键词
148
- 拒绝。每项 `requiredPermissions` 必须属于 manifest `permissions`;scope 只是
149
- 可见性,权限仍来自当前调用者。Task-local 插件不能声明 `plugin:manage`。
202
+ `required` is an exact `{name, contractVersion}` dependency list, not a version
203
+ solver. A missing, unavailable, ambiguous or cyclic dependency rejects
204
+ activation. The schema uses the Registry's existing bounded dialect, and unknown
205
+ keywords are rejected. Every `requiredPermissions` entry must belong to the
206
+ manifest `permissions`; scope is only visibility, and permission still comes from
207
+ the current caller. A Task-local plugin cannot declare `plugin:manage`.
150
208
 
151
- 声明式 `entry.json` 必须完整且仅包含 manifest 声明的能力:
209
+ A declarative `entry.json` must be complete and contain only the capabilities the
210
+ manifest declares:
152
211
 
153
212
  ```json
154
213
  { "demo.echo": { "type": "echo" } }
155
214
  ```
156
215
 
157
- 支持 `echo`、`constant + value`,以及
158
- `call + name + contractVersion + 可选 providerId`。`call` 将原输入与 requestId
159
- 交给一个明确依赖,返回其 value,保留原 operations/effect;它不是多步流程引擎。
160
- 声明式包不能声明 build,也不会执行任意 JavaScript。
216
+ It supports `echo`, `constant + value`, and
217
+ `call + name + contractVersion + optional providerId`. `call` hands the original
218
+ input and requestId to one explicit dependency, returns its value, and preserves
219
+ the original operations/effect; it is not a multi-step flow engine. A declarative
220
+ package cannot declare a build and never runs arbitrary JavaScript.
161
221
 
162
- ## 可执行合同与授信
222
+ ## Executable contract and trust
163
223
 
164
- `kind: trusted-local`、`entry: entry.mjs` 的包在独立 Node 子进程中执行,不进入
165
- Controller。子进程使用明确采用的环境目录为 cwd,重新构造最小环境变量,
166
- 不继承 Yui Session、凭据、`NODE_OPTIONS` 或 `NODE_PATH`。
224
+ A `kind: trusted-local`, `entry: entry.mjs` package runs in a separate Node child
225
+ process, not inside the Controller. The child process uses the explicitly adopted
226
+ environment directory as cwd, reconstructs a minimal set of environment
227
+ variables, and does not inherit the Yui Session, credentials, `NODE_OPTIONS` or
228
+ `NODE_PATH`.
167
229
 
168
- 运行模块通过 `SourceTextModule` 从已捕获的字节加载,只支持包内相对模块依赖,
169
- 不支持裸包名、`node:` 或动态 import;需要的纯 JS 依赖应先打包。此加载器
170
- 限定代码来源,**不是恶意代码安全沙箱**。不能据此承诺宿主文件、网络、进程或
171
- 秘密绝不可访问。未经具体授信的自动生成代码应使用声明式路径或另选真正受限
172
- 环境;当前 SDK 不提供那种环境。
230
+ The running module is loaded from the captured bytes through `SourceTextModule`;
231
+ it supports only in-package relative module dependencies, not bare package names,
232
+ `node:` or dynamic import — a needed pure-JS dependency must be bundled first.
233
+ This loader bounds where the code comes from; it is **not a malicious-code
234
+ security sandbox**. It cannot promise the host filesystem, network, processes or
235
+ secrets are unreachable. Auto-generated code without specific trust should use the
236
+ declarative path or a genuinely restricted environment instead; this SDK does not
237
+ provide that environment.
173
238
 
174
- 作者 entry 导出:
239
+ The author entry exports:
175
240
 
176
241
  ```javascript
177
242
  const echo = input => input;
@@ -186,105 +251,143 @@ export function selfTest() {
186
251
  }
187
252
  ```
188
253
 
189
- ### 作者模块的运行环境
254
+ ### The author module's runtime environment
190
255
 
191
- Node 子进程是宿主,不代表作者模块运行在完整的 Node 全局环境中。
192
- 当前模块使用独立 vm context,仅依赖 ECMAScript 内建值和下述 SDK 端口:
256
+ The Node child process is the host; that does not mean the author module runs in
257
+ a full Node global environment. The current module uses a separate vm context and
258
+ relies only on ECMAScript built-ins and the SDK ports below:
193
259
 
194
- | 类别 | 当前可用性 |
260
+ | Category | Current availability |
195
261
  | --- | --- |
196
- | ECMAScript 内建值,例如 `Promise`、`JSON`、`Math`、`Date` | 可用;支持 `async/await`、`Promise.resolve()` |
197
- | `console` | 可见,但不是 SDK 日志或回执端口;子进程 stdout/stderr 不向调用者转发 |
198
- | `setTimeout`、`setInterval`、`queueMicrotask` | 不提供;不要使用普通 Node 定时器写异步流程 |
199
- | `structuredClone`、`process`、`Buffer` | 不提供 |
200
- | `fetch`、`URL`、`TextEncoder`、`AbortController`、`crypto` | 不提供 |
201
- | 业务 I/O 与下游工具 | 使用 handler 的 `api.call`,服从原调用者的权限与效果上限 |
202
-
203
- 因此 `await Promise.resolve()` 可用,`await new Promise(r => setTimeout(r, 50))`
204
- 不可用。一个永不 settle 的 handler 会触发下面的 30 秒子进程请求超时。
205
- 表格描述正常作者 API,不是安全隔离声明;不能根据某个全局变量不存在推导
206
- 恶意 trusted-local 代码无法触碰宿主。build 脚本是另一条已授信 Node 执行路径,
207
- 不受这张作者模块全局表的约束。
208
-
209
- 初始化只能准备完整注册,不得发送、发布、修改业务资料或启动后台服务。
210
- 它得不到任何业务调用端口;初始化失败仅关闭候选子进程。trusted-local 作者
211
- 仍必须遵守这个合同,缺少端口不是对任意恶意代码直接宿主访问的隔离保证。
212
- `selfTest()` 在验证时实际执行且必须返回 `true`,报告不把作者测试等同于安全认证。
213
-
214
- handler 的 `api` 只包含原 `context` 的无凭据身份、`requestId` 与
215
- `call({name,input,contractVersion?,providerId?,requestId?})`。没有 Store、Host、
216
- Registry、鉴权器、可选 actor 或 `observe` 端口。每个嵌套调用重新检查原调用者
217
- 和当前执行 grant,权限不得超过父 descriptor 声明,效果不得超过父 effect。
218
- 对已完成的子动作,即使父输出 schema 错误、抛错或无法 JSON 序列化,也保留
219
- 原 operations、effect 和 receipt locator;真正的证据仍属于原 Job 等业务 owner。
220
-
221
- 可信代码应只使用这些受控端口产生业务效果。直接绕过端口的 trusted-local
222
- 宿主操作无法由 SDK 推导真实回执或效果范围,不在上述证据保证内。
223
- 默认单次子进程请求上限 30 秒;超时或异常结束返回失败并关闭自有子进程,不重试。
224
- dispose 必须只释放自己的资源,不管理共享 daemon。任意作者派生进程或崩溃后的
225
- 宿主残留不被伪称为已回收,当前 SDK 不提供跨 Controller 进程恢复/清扫协议。
226
-
227
- ### 执行授权
228
-
229
- Adopted 目录不授予执行作者代码。每次实际 `build`、`validate`、`activate`
230
- 或 `call` 尝试还需要现行 `plugin.execute` grant,同时明确限定全部五个参数:
231
-
232
- | 参数 | 值 |
262
+ | ECMAScript built-ins such as `Promise`, `JSON`, `Math`, `Date` | Available; `async/await` and `Promise.resolve()` work |
263
+ | `console` | Visible, but not an SDK log or receipt port; child stdout/stderr is not forwarded to the caller |
264
+ | `setTimeout`, `setInterval`, `queueMicrotask` | Not provided; do not use ordinary Node timers to drive async flow |
265
+ | `structuredClone`, `process`, `Buffer` | Not provided |
266
+ | `fetch`, `URL`, `TextEncoder`, `AbortController`, `crypto` | Not provided |
267
+ | Business I/O and downstream tools | Use the handler's `api.call`, bounded by the original caller's permissions and effect |
268
+
269
+ So `await Promise.resolve()` works while `await new Promise(r => setTimeout(r, 50))`
270
+ does not. A handler that never settles triggers the 30-second child request
271
+ timeout below. The table describes the normal author API, not a security-isolation
272
+ claim; the absence of some global does not prove malicious trusted-local code
273
+ cannot reach the host. A build script is another trusted Node execution path and
274
+ is not bound by this author-module global table.
275
+
276
+ Initialization may only prepare the complete registration; it must not send,
277
+ publish or modify business data or start a background service. It receives no
278
+ business call port, and a failed initialization only closes the candidate child
279
+ process. A trusted-local author must still honor this contract, and a missing
280
+ port is not an isolation guarantee against arbitrary malicious code with direct
281
+ host access. `selfTest()` actually runs during validation and must return `true`;
282
+ the report does not treat an author test as a security certification.
283
+
284
+ The handler's `api` contains only the original `context`'s credential-free
285
+ identity, its `requestId`, and
286
+ `call({name,input,contractVersion?,providerId?,requestId?})`. There is no Store,
287
+ Host, Registry, authorizer, optional actor or `observe` port. Every nested call
288
+ rechecks the original caller and the current execution grant; permission cannot
289
+ exceed the parent descriptor's declaration, and effect cannot exceed the parent
290
+ effect. For a completed sub-action, even if the parent output schema is wrong,
291
+ throws, or cannot be JSON-serialized, the original operations, effect and receipt
292
+ locator are preserved; the real evidence still belongs to the original business
293
+ owner, such as a Job.
294
+
295
+ Trusted code should produce business effects only through these controlled ports.
296
+ A trusted-local host operation that bypasses the ports directly cannot have its
297
+ real receipt or effect scope derived by the SDK and is not covered by the
298
+ evidence guarantees above. The default single child request limit is 30 seconds;
299
+ a timeout or abnormal exit returns a failure and closes the owned child process
300
+ without retry. `dispose` must release only its own resources and not manage a
301
+ shared daemon. Any author-spawned process or host residue after a crash is not
302
+ falsely claimed as reclaimed, and this SDK provides no cross-Controller-process
303
+ recovery/sweep protocol.
304
+
305
+ ### Execution authorization
306
+
307
+ An adopted directory does not grant execution of author code. Every actual
308
+ `build`, `validate`, `activate` or `call` attempt additionally requires a current
309
+ `plugin.execute` grant that pins all five parameters:
310
+
311
+ | Parameter | Value |
233
312
  | --- | --- |
234
313
  | `pluginId` | manifest id |
235
- | `digest` | build/validate 使用 `plugin.scan` 的源码摘要;activate/call 使用报告的产物摘要 |
314
+ | `digest` | build/validate use the `plugin.scan` source digest; activate/call use the report's artifact digest |
236
315
  | `environmentRef` | `Task/preparation` |
237
316
  | `trust` | `trusted-local` |
238
- | `phase` | 明确选择的 `build,validate,activate,call` 子集 |
317
+ | `phase` | an explicitly chosen subset of `build, validate, activate, call` |
239
318
 
240
- 使用 Task scope;可附加精确环境路径的 home scope,不接受 Project/repository/
241
- package scope 替代资源授信。因 trusted-local 不约束直接宿主效果,此 grant
242
- 必须允许 `irreversibilityCeiling: irreversible`:这是能力上限,不表示每次调用
243
- 实际产生不可逆效果。`none/reversible` 不得解释为无限本机执行权。
319
+ Use Task scope; a home scope with an exact environment path may be added, but a
320
+ Project/repository/package scope is not accepted as a resource-trust substitute.
321
+ Because trusted-local does not bound direct host effects, this grant must allow
322
+ `irreversibilityCeiling: irreversible`: that is the capability ceiling, not a
323
+ statement that every call actually produces an irreversible effect. `none` or
324
+ `reversible` must not be read as unlimited local execution authority.
244
325
 
245
- 由获用户明确授权的 Operator 使用原 grant 入口,例如只允许一次验证:
326
+ An Operator explicitly authorized by the user uses the original grant ingress,
327
+ for example to allow a single validation:
246
328
 
247
329
  ```text
248
330
  <checkout>/output/dev/bin/yui task grant issue T --action plugin.execute --param pluginId=demo --param digest=SOURCE_SHA256 --param environmentRef=T/P --param trust=trusted-local --param phase=validate --max-uses 1 --irreversibility-ceiling irreversible
249
331
  ```
250
332
 
251
- grant 不由 SDK 自签发。次数按真实执行尝试消费,失败也不回退;一次 validate
252
- 包含 initialize/selfTest/dispose。build 是另一次执行。
253
- `call` 是不可从持久步骤恢复的短调用,只增加 usesUsed,不追加永久 reservation;
254
- 其准入由当前调用的绑定闭包持有,不能导出、伪造或用于进程重启后的继续执行。
255
- build/validate/activate 使用持久 reservation;已有 key 不截断或清理。
256
- 已消费额度的当前调用可以继续复核,但撤销/到期仍阻止后续受控动作,
257
- 额度耗尽则不允许新调用。长期使用不会因每次 call 再新增一条永久 key。
258
- 尚未提交的启用意图事务失败不算已执行尝试,其消费随事务回滚。
259
- 普通 disable 不撤销已在执行的原调用,撤权也不抹除意图或已发生效果。
260
-
261
- ### 构建与产物
262
-
263
- 可执行 manifest 可增加 `"build": ["build.mjs", "arg"]`。这是明确的 Node 脚本
264
- 及参数,不是 shell 字符串。build 脚本必须在捕获的源码包内;它在采用环境内
265
- 新建的自有临时副本中执行,可使用 Node API,因而同样需要 trusted-local 授信。
266
- 构建器不得依赖未声明的用户秘密或残留后台进程。
267
-
268
- 验证保存实际构建产物全部字节及摘要,记录源码摘要、Node 版本、环境 identity、
269
- 实际构建 cwd/argv 与执行检查。构建不能改变 manifest/权限;无 build 时直接
270
- 执行首次捕获的字节,不二次读取后再执行。构建不覆盖作者源码。验证结束复核
271
- 源目录,已变化则拒绝保存成功报告。
272
-
273
- 激活重新核对源目录摘要、环境及当前授权,然后只从报告中的产物字节初始化,
274
- 不会重建或改用同版本的另一个目录。构建后的验证授权针对已明确授信源码所产生
275
- 的产物,正式激活/调用则另用该实际产物摘要授权。
276
-
277
- 发布前再次检查完整贡献、依赖和权限。失败不改变现有目录;竞争 activate/disable
278
- 会使迟到候选拒绝发布。成功发布后旧 generation 只服务已有引用,排空才 dispose;
279
- 清理失败保留诊断 Artifact,不回滚新 Provider 或伪称当前实例仍未发布。
280
-
281
- ## 存储与其他入口
282
-
283
- 验证产物和启用意图属于唯一 Home 存储合同,持久结构变更走显式
284
- upgrade/update 与备份机制。读取报告不会推测或恢复实例,采用新源码不等于
285
- 授权升级共享 Home、重启 Controller 或执行插件。
286
-
287
- 同一个 Registry 将能力投影为命令和受控查询面板,不复制 SDK Host;
288
- Web 查询身份不获得 `plugin:manage`。原生 Session 与插件共享环境 owner,
289
- 释放前同时检查原生执行引用与插件引用。插件不提供 Project/global scope
290
- 提升或原生 Endpoint 注册。
333
+ A grant is not self-issued by the SDK. Uses are consumed per real execution
334
+ attempt and are not refunded on failure; one validate includes
335
+ initialize/selfTest/dispose. A build is another execution. `call` is a short
336
+ invocation that cannot resume from a persistent step; it only increments usesUsed
337
+ and adds no permanent reservation. Its admission is held by the current call's
338
+ bound closure and cannot be exported, forged or used to continue execution after a
339
+ process restart. build/validate/activate use a persistent reservation; an
340
+ existing key is not truncated or cleaned up. A current call that has already
341
+ consumed its quota can keep rechecking, but revocation/expiry still blocks
342
+ subsequent controlled actions, and an exhausted quota allows no new call.
343
+ Long-term use does not add a new permanent key per call. A not-yet-committed
344
+ enable-intent transaction that fails is not a completed execution attempt, and
345
+ its consumption rolls back with the transaction. An ordinary disable does not
346
+ revoke an original call already executing, and revocation erases neither the
347
+ intent nor an effect that already happened.
348
+
349
+ ### Build and artifacts
350
+
351
+ An executable manifest may add `"build": ["build.mjs", "arg"]`. This is an
352
+ explicit Node script and arguments, not a shell string. The build script must
353
+ live inside the captured source package; it runs in its own new temporary copy
354
+ inside the adopted environment and may use Node APIs, so it likewise requires
355
+ trusted-local trust. The builder must not depend on undeclared user secrets or
356
+ leave a background process behind.
357
+
358
+ Validation saves all bytes and the digest of the actual build artifact and
359
+ records the source digest, the Node version, the environment identity, the actual
360
+ build cwd/argv and the executed checks. A build cannot change the
361
+ manifest/permissions; with no build, the first captured bytes execute directly,
362
+ without a second read before execution. A build does not overwrite the author
363
+ source. Validation rechecks the source directory at the end and refuses to save a
364
+ success report if it has changed.
365
+
366
+ Activation rechecks the source-directory digest, the environment and the current
367
+ authorization, then initializes only from the artifact bytes in the report; it
368
+ does not rebuild or switch to another directory of the same version. A post-build
369
+ validation authorization applies to the artifact produced from the explicitly
370
+ trusted source, while a formal activate/call is authorized separately against that
371
+ actual artifact digest.
372
+
373
+ Publication rechecks the complete contribution, dependencies and permissions
374
+ again. A failure does not change the existing directory; a competing
375
+ activate/disable makes a late candidate refuse to publish. After a successful
376
+ publication, the old generation only serves existing references and is disposed
377
+ once drained; a cleanup failure keeps a diagnostic Artifact and neither rolls
378
+ back the new Provider nor pretends the current instance is still unpublished.
379
+
380
+ ## Storage and other ingress
381
+
382
+ Validation artifacts and enable intent belong to the single Home storage
383
+ contract, and a persistent structural change follows the explicit upgrade/update
384
+ and backup mechanism. Reading a report does not infer or recover an instance, and
385
+ adopting new source does not authorize upgrading the shared Home, restarting the
386
+ Controller or executing the plugin.
387
+
388
+ One Registry projects capabilities into commands and controlled query panels
389
+ without duplicating the SDK Host; a Web query identity does not gain
390
+ `plugin:manage`. A native Session and a plugin share the environment owner, and
391
+ both native execution references and plugin references are checked before release.
392
+ A plugin provides no Project/global scope elevation and no native Endpoint
393
+ registration.