@dsh-enhanced/assistant-verifier 0.1.47 → 0.1.49
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/README.md +89 -0
- package/lib/config.d.ts +8 -0
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +4 -0
- package/lib/config.js.map +1 -1
- package/lib/creation-review-native.d.ts +30 -0
- package/lib/creation-review-native.d.ts.map +1 -0
- package/lib/creation-review-native.js +130 -0
- package/lib/creation-review-native.js.map +1 -0
- package/lib/creation-review-store.d.ts +29 -0
- package/lib/creation-review-store.d.ts.map +1 -0
- package/lib/creation-review-store.js +206 -0
- package/lib/creation-review-store.js.map +1 -0
- package/lib/creation-review.d.ts +159 -0
- package/lib/creation-review.d.ts.map +1 -0
- package/lib/creation-review.js +511 -0
- package/lib/creation-review.js.map +1 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/memory-review-native.d.ts +38 -0
- package/lib/memory-review-native.d.ts.map +1 -0
- package/lib/memory-review-native.js +149 -0
- package/lib/memory-review-native.js.map +1 -0
- package/lib/memory-review.d.ts +48 -0
- package/lib/memory-review.d.ts.map +1 -0
- package/lib/memory-review.js +260 -0
- package/lib/memory-review.js.map +1 -0
- package/lib/plugin-behavior-runner.d.ts +46 -0
- package/lib/plugin-behavior-runner.d.ts.map +1 -0
- package/lib/plugin-behavior-runner.js +437 -0
- package/lib/plugin-behavior-runner.js.map +1 -0
- package/lib/revision-regression-review.d.ts +38 -0
- package/lib/revision-regression-review.d.ts.map +1 -0
- package/lib/revision-regression-review.js +315 -0
- package/lib/revision-regression-review.js.map +1 -0
- package/lib/revision-review.d.ts +99 -0
- package/lib/revision-review.d.ts.map +1 -0
- package/lib/revision-review.js +275 -0
- package/lib/revision-review.js.map +1 -0
- package/lib/service.d.ts +30 -0
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +139 -1
- package/lib/service.js.map +1 -1
- package/lib/source-review-native.d.ts +9 -0
- package/lib/source-review-native.d.ts.map +1 -1
- package/lib/source-review-native.js +6 -5
- package/lib/source-review-native.js.map +1 -1
- package/lib/source-review-store.d.ts +4 -0
- package/lib/source-review-store.d.ts.map +1 -1
- package/lib/source-review-store.js +65 -12
- package/lib/source-review-store.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +34 -25
package/README.md
CHANGED
|
@@ -81,6 +81,63 @@ Goals Host 的 `prepareGoalAssessment(input, template)` 从已持久化的初始
|
|
|
81
81
|
|
|
82
82
|
待运行 CI、待评审、截断数据或无法认证返回 unknown;失败 CI/请求修改不能通过 `/ready`。回执有效期从读取开始计时,最多为 `freshnessMs` 且不晚于契约到期。回执仅描述这次观察,不能证明远端之后不变,也不自动配置事件订阅。测试覆盖真实 Verifier→Actions Host 调用,GitHub 传输为替身;真实远端认证与完整事件跟进仍需验证。
|
|
83
83
|
|
|
84
|
+
## 新插件包的隔离行为观察
|
|
85
|
+
|
|
86
|
+
从 `@dsh-enhanced/assistant-verifier/plugin-behavior-runner` 显式导入 `PluginBehaviorRunner`,它是供可信 Host 构造的观察器,未自动激活,也不注册模型工具。主 bundle 不加载可选 Isolation peer;仅使用这个子入口时才需要它。构造参数复用 `IsolatedVerifierRunnerConfig`,省略 `command`;命令由实现固定。必须使用[专用镜像](../../scripts/isolation/README.md)、私有 `stateRoot`、不可变镜像 ID、有限次数与累计时间,`maxOutputBytes` 至少 65536。Host 持有实例并在所属 Cordis effect 的 disposer 中等待 `close()`。
|
|
87
|
+
|
|
88
|
+
`run({ key, artifact, operation, signal })` 接受真实 tgz 的 `Buffer`:`operation: { kind: 'discover' }` 返回工具 schema 与摘要;`{ kind: 'invoke', schemaDigest, calls: [{ id, toolName, arguments }] }` 仅在 schema 摘要匹配时执行调用。每包最多 512 KiB,每轮最多 8 次调用。两轮分别消耗持久预算,key 须绑定候选、操作与调用输入;派发不明的 key 不重放。
|
|
89
|
+
|
|
90
|
+
新版镜像的父观察器不导入候选;候选在另一个受限进程中用固定 Cordis、SystemPrompt 和原生 Tools 加载,不提供模拟 Agent、owner 或缺失注入。父进程核对包字节、调用身份和结果大小,自行计算 schema 摘要与环境版本,等候子进程真实退出;候选 stdout/stderr 不作为父观察协议。worker 协议 v2 拒绝旧同进程镜像的 v1 结果,需要重新构建专用镜像。候选没有工具、注入不满足、包非法、超时、结果帧非法或无法确认资源结束时返回 `unknown`。
|
|
91
|
+
|
|
92
|
+
该镜像目前要求 Linux x64。固定原生启动器在加载候选前设置 `no_new_privs` 与 seccomp,限制文件写入、非线程进程创建、网络和跨进程操作;父进程禁用信号启动调试器并设置 [non-dumpable](https://man7.org/linux/man-pages/man2/PR_SET_DUMPABLE.2const.html),避免同 UID 子进程重开其受保护的 `/proc` 内存或描述符。设置失败即拒绝运行;容器仍沿用 Isolation 的无网络、只读根文件系统、无 capability 和资源限额,不新增 Host 权限。Node 的路径权限只是额外限制,[官方权限模型](https://nodejs.org/download/release/latest-v22.x/docs/api/permissions.html)并不保证抵抗恶意代码;[seccomp](https://docs.kernel.org/userspace-api/seccomp_filter.html) 不检查路径内容,不能单独当完整沙箱。
|
|
93
|
+
|
|
94
|
+
容器只收到制品与调用输入;预期结果、验收政策和签名密钥留在 Host。schema 和工具结果仍是候选的黑箱输出;`observed` 与 `quiescent` 只说明本次输出、子进程退出与外层容器回收,不能证明候选按原语义执行了工具或 Cordis disposer,也不能单独证明目标达成或发布安全。可选创建验收见下文;真实加载后的外部观察与自动采用仍需接通。
|
|
95
|
+
|
|
96
|
+
新增权限为通过固定 Docker executable 写入私有隔离账本、暂存包和输入,在无网络、只读根文件系统且有资源上限的容器内执行候选。运行时不执行安装脚本、不挂载 Host 仓库或凭据。专用镜像准备会联网下载公开系统依赖,随后按完整锁文件离线安装且禁用依赖脚本;详见镜像指南。
|
|
97
|
+
|
|
98
|
+
## 普通任务产生的新插件验收
|
|
99
|
+
|
|
100
|
+
`creationReviews` 是可选 Host 配置。Control Plane 复用原生 SourceJobs 续跑调用 `verifyPluginCreation({ protocol: 'assistant-growth/creation-verification-request/v1', planId })`;此入口不注册为模型工具。相关原生服务与可选 Control Plane peer 未就绪时返回 `unknown`,provider 替换或卸载时取消并等待在途验收。
|
|
101
|
+
|
|
102
|
+
配置必须包括以下字段;owner 是与 `sourceReviews.owner` 相同的七字段稳定身份,不包含每任务变化的 session/binding/generation。完整任务身份仍由 Control Plane 当前来源检查。
|
|
103
|
+
|
|
104
|
+
| 字段 | 约束 |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `authorityId`, `keyId`, `namePrefix`, `expiresAt` | 明确的有限验收授权,与 Control Plane 创建命名空间和期限一致。 |
|
|
107
|
+
| `owner` | `authorityId`, `authorityHash`, `principalId`, `principalRecordId`, `principalVersion`, `workspace`, `agentPreset`。workspace 为已存在的 canonical 绝对路径。 |
|
|
108
|
+
| `keyPath` | owner 私有、单链接、非符号链接的 Ed25519 PKCS8 文件;不会交给模型或容器。 |
|
|
109
|
+
| `maxVerifications` | 1–1000;失败与未知派发也消费持久额度,不随重启返还。 |
|
|
110
|
+
| `runner` | `stateRoot`, `image`, `dockerPath`, `expiresAt`, `maxRuns`, `maxTotalDurationMs`, `maxDurationMs`, `maxOutputBytes`;使用当前锁文件的专用观察镜像。最坏每次消耗 `1 + maxCases` 个独立容器调用。 |
|
|
111
|
+
| `policy` | owner 固定的验收政策,最多 8192 字节。 |
|
|
112
|
+
| `maxInputBytes`, `maxOutputTokens` | 输入 4096–262144 字节,每个模型回合 1–32768 输出 token。 |
|
|
113
|
+
| `maxDurationMs`, `maxCases`, `receiptTtlMs` | 整次验收 1 秒至 30 分钟;2–8 个不同输入;回执 1 秒至 24 小时,受所有原授权窗口收窄。 |
|
|
114
|
+
|
|
115
|
+
部署前用导出的 `compileCreationReviewConfig(config)` 取得 `{ authority, publicKey }`,只将这两个公开字段写入 Control Plane 的 `creationVerifications`。验收政策、固定规则、密钥指纹、镜像及预算纳入 authority digest。Growth 在首次作者模型请求前持久冻结这个引用;历史无引用的候选不会取得新签名资格。
|
|
116
|
+
|
|
117
|
+
封存精确 tgz 后,第一轮全新、无工具的原生 Agent 从当前认证任务/纠正正文与候选参数结构生成私有用例;不读取候选代码、测试或调用结果。schema 的说明文字不进入此轮。Host 在调用前持久保存用例,分别在独立子进程执行并精确比较文本或 JSON 值。第二轮全新 Agent 检查实际已核对的源码补丁、任务语义与固定用例;两轮均使用来源 Growth run 的准确模型,不增加默认供应商或隐式恢复切换。
|
|
118
|
+
|
|
119
|
+
只有实际比较通过、源码审查通过且最终当前来源 fence 有效,才签发 `assistant-growth/creation-verification/v1` Ed25519 凭证。它绑定任务修订、Growth run、精确源码/制品、私有合同摘要、观察作业、SDK 环境、模型和预算。私有 SQLite 在每次派发前持久 claim;崩溃、取消或不明执行不自动重放。含糊任务、不可支持的行为或缺失证据保持 `unknown`。
|
|
120
|
+
|
|
121
|
+
生成用例与源码审查仍依赖模型语义判断;剥离 schema 说明和禁止工具不证明模型判断总是正确。此凭证仅证明这些任务派生检查通过,不是 owner 审批、通用目标成功、发布许可或采用授权。Control Plane 仍保留 `pending-approval`;之后的有限采用、Cordis 动态加载及真实后续收益必须分别验收。
|
|
122
|
+
|
|
123
|
+
新增数据与权限:读取当前 Host 认证任务和检查补丁,向该任务模型供应商发送这些材料;写私有合同、观察摘要、模型 Session、有限额度与签名账本;读取私有签名密钥,并通过固定 Docker executable 执行封存候选。没有浏览器或运行时联网容器权限,没有安装脚本或公开验收写工具。
|
|
124
|
+
|
|
125
|
+
## 已采用插件的新任务修订验收
|
|
126
|
+
|
|
127
|
+
`revisionReviews` 是可选、独立的 Host 配置,字段及限制与上表 `creationReviews` 相同;须单独配置修订 authority、Ed25519 密钥引用、政策和有限额度,密钥文件可与创建验收共用,但两种用途不能互相代用。用 `compileRevisionReviewConfig(config)` 取得 `{ authority, publicKey }`,仅将这两个公开字段交给 Control Plane 的 `revisionVerifications`;还须配置其独立的 `sourceJobs.revision` 授权和保留的已采用父版本源码。`revisionReviews` 缺省时不启用本轨,不借用创建验收引用或额度。修订 authority 使用 `assistant-growth/revision-acceptance-authority/v1` 和独立政策摘要,私有账本位于 `databasePath + '.revision-reviews'`;失败与 unknown 派发也占用修订额度,未知结果不自动重放。
|
|
128
|
+
|
|
129
|
+
新的普通认证失败任务经 Growth 冻结 `revisionAcceptance`、原任务模型及预算,并选择同 owner 已采用父版本后,Control Plane 原生 SourceJobs 才能调用 Host-only `verifyPluginRevision({ protocol: 'assistant-growth/revision-verification-request/v1', planId })`。它不注册为模型工具。Host 重新核对当前 owner/任务、父版本签名归档、精确源码基线、父绑定及封存制品;任务纠正、撤回、授权或 provider 变化会使旧验收失效。父绑定含 `planId`、`certificateDigest`、`artifactSha256`、`sourceArchiveDigest`、`sourceDigest`,并同时进入持久 claim、最终 fence 和凭证。
|
|
130
|
+
|
|
131
|
+
验收沿用两个全新的无工具原生模型回合与有界 Docker 行为观察:先依据这次任务和工具结构生成私有用例,不看候选源码;再对实际补丁、已观察用例及父绑定作源码审查。两轮使用这次新任务冻结的 supplier,另受 `revisionReviews` 的独立模型调用、输出和时限预算约束。通过后签发独立 `assistant-growth/revision-verification/v1` Ed25519 凭证,绑定父版本、当前任务、Growth run、精确制品/源码、观察环境与结果;修订签名域与旧创建凭证不互通。验收仅覆盖本次新任务及这些检查,不能推断父版本全部行为已回归通过。结果保留为 `prepared-revise` / `pending-approval` 候选;本阶段不授权执行、替换当前版本、扩大旧创建采用额度或声称版本回滚与后续收益已验证。
|
|
132
|
+
|
|
133
|
+
`revisionRegressions` 是另一个可选 Host 配置,用于对上述候选做父版本保留用例回归。它需要独立的 `authorityId`、有限额度及 runner 配置,不能由 `revisionReviews` 或 `creationReviews` 自动启用。配置字段为 `authorityId`、`owner`、`namePrefix`、`keyId`、`keyPath`、`expiresAt`、`maxVerifications`、`runner`、`maxDurationMs`、`maxCases`、`receiptTtlMs`;类型是创建验收配置去掉 `policy`、`maxInputBytes`、`maxOutputTokens`,其余字段沿用上表校验。`maxCases` 为 2–8,`runner.maxRuns` 至少为 `maxVerifications * (2 + 2 * maxCases)`,覆盖每次两侧发现及每条用例两侧调用。`compileRevisionRegressionReviewConfig(config)` 返回独立的 `{ authority, publicKey }`,公开引用使用 `assistant-growth/revision-regression-acceptance-authority/v1`;部署时将其配置到 Control Plane 的独立回归授权。旧配置缺少此字段时本轨保持关闭。
|
|
134
|
+
|
|
135
|
+
Host-only `verifyPluginRevisionRegression({ protocol: 'assistant-growth/revision-regression-request/v1', planId })` 从已签发的新任务修订候选出发。Verifier 只从自身创建验收私有 SQLite 读取父版本当时保存的用例,核对历史创建凭证签名、合同摘要、观察操作及原记录;过期的父凭证可作历史证据,缺失或被改写的记录不能推测恢复。它不读取或扣减旧创建额度,也不向模型或服务调用者暴露私有用例。运行时不用额外模型回合,而是对父制品和候选制品分别做全新的隔离发现与调用,要求完整工具结构和 SDK 环境一致,并将两侧结果各自与原用例期望比较。两侧完整原始结果可不同;任一侧未达到期望即拒绝。`databasePath + '.revision-regressions'` 存储独立 claim、额度及结果;调用不明、取消或私有证据缺失返回 `unknown`,未完成的 claim 在重启后也不自动重放 Docker 调用。
|
|
136
|
+
|
|
137
|
+
通过后独立签发 `assistant-growth/revision-regression/v1` Ed25519 凭证,绑定父凭证合同摘要、两侧观察、候选验收凭证、精确源码摘要、冻结的新任务 Growth run 与回归 authority。它只证明这些父保留用例在本次两个制品的隔离观察中达到原期望,不授予候选执行、工具版本切换、旧创建额度扩张或回滚权限。
|
|
138
|
+
|
|
139
|
+
父私有用例必须在首次签发时完整可用;已完成的同一 plan/binding 重试在当前来源围栏与授权窗口内返回原签名凭证,不重新读取用例、派发观察或恢复额度。签发后的私有记录丢失不撤销当时的历史证明,但不能据此为新候选恢复或重建用例。Control Plane 消费签名凭证时核对父凭证及合同摘要,不获得私有用例读取权限。
|
|
140
|
+
|
|
84
141
|
## 独立源码审查
|
|
85
142
|
|
|
86
143
|
`sourceReviews` 是可选 Host 能力,供 Control Plane 的 `sourceReleaseExecution.independentReview` 调用。复用当前 DSH `agents`、`sessions`、`tools`、`llm`、`systemPrompt` 与 `assistantPolicy`,不新增调度器。缺少这些服务时保持未就绪,依赖替换或卸载会取消并等待当前审查。Host 在 PR 前检查精确 owner、插件、模型、目录与剩余额度;已存在的 operation 可进入终态恢复核验。
|
|
@@ -119,3 +176,35 @@ Host 独立读取精确 PR ref、单一 base parent、改动范围和已检查 t
|
|
|
119
176
|
持久账本位于 `databasePath + '.source-reviews'`,目录须私有且 canonical。调用前落 claim;崩溃、取消或不明确结果不会自动重调模型。相同授权下的已完成批准可在再次核对来源与 PR 后恢复同一 decision 文件;改变政策、模型、目录或额度须使用新的授权标识。拒绝不会写批准文件。已 claim 的未知调用需要管理员核查本地 Session/账本,Host 返回的 `sessionId` 可定位该请求的原生会话;当前没有自动重审或模型自我批准入口。
|
|
120
177
|
|
|
121
178
|
新增权限为:读取固定 Git executable/仓库、执行受限 Git 读命令、经 Host 模型供应商发送任务目标与补丁、写私有 SQLite/Session/decision。模型不能读取凭据、执行命令或写文件。该进程内工具边界不构成 OS 隔离;候选构建与 decision 写权限必须由部署隔离。原始任务、补丁、审查输出和账本留本地,不提交到 GitHub。
|
|
179
|
+
|
|
180
|
+
## 普通任务记忆候选审查
|
|
181
|
+
|
|
182
|
+
可选 `memoryReviews` 提供 Host-only `reviewMemoryLearning(request, signal?)` 与
|
|
183
|
+
`lookupMemoryLearningReview(request)`。调用者只传共享库的候选和来源定位,不传入批准结论。
|
|
184
|
+
Host-only `inspectMemoryLearningReviewAvailability({ owner })` 返回当前配置授权的
|
|
185
|
+
`authorityId`、`authorityDigest`、`expiresAt`、`remainingReviews`、`available`。
|
|
186
|
+
它核对完整 owner 与当前 Delivery route、Policy 及私有账本;首次 claim 前显示配置上限,
|
|
187
|
+
到期、服务缺失、授权变化、账本损坏或额度耗尽时不可用。查询只读,不建立 claim、
|
|
188
|
+
消耗额度或调用模型;历史 unknown 仍须按原 operation ID 精确查询,不能通过该探针重派。
|
|
189
|
+
Verifier 独立读取 Delivery 原任务、普通回复与当前 owner;经验还须绑定当前 canonical
|
|
190
|
+
结果,允许保留失败经验。事实引用只能来自 owner 原文,任务未获目标结果不妨碍审查事实,
|
|
191
|
+
明确的 owner 撤回则会阻止审查。替换/删除还需 PersonalMemory 的 exact managed target reader;
|
|
192
|
+
缺少该服务或目标版本不符即拒绝,不把手动记录交给模型自动接管。
|
|
193
|
+
|
|
194
|
+
`memoryReviews` 必填字段为 `authorityId`、`owner`(同上七个 owner 字段)、`expiresAt`、
|
|
195
|
+
`maxReviews`、`policy`、`maxInputBytes`、`maxOutputTokens`、`timeoutMs`。`model` 可选,
|
|
196
|
+
默认继承原任务冻结的供应商、模型和推理强度。最多 10000 次审查、128 KiB 输入、8192 输出
|
|
197
|
+
tokens、每次 5 分钟;配置更改不能给原授权续期或补额度。Policy 还必须允许精确 background
|
|
198
|
+
subject `assistant-memory-learning`(绑定 workspace/principal),action `review`、memory resource
|
|
199
|
+
`learning:<authorityId>`;可通过该规则的持久预算进一步限制调用。未配置时没有默认审查权限。
|
|
200
|
+
|
|
201
|
+
原生审查使用新会话、固定规则和零工具,每次至多一次模型调用。它只判断候选是否受来源支持,
|
|
202
|
+
不证明事实在现实中为真或后续任务得到改善,也不直接写入 Memory。完整原文被截断时拒绝审查。
|
|
203
|
+
`.memory-reviews` 私有 SQLite 使用独立授权和持久 claim;重复调用/重启只回读既有结果,unknown
|
|
204
|
+
不重派。来源、owner、canonical 状态与目标版本在结束后重验,批准落盘使用
|
|
205
|
+
Delivery → Evaluation → review ledger 同步 writer fence;卸载会先取消并等待在途审查。
|
|
206
|
+
|
|
207
|
+
普通任务的自动发现、提取与调度见独立 [assistant-memory-learning](../assistant-memory-learning/README.md);
|
|
208
|
+
有限采用与下一任务召回由 [Memory](../personal-memory/README.md) 负责。批准回执不能替代采用时的当前来源与权限检查。新增数据权限仅为读取这些
|
|
209
|
+
owner 来源/受管理目标,经既有 Host 模型供应商发送有界文本,并写私有审查账本和原生会话;
|
|
210
|
+
无新增浏览器、子进程、凭据读取或安装脚本权限。
|
package/lib/config.d.ts
CHANGED
|
@@ -3,6 +3,10 @@ import type { AcceptanceTaskIdentity, TaskAcceptanceContract } from '@dsh-enhanc
|
|
|
3
3
|
import type { AcceptanceTask } from './host.js';
|
|
4
4
|
import type { VerifierAuthority, VerifierAuthorityInput } from './drivers.js';
|
|
5
5
|
import type { SourceReviewConfig } from './source-review.js';
|
|
6
|
+
import type { MemoryReviewConfig } from './memory-review.js';
|
|
7
|
+
import type { CreationReviewConfig } from './creation-review.js';
|
|
8
|
+
import type { RevisionReviewConfig } from './revision-review.js';
|
|
9
|
+
import type { RevisionRegressionReviewConfig } from './revision-regression-review.js';
|
|
6
10
|
/** A Host-owned exact task specification; editing it cannot rewrite accepted work. */
|
|
7
11
|
export interface AcceptanceProfile extends Omit<AcceptanceTask, 'task'> {
|
|
8
12
|
readonly id: string;
|
|
@@ -19,6 +23,10 @@ export interface Config {
|
|
|
19
23
|
tickIntervalMs?: number;
|
|
20
24
|
requireAcceptance?: boolean;
|
|
21
25
|
sourceReviews?: SourceReviewConfig;
|
|
26
|
+
memoryReviews?: MemoryReviewConfig;
|
|
27
|
+
creationReviews?: CreationReviewConfig;
|
|
28
|
+
revisionReviews?: RevisionReviewConfig;
|
|
29
|
+
revisionRegressions?: RevisionRegressionReviewConfig;
|
|
22
30
|
}
|
|
23
31
|
export declare const Config: Schema<Config>;
|
|
24
32
|
export interface CompiledAcceptanceProfile {
|
package/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAE7C,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAA;AAC5G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAE7C,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAA;AAC5G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAA;AAErF,sFAAsF;AACtF,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC;IACrE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAA;IACjD,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAA;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,MAAM;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC/C,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACvC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAClC,eAAe,CAAC,EAAE,oBAAoB,CAAA;IACtC,eAAe,CAAC,EAAE,oBAAoB,CAAA;IACtC,mBAAmB,CAAC,EAAE,8BAA8B,CAAA;CACrD;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CAWd,CAAA;AAEpB,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAClE,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACzC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAA;CAC/C,CAAC,CAkDD"}
|
package/lib/config.js
CHANGED
|
@@ -8,6 +8,10 @@ export const Config = Schema.object({
|
|
|
8
8
|
tickIntervalMs: Schema.number().step(1).min(0).max(60_000).default(5_000),
|
|
9
9
|
requireAcceptance: Schema.boolean().default(false),
|
|
10
10
|
sourceReviews: Schema.any(),
|
|
11
|
+
memoryReviews: Schema.any(),
|
|
12
|
+
creationReviews: Schema.any(),
|
|
13
|
+
revisionReviews: Schema.any(),
|
|
14
|
+
revisionRegressions: Schema.any(),
|
|
11
15
|
});
|
|
12
16
|
export function compileAcceptanceProfiles(config) {
|
|
13
17
|
const authorities = config.authorities === undefined || config.authorities.length === 0
|
package/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;AAG3J,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
export interface CreationModel {
|
|
3
|
+
provider: string;
|
|
4
|
+
model: string;
|
|
5
|
+
reasoningEffort?: string;
|
|
6
|
+
}
|
|
7
|
+
interface NativeInput {
|
|
8
|
+
sessionId: string;
|
|
9
|
+
owner: {
|
|
10
|
+
workspace: string;
|
|
11
|
+
agentPreset: string;
|
|
12
|
+
principalId: string;
|
|
13
|
+
};
|
|
14
|
+
model: CreationModel;
|
|
15
|
+
maxInputBytes: number;
|
|
16
|
+
maxOutputTokens: number;
|
|
17
|
+
prompt: string;
|
|
18
|
+
data: unknown;
|
|
19
|
+
signal: AbortSignal;
|
|
20
|
+
assertCurrent(): void;
|
|
21
|
+
}
|
|
22
|
+
/** Exactly one fresh, tool-free native Agent turn with a frozen supplier and budget. */
|
|
23
|
+
export declare function runNativeCreationTurn(ctx: Context, input: NativeInput): Promise<{
|
|
24
|
+
value: unknown;
|
|
25
|
+
outputDigest: string;
|
|
26
|
+
outputTokens: number;
|
|
27
|
+
sessionId: string;
|
|
28
|
+
}>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=creation-review-native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"creation-review-native.d.ts","sourceRoot":"","sources":["../src/creation-review-native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AASlD,MAAM,WAAW,aAAa;IAAG,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE;AAC5F,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;IACtE,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,WAAW,CAAA;IACnB,aAAa,IAAI,IAAI,CAAA;CACtB;AAED,wFAAwF;AACxF,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA+FxK"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { installModelSelection } from '@deepseek-ai/dsh-agent';
|
|
2
|
+
import { createUserMessage, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
3
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
4
|
+
import { growthObjectDigest } from '@dsh-enhanced/assistant-growth-contract';
|
|
5
|
+
/** Exactly one fresh, tool-free native Agent turn with a frozen supplier and budget. */
|
|
6
|
+
export async function runNativeCreationTurn(ctx, input) {
|
|
7
|
+
const { signal, model, owner, prompt, sessionId } = input;
|
|
8
|
+
const data = JSON.stringify(input.data);
|
|
9
|
+
if (Buffer.byteLength(prompt) + Buffer.byteLength(data) > input.maxInputBytes)
|
|
10
|
+
throw new Error('creation review input exceeds byte limit');
|
|
11
|
+
const nativeModel = { provider: model.provider, model: model.model,
|
|
12
|
+
...(model.reasoningEffort === undefined ? {} : { reasoningEffort: ReasoningEffortId(model.reasoningEffort) }) };
|
|
13
|
+
const agents = ctx.get('agents'), sessions = ctx.get('sessions');
|
|
14
|
+
const raw = ctx.get('assistantPolicy');
|
|
15
|
+
const policy = raw?.[Symbol.for('cordis.original')] ?? raw;
|
|
16
|
+
if (!agents || !sessions || !policy)
|
|
17
|
+
throw new Error('creation review native services unavailable');
|
|
18
|
+
let handle, calls = 0, chunksBytes = 0, violated = false;
|
|
19
|
+
try {
|
|
20
|
+
input.assertCurrent();
|
|
21
|
+
signal.throwIfAborted();
|
|
22
|
+
handle = await agents.create({ sessionId: SessionId(sessionId),
|
|
23
|
+
meta: { cwd: owner.workspace, agentPreset: owner.agentPreset },
|
|
24
|
+
agentOptions: { ...nativeModel, maxTokens: input.maxOutputTokens }, signal,
|
|
25
|
+
setup: async (agentCtx, preparedAgent) => {
|
|
26
|
+
const agent = preparedAgent;
|
|
27
|
+
if (!agent || agent.session.header.cwd !== owner.workspace
|
|
28
|
+
|| agent.session.header.agentPreset !== owner.agentPreset)
|
|
29
|
+
throw new Error('creation review Agent identity changed');
|
|
30
|
+
input.assertCurrent();
|
|
31
|
+
signal.throwIfAborted();
|
|
32
|
+
if (agent.session.snapshotEvents().some(event => event.type === 'assistant/message' || event.type === 'turn/end')) {
|
|
33
|
+
throw new Error('creation review session is not fresh');
|
|
34
|
+
}
|
|
35
|
+
agentCtx.effect(() => policy.bindInitiator(agent, 'background', owner.principalId), 'creation-review.initiator');
|
|
36
|
+
agentCtx.effect(() => installModelSelection(agentCtx, { current: nativeModel, assembled: undefined }), 'creation-review.model');
|
|
37
|
+
agentCtx.tools.restrict({ allow: [] });
|
|
38
|
+
if (agentCtx.tools.schemas(agent).length !== 0)
|
|
39
|
+
throw new Error('creation review tools are not empty');
|
|
40
|
+
agentCtx.tools.guard(() => {
|
|
41
|
+
violated = true;
|
|
42
|
+
agent.cancel({ kind: 'hook', reason: 'creation-review-tool-rejected' });
|
|
43
|
+
throw new Error('creation review tools forbidden');
|
|
44
|
+
});
|
|
45
|
+
agentCtx.on('system-prompt/assemble', async (_assembly, context, next) => {
|
|
46
|
+
const assembly = await next();
|
|
47
|
+
if (context.agent !== agent)
|
|
48
|
+
return assembly;
|
|
49
|
+
return { sections: [{ name: 'creation-review', text: prompt }], contexts: [], tools: [], variables: {} };
|
|
50
|
+
});
|
|
51
|
+
agentCtx.on('llm/stream', async function* (options, next) {
|
|
52
|
+
if (options.sessionId !== agent.session.id) {
|
|
53
|
+
yield* next();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
input.assertCurrent();
|
|
57
|
+
signal.throwIfAborted();
|
|
58
|
+
if (calls !== 0 || options.provider !== model.provider || options.model !== model.model
|
|
59
|
+
|| options.reasoningEffort !== model.reasoningEffort || options.maxTokens !== input.maxOutputTokens
|
|
60
|
+
|| (options.tools?.length ?? 0) !== 0 || agentCtx.tools.schemas(agent).length !== 0
|
|
61
|
+
|| options.system !== undefined || options.messages.length !== 2 || options.messages[0]?.role !== 'system'
|
|
62
|
+
|| growthObjectDigest(options.messages[0].content) !== growthObjectDigest([{ type: 'text', text: prompt }])
|
|
63
|
+
|| options.messages[1]?.role !== 'user' || growthObjectDigest(options.messages[1].content) !== growthObjectDigest([{ type: 'text', text: data }])
|
|
64
|
+
|| Buffer.byteLength(JSON.stringify(options.messages)) > input.maxInputBytes) {
|
|
65
|
+
violated = true;
|
|
66
|
+
agent.cancel({ kind: 'hook', reason: 'creation-review-contract-changed' });
|
|
67
|
+
throw new Error('creation review model contract changed');
|
|
68
|
+
}
|
|
69
|
+
calls++;
|
|
70
|
+
for await (const chunk of next()) {
|
|
71
|
+
signal.throwIfAborted();
|
|
72
|
+
chunksBytes += Buffer.byteLength(JSON.stringify(chunk));
|
|
73
|
+
if (chunksBytes > Math.max(65_536, input.maxOutputTokens * 128)
|
|
74
|
+
|| chunk.type === 'tool-call-delta' || chunk.type === 'block-start' && chunk.blockType === 'tool-call'
|
|
75
|
+
|| chunk.type === 'block-end' && chunk.block.type === 'tool-call') {
|
|
76
|
+
violated = true;
|
|
77
|
+
agent.cancel({ kind: 'hook', reason: 'creation-review-output-rejected' });
|
|
78
|
+
throw new Error('creation review output contract changed');
|
|
79
|
+
}
|
|
80
|
+
yield chunk;
|
|
81
|
+
}
|
|
82
|
+
signal.throwIfAborted();
|
|
83
|
+
input.assertCurrent();
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const agent = handle.agent;
|
|
88
|
+
const abort = () => agent.cancel({ kind: 'hook', reason: 'creation-review-cancelled' });
|
|
89
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
90
|
+
try {
|
|
91
|
+
signal.throwIfAborted();
|
|
92
|
+
agent.followup(createUserMessage({ content: [{ type: 'text', text: data }],
|
|
93
|
+
source: { kind: 'assistant-verifier', form: 'notice', summary: 'Independent creation verification' } }));
|
|
94
|
+
await agent.whenIdle();
|
|
95
|
+
signal.throwIfAborted();
|
|
96
|
+
input.assertCurrent();
|
|
97
|
+
const events = agent.session.snapshotEvents();
|
|
98
|
+
const messages = events.filter(event => event.type === 'assistant/message');
|
|
99
|
+
const ends = events.filter(event => event.type === 'turn/end');
|
|
100
|
+
if (violated || calls !== 1 || messages.length !== 1 || ends.length !== 1
|
|
101
|
+
|| ends[0].data.reason?.kind !== 'completed')
|
|
102
|
+
throw new Error('creation review did not complete exactly one turn');
|
|
103
|
+
const usage = messages[0].data.usage;
|
|
104
|
+
if (!usage || !Number.isSafeInteger(usage.inputTokens) || usage.inputTokens < 0
|
|
105
|
+
|| !Number.isSafeInteger(usage.outputTokens) || usage.outputTokens < 0 || usage.outputTokens > input.maxOutputTokens) {
|
|
106
|
+
throw new Error('creation review usage missing or over budget');
|
|
107
|
+
}
|
|
108
|
+
const content = messages[0].data.message?.content;
|
|
109
|
+
if (!Array.isArray(content) || content.some(block => !['text', 'reasoning'].includes(block.type)))
|
|
110
|
+
throw new Error('creation review has nontext output');
|
|
111
|
+
const output = content.filter(block => block.type === 'text').map(block => block.text).join('');
|
|
112
|
+
if (!output || Buffer.byteLength(output) > 32_768)
|
|
113
|
+
throw new Error('creation review output too large or missing');
|
|
114
|
+
const value = JSON.parse(output);
|
|
115
|
+
await sessions.flush(agent.session);
|
|
116
|
+
signal.throwIfAborted();
|
|
117
|
+
input.assertCurrent();
|
|
118
|
+
return { value, outputDigest: growthObjectDigest(value), outputTokens: usage.outputTokens, sessionId };
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
signal.removeEventListener('abort', abort);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await handle?.dispose();
|
|
126
|
+
signal.throwIfAborted();
|
|
127
|
+
input.assertCurrent();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=creation-review-native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"creation-review-native.js","sourceRoot":"","sources":["../src/creation-review-native.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type PluginCreationVerificationCertificate } from '@dsh-enhanced/assistant-growth-contract';
|
|
2
|
+
/** Every dispatch is claimed durably first. A claimed or unknown stage is never replayed. */
|
|
3
|
+
export declare class CreationReviewStore<Certificate = PluginCreationVerificationCertificate> {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(path: string);
|
|
6
|
+
close(): void;
|
|
7
|
+
remaining(authority: string, digest: string, maximum: number): number;
|
|
8
|
+
/** Historical private evidence only; no grant read, claim, or quota mutation. */
|
|
9
|
+
readRetained(plan: string): Readonly<{
|
|
10
|
+
certificate: Certificate;
|
|
11
|
+
discovery: unknown;
|
|
12
|
+
contract: unknown;
|
|
13
|
+
cases: Record<string, unknown>;
|
|
14
|
+
}> | undefined;
|
|
15
|
+
claim(plan: string, binding: string, authority: string, digest: string, maximum: number): {
|
|
16
|
+
state: 'new' | 'unknown' | 'rejected' | 'certificate';
|
|
17
|
+
reason?: string;
|
|
18
|
+
certificate?: Certificate;
|
|
19
|
+
};
|
|
20
|
+
discovered(plan: string, binding: string, discovery: unknown): void;
|
|
21
|
+
contract(plan: string, binding: string, contract: unknown): void;
|
|
22
|
+
claimCase(plan: string, binding: string, caseId: string, operationDigest: string): void;
|
|
23
|
+
observation(plan: string, binding: string, caseId: string, observed: unknown): void;
|
|
24
|
+
claimReview(plan: string, binding: string): void;
|
|
25
|
+
reject(plan: string, binding: string, reason: string): void;
|
|
26
|
+
unknown(plan: string, binding: string, reason: string): void;
|
|
27
|
+
certificate(plan: string, binding: string, certificate: Certificate): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=creation-review-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"creation-review-store.d.ts","sourceRoot":"","sources":["../src/creation-review-store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,qCAAqC,EAAE,MAAM,yCAAyC,CAAA;AAmBzH,6FAA6F;AAC7F,qBAAa,mBAAmB,CAAC,WAAW,GAAG,qCAAqC;;gBAGtE,IAAI,EAAE,MAAM;IAqBxB,KAAK,IAAI,IAAI;IAOb,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IASrE,iFAAiF;IACjF,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;QAAE,WAAW,EAAE,WAAW,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QACrG,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,GAAG,SAAS;IAe/C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GACrF;QAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,WAAW,CAAA;KAAE;IAqCvG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAGnE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAGhE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAIvF,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAQnF,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAOhD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAG3D,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAa5D,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI;CAG3E"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { closeSync, constants, lstatSync, mkdirSync, openSync, realpathSync } from 'node:fs';
|
|
2
|
+
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
3
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
4
|
+
import { canonicalGrowthJson } from '@dsh-enhanced/assistant-growth-contract';
|
|
5
|
+
const SHA = /^[a-f0-9]{64}$/u;
|
|
6
|
+
const ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$/u;
|
|
7
|
+
function fail(message) { throw new Error(`creation review store: ${message}`); }
|
|
8
|
+
function check(idValue, digestValue) {
|
|
9
|
+
if (!ID.test(idValue) || !SHA.test(digestValue))
|
|
10
|
+
fail('invalid identity');
|
|
11
|
+
}
|
|
12
|
+
function privateFile(path) {
|
|
13
|
+
const stat = lstatSync(path);
|
|
14
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1 || stat.mode & 0o077
|
|
15
|
+
|| process.getuid && stat.uid !== process.getuid() || realpathSync(path) !== path)
|
|
16
|
+
fail('database must be private');
|
|
17
|
+
}
|
|
18
|
+
/** Every dispatch is claimed durably first. A claimed or unknown stage is never replayed. */
|
|
19
|
+
export class CreationReviewStore {
|
|
20
|
+
#db;
|
|
21
|
+
#closed = false;
|
|
22
|
+
constructor(path) {
|
|
23
|
+
if (!isAbsolute(path) || resolve(path) !== path)
|
|
24
|
+
fail('invalid path');
|
|
25
|
+
const parent = dirname(path);
|
|
26
|
+
mkdirSync(parent, { recursive: true, mode: 0o700 });
|
|
27
|
+
const directory = lstatSync(parent);
|
|
28
|
+
if (!directory.isDirectory() || directory.isSymbolicLink() || directory.mode & 0o077
|
|
29
|
+
|| process.getuid && directory.uid !== process.getuid() || realpathSync(parent) !== parent)
|
|
30
|
+
fail('directory must be private');
|
|
31
|
+
try {
|
|
32
|
+
closeSync(openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_RDWR | constants.O_NOFOLLOW, 0o600));
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error.code !== 'EEXIST')
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
privateFile(path);
|
|
39
|
+
for (const suffix of ['-wal', '-shm', '-journal']) {
|
|
40
|
+
try {
|
|
41
|
+
privateFile(path + suffix);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error.code !== 'ENOENT')
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
this.#db = new DatabaseSync(path);
|
|
49
|
+
try {
|
|
50
|
+
this.#db.exec(`PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL;
|
|
51
|
+
CREATE TABLE IF NOT EXISTS grants(authority TEXT PRIMARY KEY,digest TEXT NOT NULL,maximum INTEGER NOT NULL,used INTEGER NOT NULL);
|
|
52
|
+
CREATE TABLE IF NOT EXISTS verifications(plan TEXT PRIMARY KEY,binding TEXT NOT NULL,authority TEXT NOT NULL,
|
|
53
|
+
state TEXT NOT NULL,data TEXT NOT NULL);`);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
this.#db.close();
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
close() { if (!this.#closed) {
|
|
61
|
+
this.#closed = true;
|
|
62
|
+
this.#db.close();
|
|
63
|
+
} }
|
|
64
|
+
#transaction(callback) {
|
|
65
|
+
if (this.#closed)
|
|
66
|
+
fail('closed');
|
|
67
|
+
this.#db.exec('BEGIN IMMEDIATE');
|
|
68
|
+
try {
|
|
69
|
+
const result = callback();
|
|
70
|
+
this.#db.exec('COMMIT');
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
this.#db.exec('ROLLBACK');
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
remaining(authority, digest, maximum) {
|
|
79
|
+
check(authority, digest);
|
|
80
|
+
if (!Number.isSafeInteger(maximum) || maximum < 1 || maximum > 1000)
|
|
81
|
+
fail('invalid quota');
|
|
82
|
+
const row = this.#db.prepare('SELECT * FROM grants WHERE authority=?').get(authority);
|
|
83
|
+
if (!row)
|
|
84
|
+
return maximum;
|
|
85
|
+
if (row.digest !== digest || row.maximum !== maximum || !Number.isSafeInteger(row.used)
|
|
86
|
+
|| row.used < 0 || row.used > maximum)
|
|
87
|
+
fail('grant changed or corrupt');
|
|
88
|
+
return maximum - row.used;
|
|
89
|
+
}
|
|
90
|
+
/** Historical private evidence only; no grant read, claim, or quota mutation. */
|
|
91
|
+
readRetained(plan) {
|
|
92
|
+
if (this.#closed || !ID.test(plan))
|
|
93
|
+
fail('invalid retained identity');
|
|
94
|
+
const row = this.#db.prepare('SELECT state,data FROM verifications WHERE plan=?').get(plan);
|
|
95
|
+
if (!row || row.state !== 'certificate')
|
|
96
|
+
return undefined;
|
|
97
|
+
if (Buffer.byteLength(row.data) > 262_144)
|
|
98
|
+
fail('retained record too large');
|
|
99
|
+
const data = JSON.parse(row.data);
|
|
100
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)
|
|
101
|
+
|| Object.keys(data).sort().join(',') !== 'cases,certificate,contract,discovery'
|
|
102
|
+
|| canonicalGrowthJson(data) !== row.data)
|
|
103
|
+
fail('retained record changed');
|
|
104
|
+
const evidence = data;
|
|
105
|
+
if (evidence.certificate === undefined || evidence.discovery === undefined || evidence.contract === undefined
|
|
106
|
+
|| !evidence.cases || typeof evidence.cases !== 'object' || Array.isArray(evidence.cases))
|
|
107
|
+
fail('retained evidence incomplete');
|
|
108
|
+
return { certificate: evidence.certificate, discovery: evidence.discovery, contract: evidence.contract, cases: evidence.cases };
|
|
109
|
+
}
|
|
110
|
+
claim(plan, binding, authority, digest, maximum) {
|
|
111
|
+
check(plan, binding);
|
|
112
|
+
check(authority, digest);
|
|
113
|
+
if (!Number.isSafeInteger(maximum) || maximum < 1 || maximum > 1000)
|
|
114
|
+
fail('invalid quota');
|
|
115
|
+
return this.#transaction(() => {
|
|
116
|
+
const grant = this.#db.prepare('SELECT * FROM grants WHERE authority=?').get(authority);
|
|
117
|
+
if (grant && (grant.digest !== digest || grant.maximum !== maximum || grant.used < 0 || grant.used > maximum))
|
|
118
|
+
fail('grant changed or corrupt');
|
|
119
|
+
const old = this.#db.prepare('SELECT * FROM verifications WHERE plan=?').get(plan);
|
|
120
|
+
if (old) {
|
|
121
|
+
if (old.binding !== binding || old.authority !== authority || !grant)
|
|
122
|
+
fail('binding changed');
|
|
123
|
+
const data = JSON.parse(old.data);
|
|
124
|
+
if (old.state === 'certificate') {
|
|
125
|
+
if (!data.certificate)
|
|
126
|
+
fail('certificate missing');
|
|
127
|
+
return { state: 'certificate', certificate: data.certificate };
|
|
128
|
+
}
|
|
129
|
+
if (old.state === 'rejected' || old.state === 'unknown') {
|
|
130
|
+
if (!data.reason)
|
|
131
|
+
fail('rejection missing');
|
|
132
|
+
return { state: old.state, reason: data.reason };
|
|
133
|
+
}
|
|
134
|
+
return { state: 'unknown' };
|
|
135
|
+
}
|
|
136
|
+
if (grant && grant.used >= maximum)
|
|
137
|
+
fail('quota exhausted');
|
|
138
|
+
if (!grant)
|
|
139
|
+
this.#db.prepare('INSERT INTO grants VALUES(?,?,?,0)').run(authority, digest, maximum);
|
|
140
|
+
this.#db.prepare('UPDATE grants SET used=used+1 WHERE authority=?').run(authority);
|
|
141
|
+
this.#db.prepare('INSERT INTO verifications VALUES(?,?,?,?,?)').run(plan, binding, authority, 'discover-claimed', '{}');
|
|
142
|
+
return { state: 'new' };
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
#advance(plan, binding, from, to, update) {
|
|
146
|
+
this.#transaction(() => {
|
|
147
|
+
const row = this.#db.prepare('SELECT * FROM verifications WHERE plan=?').get(plan);
|
|
148
|
+
if (!row || row.binding !== binding || row.state !== from)
|
|
149
|
+
fail('stage changed');
|
|
150
|
+
const data = update(JSON.parse(row.data));
|
|
151
|
+
const serialized = canonicalGrowthJson(data);
|
|
152
|
+
if (Buffer.byteLength(serialized) > 262_144)
|
|
153
|
+
fail('record too large');
|
|
154
|
+
this.#db.prepare('UPDATE verifications SET state=?,data=? WHERE plan=?').run(to, serialized, plan);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
discovered(plan, binding, discovery) {
|
|
158
|
+
this.#advance(plan, binding, 'discover-claimed', 'contract-claimed', data => ({ ...data, discovery }));
|
|
159
|
+
}
|
|
160
|
+
contract(plan, binding, contract) {
|
|
161
|
+
this.#advance(plan, binding, 'contract-claimed', 'contract-ready', data => ({ ...data, contract, cases: {} }));
|
|
162
|
+
}
|
|
163
|
+
claimCase(plan, binding, caseId, operationDigest) {
|
|
164
|
+
check(caseId, operationDigest);
|
|
165
|
+
this.#advance(plan, binding, 'contract-ready', 'case-claimed', data => ({ ...data, activeCase: { caseId, operationDigest } }));
|
|
166
|
+
}
|
|
167
|
+
observation(plan, binding, caseId, observed) {
|
|
168
|
+
this.#advance(plan, binding, 'case-claimed', 'contract-ready', data => {
|
|
169
|
+
const active = data;
|
|
170
|
+
if (active.activeCase?.caseId !== caseId || Object.hasOwn(data.cases ?? {}, caseId))
|
|
171
|
+
fail('case changed');
|
|
172
|
+
const { activeCase: _, ...rest } = active;
|
|
173
|
+
return { ...rest, cases: { ...data.cases, [caseId]: observed } };
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
claimReview(plan, binding) {
|
|
177
|
+
this.#advance(plan, binding, 'contract-ready', 'review-claimed', data => {
|
|
178
|
+
const contract = data.contract;
|
|
179
|
+
if (!contract?.cases || Object.keys(data.cases ?? {}).length !== contract.cases.length)
|
|
180
|
+
fail('cases incomplete');
|
|
181
|
+
return data;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
reject(plan, binding, reason) {
|
|
185
|
+
this.#terminal(plan, binding, reason, 'rejected');
|
|
186
|
+
}
|
|
187
|
+
unknown(plan, binding, reason) {
|
|
188
|
+
this.#terminal(plan, binding, reason, 'unknown');
|
|
189
|
+
}
|
|
190
|
+
#terminal(plan, binding, reason, state) {
|
|
191
|
+
if (!reason.trim() || reason.length > 4096)
|
|
192
|
+
fail('invalid reason');
|
|
193
|
+
this.#transaction(() => {
|
|
194
|
+
const row = this.#db.prepare('SELECT * FROM verifications WHERE plan=?').get(plan);
|
|
195
|
+
if (!row || row.binding !== binding || row.state === 'certificate' || row.state === 'rejected' || row.state === 'unknown')
|
|
196
|
+
fail('stage changed');
|
|
197
|
+
const data = JSON.parse(row.data);
|
|
198
|
+
this.#db.prepare('UPDATE verifications SET state=?,data=? WHERE plan=?')
|
|
199
|
+
.run(state, canonicalGrowthJson({ ...data, reason }), plan);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
certificate(plan, binding, certificate) {
|
|
203
|
+
this.#advance(plan, binding, 'review-claimed', 'certificate', data => ({ ...data, certificate }));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=creation-review-store.js.map
|