@dsh-enhanced/assistant-growth-driver 0.1.34

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-enhanced contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # @dsh-enhanced/assistant-growth-driver
2
+
3
+ 默认关闭的有界后台成长驱动。可通过 `usageLearning` 让真实前台任务结果自动触发持久成长作业,或由 Host 显式唤醒。Agent 回顾 owner 的已验收成功、沉淀 pending 技能候选;启用源码轨后可准备已有 gap 对应的插件修改提案。当前自动入口已接通,修复后的有限采用与持续观察需另配 Control Plane;可安装部署与独立行为验收仍未贯通,`reviewed` 仅表示本次成长复盘结束。
4
+
5
+ 同一插件内还有**第二条、独立开关**的学习轨 `workflowOwnerAnchored`(默认关闭):它不起模型、不触网,只在本地枚举最近完成的 owner-root goal,把 locator(不含任何 prompt/步骤/验收结论)交给 `assistant-delivery`;由 Delivery 自己再调 goals 的 `inspectOwnerVerifiedWorkflowSource` 独立复核(owner-root、whole-goal succeeded 且 quiescent、cwd/preset 精确匹配),只接受可诚实归约为**单步零工具 agent-turn** 的 goal,通过后经 content-free trace v2 沉淀为 workflow growth candidate,并由 Growth 以 **paused** automation 落库待 owner 批准。自由 objective 无法跨任务聚齐重复门,故该轨**单条即沉淀**:每个独立复核通过的成功 goal 产一条独立 paused 候选。候选带冻结的**占位 cron**(`0 0 29 2 *` UTC,由 store 的激活门阻断执行);automations 在 store 层 fail-closed——Growth 所属且仍带占位 schedule 的 workflow 无法经 owner 批准 `resume` 或系统 reconcile 转 active,必须先由 owner 显式做一次 schedule mutation(换真 cron)。该轨同样零 approve/activate/install。
6
+
7
+ 自动成长默认继承 Delivery 随来源任务保存的实际 `request/header` 模型快照,包括 adapter 默认 reasoning effort;历史来源不读取后来切换的会话模型。可同时配置 `provider` / `model` 固定覆盖。Host 显式 `wake({ sourceAgent })` 读取该 Agent 的实际请求,普通周期 wake 仍读取外部会话当前选择。原生 Web 无来源时不猜模型。`health().run.model` 记录本轮模型;已派发但中断的持久作业保持 unknown,不换模型或自动重放。
8
+
9
+ ## 安装
10
+
11
+ 先装好 `assistant-delivery`、`assistant-goals`、`assistant-skills`、`assistant-policy` 和所用模型 adapter,再安装本包。只有选用 super-relay 时才需要安装并启用 `assistant-super-relay-budget`:
12
+
13
+ ```sh
14
+ dsh plugin --profile web add @dsh-enhanced/assistant-growth-driver
15
+ dsh --profile web --dump-config
16
+ ```
17
+
18
+ 包内 `cordis.patch.yml` 只注册插件、不带任何 `enabled` 配置,因此**安装后处于休眠状态**:无 timer、不起 Agent、零写入。第一期不随任何生产 profile 默认启用。
19
+
20
+ ## 工作机制
21
+
22
+ 每次唤醒(`intervalMs > 0` 的 unref timer,或显式调用 `wake()`):
23
+
24
+ 1. **Preflight(不触网、不起 Agent)**:用配置中冻结的 owner scope 经 `assistantDelivery.validateOwnerRoute` 重新锚定真实 owner route 并铸造一枚短-lived authority(寿命 `≤ maxDurationMs`,硬顶 300000ms,每次使用都重新校验 route,route 漂移即整轮作废);读取并冻结所选模型;仅使用 super-relay 时检查其契约和默认凭据引用,其他供应由对应 DSH adapter 管理凭据;确认 policy 服务在线;可选地预留 owner 配置的后台预算。
25
+ 2. **有界后台 Agent**:照 `assistant-skills` repair-agent 的冻结范式运行——`llm/stream` 逐请求钉 provider/model/maxTokens/tools digest,`tools.guard` 白名单 + 双预算计数,system-prompt 按身份过滤,`deadline = min(expiresAt, now + maxDurationMs)` 到点 abort。刻意**不挂载任何 preset**:默认工具面恰好是下面四个 `growth_*` realm 工具;显式开启源码提案且 control-plane 服务在线且配置了构建器时增加三个 `plugin_source_*` 工具。任何其它可见工具都会在发请求前被拒绝。
26
+ - `growth_list_owner_goals`:列最近的 owner-root goal(只读投影)。
27
+ - `growth_read_verified_workflow`:读一条已完成 goal 的**脱敏**摘要;Host 独立复核 owner-root(非 subagent、无 parent session、delegationDepth=0)、whole-goal succeeded 且 quiescent,cwd/preset 精确匹配;不返回步骤参数与验收回执。
28
+ - `growth_list_skills`:列该 owner 的 active skill 与 pending candidate,避免重名。
29
+ - `growth_propose_skill_candidate`:唯一的写工具,只产「提议」。
30
+ 3. **Host 侧复核沉淀(系统 authority,非模型)**:提议携带的每个 `{session_id, goal_id}` 都由 skills 服务经 goals 独立重读、逐条重新验收;必须有 **≥ `minRepeatedSuccesses` 个不同** 的 owner-verified 成功(模型无法把门槛降到配置值以下,谎报/伪造/重复 locator 一律拒绝且零写入),同名 active / pending / retired 冲突不写。通过后只 `stageCandidate` 产一条 **pending candidate**(TTL ≤ 7 天,带 reason/trigger/parentVersion):不进 current 版本,`skill_run` 不可达。
31
+
32
+ ## 配置与使用
33
+
34
+ 所有配置项 fail-closed;未知字段直接报错。
35
+
36
+ | 字段 | 默认 | 说明 |
37
+ | --- | --- | --- |
38
+ | `enabled` | `false` | 必须显式置 `true` 才运行;且启用时必须同时声明 `scope`,否则启动报错。 |
39
+ | `scope` | 无 | 冻结的 owner 四字段 `workspace` / `preset` / `principalId` / `ownerRouteId`。driver 只在该 scope 内动作,identity 不从模型输出派生。`ownerRouteId` 必须是 Delivery 中既有的、已认证的 owner route id;route 不存在/不匹配时每轮跳过并记 `missing-binding`。 |
40
+ | `intervalMs` | `0` | 显式 wake 的可选周期(上限 24h);启用 `usageLearning` 时必须为 `0`,由 Automations 负责调度。 |
41
+ | `minRepeatedSuccesses` | `3` | Host 侧重复门下限(1–32),模型提交值只允许更高。 |
42
+ | `maxReviewsPerWake` | `10` | 每轮枚举历史 goal 的条数上限(1–50)。 |
43
+ | `candidateTtlMs` | `86400000` | pending candidate TTL,schema 硬顶 7 天。 |
44
+ | `maxModelCalls` / `maxToolCalls` / `maxOutputTokens` | `8` / `24` / `8192` | 单轮预算,到顶即 abort/cancel。 |
45
+ | `maxDurationMs` | `120000` | 单轮墙钟上限,**硬顶 300000ms**(安全根,配置不可越过)。 |
46
+ | `budgetId` / `budgetAmount` | 均无 | 必须**同时出现**;显式 wake 经 Policy 预留;usage 作业由 Automations 预留,避免重复扣取。已提交的未知消耗不退回。 |
47
+ | `provider` / `model` | 继承会话 | 同时配置以固定修复/成长模型;只配置一个会拒绝。不会自动回退到 Day1。 |
48
+ | `reasoningEffort` | 继承会话;固定模型时用供应默认 | 只有同时配置固定 provider/model 时可覆盖。 |
49
+ | `apiKeyEnv` | 随供应 | 可选凭据引用名;未设置时,super-relay 使用 `SUPER_RELAY_API_KEY`,其他供应由对应 adapter 管理。引用优先经 credentials 解析,再读同名环境变量;不接受或打印明文 key。 |
50
+ | `workflowOwnerAnchored.enabled` | `false` | owner-anchored workflow 轨独立开关;置 `true` 时要求驱动本体 `enabled: true` 且已声明 `scope`,否则启动报错。 |
51
+ | `workflowOwnerAnchored.maxCommitsPerWake` | `5` | 单轮最多尝试提交的候选数(1–50);goals/delivery 不可用、authority/route 漂移即中断本轮。幂等重放代价很低。 |
52
+ | `pluginSourceProposals.enabled` | `false` | 开启后通过可选 `pluginControlPlane` 服务准备既有插件的 pending 修改提案。缺少该服务或构建器未配置时仍保持四工具基线。 |
53
+ | `pluginSourceProposals.repository` | 无 | 开启时必填的绝对规范仓库路径;由 owner 配置,模型不可传入。 |
54
+ | `pluginSourceProposals.preparationMode` | `inline` | `inline` 保持本轮隔离构建;`durable` 只把已读、冻结 base 的内容排入 Control Plane 自己的持久队列。队列 authority、构建超时和执行生命周期都由 Control Plane 配置,独立于模型 wake。 |
55
+ | `pluginSourceProposals.maxPlansPerWake` | `1` | 每轮源码提案尝试上限(1–5);inline 的 prepared 与 durable 的 queued 都占用此预算,失败也占一次。 |
56
+ | `pluginSourceProposals.isolatedBuildTimeoutMs` | `180000` | 仅 `inline` 使用的构建时间上限(60000–240000ms);控制面可进一步收窄,单轮 authority 到期仍会取消。`durable` 使用控制面 `sourceBuild.timeoutMs`。 |
57
+ | `pluginSourceProposals.offline` | `true` | 源码提案必须离线构建;`false` 配置会拒绝。镜像须预先准备依赖。 |
58
+ | `pluginSourceProposals.planTtlMs` | `86400000` | 待批 worktree 保留期限(15 分钟–24 小时)。 |
59
+ | `workflowOwnerAnchored.lookbackMs` | `86400000` | 只枚举该回看窗口内更新过的 owner goal(1 分钟–7 天)。 |
60
+ | `usageLearning.enabled` | `false` | 真实任务触发开关;要求主开关、owner scope、预算及 Evaluation/Automations 服务。 |
61
+ | `usageLearning.databasePath` | 无 | 开启时必填的私有 SQLite 绝对路径,保存游标、冻结来源与作业状态。 |
62
+ | `usageLearning.maxPending` | `16` | 同时 queued/running 上限(1–100);满时保留未消费游标,释放容量后继续。 |
63
+ | `usageLearning.lookbackMs` | `86400000` | 来源结果最大年龄与排队 TTL(1 分钟–7 天)。 |
64
+
65
+ super-relay 自身的 5 个键(`enabled` / `apiKeyEnv` / `timeoutMs` / `maxResponseBytes` / `defaultMaxTokens`)在 `assistant-super-relay-budget` 插件上配置;driver 不重复定义。
66
+
67
+ ### copy-paste opt-in 片段
68
+
69
+ 在 profile 的 `cordis.patch.yml` 中插入本插件(路径/身份按实际 owner 替换):
70
+
71
+ ```yaml
72
+ - insert:
73
+ - id: dsh-enhanced-assistant-growth-driver
74
+ name: '@dsh-enhanced/assistant-growth-driver'
75
+ config:
76
+ enabled: true
77
+ intervalMs: 3600000
78
+ minRepeatedSuccesses: 3
79
+ maxDurationMs: 120000
80
+ # 默认继承会话;需要固定模型时添加以下两项:
81
+ # provider: super-relay
82
+ # model: auto_model/alwaysday1
83
+ scope:
84
+ workspace: /abs/path/to/owner/workspace
85
+ preset: primary
86
+ principalId: owner-1
87
+ ownerRouteId: <exact-delivery-owner-route-id>
88
+ budgetId: growth-budget
89
+ budgetAmount: 1
90
+ # 第二条、独立开关的学习轨;整段删除即保持关闭。
91
+ workflowOwnerAnchored:
92
+ enabled: true
93
+ maxCommitsPerWake: 5
94
+ lookbackMs: 86400000
95
+ ```
96
+
97
+ owner-anchored 轨不需要额外 policy 规则:它不挂模型 Agent,唯一写动作是 Host-only 的 Delivery 提交口(系统 authority,非模型面)。产出的 paused automation 需 owner 在 automations 既有审批面处理——**批准 resume 前必须先把占位 cron 显式改成真实 schedule**,否则批准会落 `conflicted` 且行保持 paused(这是 store 层硬门,不是 UI 提示)。
98
+
99
+ 后台 Agent 以 `background` initiator 绑定 owner principal;policy 默认空规则全拒,需在 `dsh-enhanced-assistant-policy` 的 `rules` 中补两条最小 allow(主体 id 是 scope 的 preset,workspace/principal 必须与 scope 精确一致):
100
+
101
+ ```yaml
102
+ rules:
103
+ - id: growth-draft
104
+ effect: allow
105
+ subject: { kind: agent, id: primary, workspace: /abs/path/to/owner/workspace, principal: owner-1 }
106
+ actions: [draft]
107
+ resource: { kind: evolution, id: verified-workflows }
108
+ context: { initiators: [background] }
109
+ - id: growth-tool-execute
110
+ effect: allow
111
+ subject: { kind: agent, id: primary, workspace: /abs/path/to/owner/workspace, principal: owner-1 }
112
+ actions: [execute]
113
+ resource: { kind: tool, id: 'growth_*' }
114
+ context: { initiators: [background] }
115
+ ```
116
+
117
+ 使用 `budgetId` 时还要在 policy `budgets` 中存在同 id、`scope: subject` 的预算。任何规则都只授予「读历史 + 提 pending 候选」;driver 不注册、也不需要 save/activate/install/retire/rollback 权限。
118
+
119
+ ### 观察与关闭
120
+
121
+ - 服务方法 `health()` 返回最近一次唤醒的 `lastWakeAt` / `outcome`(`never-run`/`ran`/`skipped`/`failed`)/ `reason` / 运行用量;跳过原因包括 `missing-scope`、`missing-binding:*`、`contract-expired:*`、`missing-credential`、`missing-policy`、`budget:*`。
122
+ - `health().ownerAnchored`(仅该轨启用且本轮跑过时存在)给本地轨计数:`considered`(窗口内完成的 goal)/ `attempted`(实际尝试提交)/ `recorded`(新沉淀)/ `replayed`(幂等重放)/ `abstained`(多工具等无法归约为单步 agent-turn,诚实跳过)/ `stopped`(非空时为 fail-closed 中断原因,如 `inspect:*`、`authority:*`、`runtime-unavailable:*`)。
123
+ - 停用:把 `enabled` 置回 `false`(或移除插件配置)即恢复休眠,不影响已经 staged 的 pending candidate——它们仍只由 owner 在既有 skills/automations 审批面处理。
124
+
125
+ ## 既有插件源码提案
126
+
127
+ 源码审阅与技能沉淀分别执行:启用本能力后,即使没有历史完成目标,也会检查已登记的开放 gap。重复、独立验收成功仍是技能候选的必要条件;源码候选按 gap、读取版本、权限和隔离检查规则准入。
128
+
129
+ 另行安装同批 `plugin-control-plane`,按其 README 配置 owner trust 和隔离构建镜像,再给 driver 增加:
130
+
131
+ ```yaml
132
+ pluginSourceProposals:
133
+ enabled: true
134
+ preparationMode: durable # 删除或设为 inline 时保持当前同步构建行为
135
+ repository: /abs/path/to/dsh-enhanced
136
+ maxPlansPerWake: 1
137
+ isolatedBuildTimeoutMs: 180000
138
+ offline: true
139
+ planTtlMs: 86400000
140
+ ```
141
+
142
+ 这段是 driver 完整配置的补充。DSH patch 的 `config` 为整值替换,覆盖配置时必须同时保留 `enabled`、`scope` 和其它需要的值。Policy 还需对相同 owner、workspace、preset 和 `background` initiator 授予 `execute` / `tool:plugin_source_*`。
143
+
144
+ Agent 先通过 `plugin_source_gaps` 发现 owner 配置的控制面账本中已有的开放 gap,通过 `plugin_source_read` 列出并读取目标插件在 Git 提交中的文本源码,最后通过 `plugin_source_prepare` 提交 `gap_id`、`plugin_name` 与两种互补的修改输入:新增短文件或完整替换用 `files: [{path, content}]`;已读的长既有文件用 `edits: [{path, before, after}]`。每个 `before` 必须在本轮缓存的原始文本中精确且唯一地出现,编辑按原始偏移处理,且不能重叠;`files` 与 `edits` 可以一起使用,但路径必须互不相同。Host 先展开为完整文件再交给 Control Plane,模型不会从确认结果取回缓存源码。普通手动 wake 读取既有手工 gap,这类记录没有逐条 owner 来源证明,多 owner 部署仍须隔离手工账本。启用下述 `usageLearning` 时只读取本次可信失败的专属 gap,绝不退回全局列表。至少提供一种非空输入;两种输入合计最多 64 项,单个完整内容、`before`、`after` 与最终每个文件最多 64 KiB,最终完整文件最多 64 个、合计 256 KiB。模型不能给仓库路径、命令、镜像、环境、TTL、审批或发布参数。安全根插件由 driver 和控制面同时拒绝。
145
+
146
+ `plugin_source_read` 接收 `gap_id`、`plugin_name`、`paths`;`paths: []` 返回文件清单,再按需读取源码、测试、README、package.json 和 patch。只读取已提交的文本,不读取工作区改动、未跟踪文件、符号链接、隐藏文件或生成目录。单文件最多 64 KiB,每轮内容累计最多 256 KiB,并受现有工具调用次数与运行时限控制。读取的内容属于不可信数据,不能改变工具权限。
147
+
148
+ Host 在本轮内按 gap 与插件保存首次读取的 commit,后续读取和准备均绑定该 commit;HEAD 变化即拒绝旧上下文。同一文件在同一 commit 的再次读取若内容漂移也会拒绝。完整替换既有文件前必须读取原内容;精确编辑只能作用于已读的既有文件,可在已有目录中增加源码或测试文件。模型不能指定 commit,也不能只凭文件清单覆盖未读文件。服务提供者更换后读上下文与待执行动作一并失效;未提供源码读取接口的旧版 control-plane 保持四工具基础模式。
149
+
150
+ Control Plane 拥有 worktree、源码快照、容器构建和 SQLite 写入。`inline` 成功时仅返回待审批 plan id 与检查摘要;`durable` 成功时只返回 content-free job id/status,Host 接受队列后继续以它自己的 durable authority 运行,即使模型 wake 随后到期也不会伪造为 prepared。`plugin_source_job_status` 只在 durable 模式出现,并用当前 Growth authority 的 owner scope 查询 job。owner 仍需通过控制面的签名审批、源码复核和发布流程处理。模型看不到 worktree 路径或构建日志。检查失败、owner route 漂移、provider 移除、插件卸载或本轮到期均终止尚未被 Host 接受的操作。`health().run.sourceProposals` 分别提供 `queued`、`prepared` / `rejected` 数量;可选 provider 更换后下一轮重新绑定,旧轮次不会跨代继续写入。
151
+
152
+ ## 真实使用自动触发
153
+
154
+ 在完整 driver 配置中加入:
155
+
156
+ ```yaml
157
+ enabled: true
158
+ intervalMs: 0
159
+ budgetId: growth-budget
160
+ budgetAmount: 1
161
+ usageLearning:
162
+ enabled: true
163
+ databasePath: /absolute/private/assistant-growth.sqlite
164
+ scanBudgetId: growth-discovery-runs
165
+ scanBudgetAmount: 1
166
+ maxPending: 16
167
+ lookbackMs: 86400000
168
+ ```
169
+
170
+ 保留前文 `scope` 和模型/工具预算;按需保留源码轨配置。安装并挂载 `assistant-evaluation` 与 `assistant-automations`,启用 Automations scheduler。Policy 需允许 background 主体 `assistant-growth-usage` 对相同 workspace/principal 的 `automation:*` 执行 `reconcile`,并允许对应后台作业的 `execute`。使用全局或 owner 聚合的周期预算限制持续成长总消耗;每个 review 由原生 Automations 预留一次预算,driver 不重复扣取。已有 `growth_*` 与可选 `plugin_source_*` 工具规则仍适用。
171
+
172
+ `scanBudgetId/scanBudgetAmount` 是启用时的必填配置;对应 Policy budget 的 metric 为 `automation-runs`,扫描建议用 `subject` scope(每个 owner scope 的 scan automation id 稳定)。每分钟扫描即使队列为空也需要预算;例如每天最多 1,440 次扫描可配置 `limit: 1440, periodMs: 86400000, scope: subject`。模型复盘继续使用顶层 `workspace/global` 聚合预算。Policy 账本按 scope、metric 和周期计量,仅换 budget id 不会分开额度;扫描用 `subject`、复盘用 `workspace/global` 可以避免扫描占用模型额度。扫描预算耗尽暂停跨进程发现,同进程通知仍可登记候选,但 review 仍须通过自己的预算;不要开启 `allowUnbudgetedExecution` 绕过配置。升级已启用配置须补齐扫描预算,旧排队作业因配置摘要变化停止,不自动重放。
173
+
174
+ 同进程 Evaluation 变化即时扫描,原生每分钟 scan 负责重启及其他进程写入的恢复;scan 自身不调用模型。只处理精确 owner、已结束且 quiescent、未截断的前台可信结果(独立 Verifier 或已认证 owner 反馈),内置 Delivery 普通对话可在回复具体消息的 `/feedback not-achieved` 后触发,无需预先配置任务验收 profile;单纯模型结束不会生成可信结果。排除 Automation/后台成长自己的结果,避免递归触发。缺模型快照或多请求模型不一致且没有固定覆盖时不发起作业。相同 canonical 修订只接纳一次;纠正/撤回使旧排队作业失效,运行中的作业在模型/工具边界重查来源。原始记录和评价仍由 Evaluation 持有。
175
+
176
+ `usageHealth()` 返回连接、扫描错误与各状态数量,不返回任务正文。queued 可在重启后恢复;running 中断转 unknown,不自动重跑。配置、owner 身份/route 或来源变化会阻止旧作业继续。停用 `usageLearning` 会卸载执行器并中止本代工作;持久作业不会被清除。它目前自动驱动有界复盘和候选生成,尚不创建任意修复 Goal;完成复盘不代表候选已采用或带来收益。
177
+
178
+ 同时启用 `pluginSourceProposals` 后,可信 `not-achieved` 前台结果会在模型启动前自动登记 Control Plane 私有 gap,无需预先人工登记。Host 重新读取 Delivery 来源,在 Evaluation writer fence 内记录 owner、任务修订和来源摘要;gap 不保存任务原文,默认 ROI 为未知占位值 0。成功、unknown、撤回、未结束及截断来源不产生失败 gap。新控制面接口缺失时失败关闭,不读取全局手工 gap。
179
+
180
+ 源码检查、最终计划提交及 durable job 的排队、恢复和执行都重新核对来源。完整 owner receipt 固定后,`/new` 导致 binding/generation 变化也会停止旧任务。纠正或撤回后保留历史引用,禁止旧来源继续产出计划。Driver 负责候选生成;后续有限审批、发布、独立审查、采用与真实任务观察由另行配置的 [Control Plane](../plugin-control-plane/README.md) 接续。组件已接线,可安装部署与独立行为验收尚未贯通,不能据此宣称生产自迭代已完成。
181
+
182
+ ## 权限与数据
183
+
184
+ - 网络:经本轮冻结的 DSH 模型 adapter 发出请求,目标及凭据由该供应配置决定;没有模型之外的网络工具。
185
+ - 文件系统:启用 `usageLearning` 后写私有 SQLite(文件权限 `0600`),保存冻结任务正文、owner 与模型,未自动清理历史。正文最多 4096 字符,经 owner 校验后作为不可信数据交给获授权的成长模型;Automations 定义与公开 health 不含正文。skill candidate 由 Skills 入库,源码提案经 Control Plane 写入其私有 worktree 和 SQLite。
186
+ - 子进程:源码轨开启时委托 Control Plane 调用 Git 与隔离容器构建;构建权属于 owner 配置的 Control Plane,见其权限说明。driver 无浏览器能力。
187
+ - 凭据:只读解析一次凭据引用(存在性检查),不持久化、不回显、不入日志。
188
+ - 审批/策略:每次沉淀与每个工具调用都在 service 边界经 `assistant-policy`;空规则默认拒绝。产物仅 pending,零 activate/install。
189
+
190
+ ## 明确不做(边界)
191
+
192
+ - 不自主发起/执行 goal、不提议 guidance、不记 capability gap。
193
+ - 不 activate / install / retire / rollback、不扩权、不改 policy 规则表、不碰预算上限与急停等安全根。
194
+ - owner-anchored 轨只提交 locator:证据(objective、步骤、验收结论)一律由 Delivery 持 goals 独立重取,driver 不接受调用方自带 prompt,也不自造 trace source/authority。
195
+ - 源码轨只到经过检查的 pending 提案;owner 签名、发布、生产启用和 HMR reload 由独立控制面处理。
196
+ - owner-anchored 轨的证据是 Delivery 在进程内对真实 goals SQLite 的独立复核(工程层);真实 super-relay 端到端与真实外部平台深评测均不在本期,前者仅由 owner 显式 opt-in 后手动触发一次。
197
+
198
+ ## 兼容性
199
+
200
+ See the repository [compatibility baseline](../../docs/compatibility.md)。
@@ -0,0 +1,3 @@
1
+ - insert:
2
+ - id: dsh-enhanced-assistant-growth-driver
3
+ name: '@dsh-enhanced/assistant-growth-driver'
@@ -0,0 +1,122 @@
1
+ import Schema from '@deepseek-ai/schemastery';
2
+ /**
3
+ * The growth driver is opt-in and fail-closed: it never runs until `enabled`
4
+ * is explicitly true and a concrete owner scope is declared. Model selection
5
+ * follows the owner's conversation unless an explicit fixed pair overrides it.
6
+ */
7
+ export declare const DEFAULT_API_KEY_ENV: "SUPER_RELAY_API_KEY";
8
+ export interface GrowthOwnerScopeConfig {
9
+ workspace: string;
10
+ preset: string;
11
+ principalId: string;
12
+ ownerRouteId: string;
13
+ }
14
+ /**
15
+ * The owner-anchored workflow bridge is a second, independently switched
16
+ * learning track inside the wake. It is opt-in and fail-closed even when the
17
+ * driver itself is enabled: it never proposes, approves, activates or installs
18
+ * anything, it only asks Delivery to re-verify and record paused candidates.
19
+ */
20
+ export interface WorkflowOwnerAnchoredConfig {
21
+ enabled?: boolean;
22
+ /** Hard cap on commit attempts in one wake (rate limit); idempotent replays are cheap. */
23
+ maxCommitsPerWake?: number;
24
+ /** Only consider owner goals last updated inside this lookback horizon (TTL). */
25
+ lookbackMs?: number;
26
+ }
27
+ /**
28
+ * The plugin source-proposal track is the third, independently switched growth
29
+ * capability. It is opt-in and fail-closed even when the driver itself is
30
+ * enabled: the growth agent may then prepare PENDING modify source plans in
31
+ * isolated worktrees, but it can never approve, sign, release, activate,
32
+ * install or reload anything. Every build-shaping value (repository path,
33
+ * timeouts, TTL, offline flag) is frozen owner configuration — the model can
34
+ * never supply a repository, worktree, base commit or environment.
35
+ */
36
+ export interface PluginSourceProposalsConfig {
37
+ enabled?: boolean;
38
+ /** Inline builds during the model wake; durable queues Host-owned work. */
39
+ preparationMode?: 'inline' | 'durable';
40
+ /** Canonical absolute path of the dsh-enhanced repository the patches target. Required when enabled. */
41
+ repository?: string;
42
+ /** Hard cap on prepared modify plans in one wake (rate limit); idempotent replays are cheap. */
43
+ maxPlansPerWake?: number;
44
+ /** Per-command bounded timeout for the frozen install/check/pack gate. */
45
+ isolatedBuildTimeoutMs?: number;
46
+ /** Run pnpm install fully offline (the owner must warm the store beforehand). */
47
+ offline?: boolean;
48
+ /** Pending-plan TTL: how long the isolated worktree waits for owner action. */
49
+ planTtlMs?: number;
50
+ }
51
+ export interface AssistantGrowthDriverConfig {
52
+ enabled?: boolean;
53
+ /** 0 = no periodic wake; the driver only runs when explicitly triggered. */
54
+ intervalMs?: number;
55
+ maxReviewsPerWake?: number;
56
+ minRepeatedSuccesses?: number;
57
+ candidateTtlMs?: number;
58
+ maxModelCalls?: number;
59
+ maxToolCalls?: number;
60
+ maxOutputTokens?: number;
61
+ maxDurationMs?: number;
62
+ /** Omit both to inherit the owner conversation; specify both for a fixed route. */
63
+ provider?: string;
64
+ model?: string;
65
+ /** Optional effort for an explicitly configured fixed route. */
66
+ reasoningEffort?: string;
67
+ /** Optional policy budget id; when unset no budget reservation is made. */
68
+ budgetId?: string;
69
+ /** Reserved amount in the owner-configured budget metric; required when budgetId is set. */
70
+ budgetAmount?: number;
71
+ /** Credential reference only; never a literal API key. */
72
+ apiKeyEnv?: string;
73
+ scope?: GrowthOwnerScopeConfig;
74
+ workflowOwnerAnchored?: WorkflowOwnerAnchoredConfig;
75
+ pluginSourceProposals?: PluginSourceProposalsConfig;
76
+ /** One-time opt-in to durable reviews driven by actual trusted foreground results. */
77
+ usageLearning?: {
78
+ enabled?: boolean;
79
+ databasePath?: string;
80
+ maxPending?: number;
81
+ lookbackMs?: number;
82
+ /** Native discovery scans need their own explicit automation-runs allocation. */
83
+ scanBudgetId?: string;
84
+ scanBudgetAmount?: number;
85
+ };
86
+ }
87
+ export interface NormalizedWorkflowOwnerAnchoredConfig {
88
+ readonly enabled: boolean;
89
+ readonly maxCommitsPerWake: number;
90
+ readonly lookbackMs: number;
91
+ }
92
+ export interface NormalizedPluginSourceProposalsConfig {
93
+ readonly enabled: boolean;
94
+ readonly preparationMode: 'inline' | 'durable';
95
+ readonly repository: string | null;
96
+ readonly maxPlansPerWake: number;
97
+ readonly isolatedBuildTimeoutMs: number;
98
+ readonly offline: boolean;
99
+ readonly planTtlMs: number;
100
+ }
101
+ export interface NormalizedGrowthDriverConfig extends Required<Omit<AssistantGrowthDriverConfig, 'provider' | 'model' | 'reasoningEffort' | 'apiKeyEnv' | 'budgetId' | 'budgetAmount' | 'scope' | 'workflowOwnerAnchored' | 'pluginSourceProposals' | 'usageLearning'>> {
102
+ readonly provider: string | null;
103
+ readonly model: string | null;
104
+ readonly reasoningEffort: string | null;
105
+ readonly apiKeyEnv: string | null;
106
+ readonly budgetId: string | null;
107
+ readonly budgetAmount: number | null;
108
+ readonly scope: GrowthOwnerScopeConfig | null;
109
+ readonly workflowOwnerAnchored: NormalizedWorkflowOwnerAnchoredConfig;
110
+ readonly pluginSourceProposals: NormalizedPluginSourceProposalsConfig;
111
+ readonly usageLearning: Readonly<{
112
+ enabled: boolean;
113
+ databasePath: string | null;
114
+ maxPending: number;
115
+ lookbackMs: number;
116
+ scanBudgetId: string | null;
117
+ scanBudgetAmount: number | null;
118
+ }>;
119
+ }
120
+ export declare const Config: Schema<AssistantGrowthDriverConfig>;
121
+ export declare function normalizeConfig(input?: AssistantGrowthDriverConfig): Readonly<NormalizedGrowthDriverConfig>;
122
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/lib/config.js ADDED
@@ -0,0 +1,207 @@
1
+ import { isAbsolute, resolve } from 'node:path';
2
+ import Schema from '@deepseek-ai/schemastery';
3
+ /**
4
+ * The growth driver is opt-in and fail-closed: it never runs until `enabled`
5
+ * is explicitly true and a concrete owner scope is declared. Model selection
6
+ * follows the owner's conversation unless an explicit fixed pair overrides it.
7
+ */
8
+ export const DEFAULT_API_KEY_ENV = 'SUPER_RELAY_API_KEY';
9
+ const fields = new Set([
10
+ 'enabled',
11
+ 'intervalMs',
12
+ 'maxReviewsPerWake',
13
+ 'minRepeatedSuccesses',
14
+ 'candidateTtlMs',
15
+ 'maxModelCalls',
16
+ 'maxToolCalls',
17
+ 'maxOutputTokens',
18
+ 'maxDurationMs',
19
+ 'provider',
20
+ 'model',
21
+ 'reasoningEffort',
22
+ 'budgetId',
23
+ 'budgetAmount',
24
+ 'apiKeyEnv',
25
+ 'scope',
26
+ 'workflowOwnerAnchored',
27
+ 'pluginSourceProposals',
28
+ 'usageLearning',
29
+ ]);
30
+ const ref = Schema.string().pattern(/^[A-Z_][A-Z0-9_]*$/u);
31
+ const boundedText = (max) => Schema.string().min(1).max(max);
32
+ // schemastery gives every object schema a default of {}, which would otherwise
33
+ // deep-validate a missing scope against the required inner fields. Pin the
34
+ // default to undefined so an undeclared scope stays absent (fail-closed config
35
+ // validation happens explicitly in normalizeConfig). The cast bridges the
36
+ // library typings, whose default() parameter excludes undefined even though the
37
+ // runtime stores and returns it verbatim.
38
+ const scopeSchema = Schema.object({
39
+ workspace: boundedText(4_096).required(),
40
+ preset: boundedText(256).required(),
41
+ principalId: boundedText(256).required(),
42
+ ownerRouteId: boundedText(256).required(),
43
+ }).default(undefined);
44
+ // Same missing-object default rationale as scopeSchema above. The inner fields
45
+ // are optional in WorkflowOwnerAnchoredConfig (they all carry schema defaults),
46
+ // so cast the object schema to that optional-input type before pinning its
47
+ // missing-object default to undefined.
48
+ const workflowOwnerAnchoredObjectSchema = Schema.object({
49
+ enabled: Schema.boolean().default(false),
50
+ maxCommitsPerWake: Schema.natural().min(1).max(50).default(5),
51
+ lookbackMs: Schema.natural().min(60_000).max(604_800_000).default(86_400_000),
52
+ });
53
+ const workflowOwnerAnchoredSchema = workflowOwnerAnchoredObjectSchema
54
+ .default(undefined);
55
+ // Same missing-object default rationale as workflowOwnerAnchoredSchema above.
56
+ const pluginSourceProposalsObjectSchema = Schema.object({
57
+ enabled: Schema.boolean().default(false),
58
+ preparationMode: Schema.union(['inline', 'durable']).default('inline'),
59
+ repository: boundedText(4_096),
60
+ maxPlansPerWake: Schema.natural().min(1).max(5).default(1),
61
+ // Security root: the isolated build gate must finish well inside the 300000 ms
62
+ // growth authority lifetime; bounds mirror the control-plane service limits.
63
+ isolatedBuildTimeoutMs: Schema.natural().min(60_000).max(240_000).default(180_000),
64
+ offline: Schema.boolean().default(true),
65
+ planTtlMs: Schema.natural().min(900_000).max(86_400_000).default(86_400_000),
66
+ });
67
+ const pluginSourceProposalsSchema = pluginSourceProposalsObjectSchema
68
+ .default(undefined);
69
+ const schema = Schema.object({
70
+ enabled: Schema.boolean().default(false),
71
+ intervalMs: Schema.natural().min(0).max(86_400_000).default(0),
72
+ maxReviewsPerWake: Schema.natural().min(1).max(50).default(10),
73
+ minRepeatedSuccesses: Schema.natural().min(1).max(32).default(3),
74
+ // Store-imposed ceiling: candidates expire at most 7 days after staging.
75
+ candidateTtlMs: Schema.natural().min(1_000).max(604_800_000).default(86_400_000),
76
+ maxModelCalls: Schema.natural().min(1).max(64).default(8),
77
+ maxToolCalls: Schema.natural().min(0).max(128).default(24),
78
+ maxOutputTokens: Schema.natural().min(1).max(32_768).default(8_192),
79
+ // Security root: a growth authority may never live longer than 300000 ms.
80
+ maxDurationMs: Schema.natural().min(1_000).max(300_000).default(120_000),
81
+ provider: boundedText(256),
82
+ model: boundedText(256),
83
+ reasoningEffort: boundedText(128),
84
+ budgetId: Schema.string().min(1).max(128),
85
+ budgetAmount: Schema.natural().min(1).max(1_000_000_000),
86
+ apiKeyEnv: ref,
87
+ scope: scopeSchema,
88
+ workflowOwnerAnchored: workflowOwnerAnchoredSchema,
89
+ pluginSourceProposals: pluginSourceProposalsSchema,
90
+ usageLearning: Schema.object({ enabled: Schema.boolean().default(false), databasePath: boundedText(4096),
91
+ scanBudgetId: boundedText(128),
92
+ scanBudgetAmount: Schema.natural().min(1).max(10_000_000),
93
+ maxPending: Schema.natural().min(1).max(100).default(16),
94
+ lookbackMs: Schema.natural().min(60_000).max(604_800_000).default(86_400_000),
95
+ }).default(undefined),
96
+ });
97
+ export const Config = new Proxy(schema, {
98
+ apply(target, thisArg, argumentsList) {
99
+ const value = argumentsList[0];
100
+ if (value !== undefined && (value === null || typeof value !== 'object' || Array.isArray(value)))
101
+ throw new Error('assistant-growth-driver: config must be an object');
102
+ if (value !== undefined)
103
+ for (const key of Object.keys(value))
104
+ if (!fields.has(key))
105
+ throw new Error(`assistant-growth-driver: unknown config field: ${key}`);
106
+ return Reflect.apply(target, thisArg, argumentsList);
107
+ },
108
+ });
109
+ export function normalizeConfig(input) {
110
+ const config = Config(input);
111
+ if (config.apiKeyEnv !== undefined && !/^[A-Z_][A-Z0-9_]*$/u.test(config.apiKeyEnv))
112
+ throw new Error('assistant-growth-driver: invalid apiKeyEnv');
113
+ const normalized = Object.freeze({
114
+ enabled: config.enabled ?? false,
115
+ intervalMs: config.intervalMs ?? 0,
116
+ maxReviewsPerWake: config.maxReviewsPerWake ?? 10,
117
+ minRepeatedSuccesses: config.minRepeatedSuccesses ?? 3,
118
+ candidateTtlMs: config.candidateTtlMs ?? 86_400_000,
119
+ maxModelCalls: config.maxModelCalls ?? 8,
120
+ maxToolCalls: config.maxToolCalls ?? 24,
121
+ maxOutputTokens: config.maxOutputTokens ?? 8_192,
122
+ maxDurationMs: config.maxDurationMs ?? 120_000,
123
+ provider: config.provider ?? null,
124
+ model: config.model ?? null,
125
+ reasoningEffort: config.reasoningEffort ?? null,
126
+ budgetId: config.budgetId ?? null,
127
+ budgetAmount: config.budgetAmount ?? null,
128
+ apiKeyEnv: config.apiKeyEnv ?? null,
129
+ scope: config.scope ? Object.freeze({ ...config.scope }) : null,
130
+ workflowOwnerAnchored: Object.freeze({
131
+ enabled: config.workflowOwnerAnchored?.enabled ?? false,
132
+ maxCommitsPerWake: config.workflowOwnerAnchored?.maxCommitsPerWake ?? 5,
133
+ lookbackMs: config.workflowOwnerAnchored?.lookbackMs ?? 86_400_000,
134
+ }),
135
+ pluginSourceProposals: Object.freeze({
136
+ enabled: config.pluginSourceProposals?.enabled ?? false,
137
+ preparationMode: config.pluginSourceProposals?.preparationMode ?? 'inline',
138
+ repository: config.pluginSourceProposals?.repository?.normalize('NFC').trim() ?? null,
139
+ maxPlansPerWake: config.pluginSourceProposals?.maxPlansPerWake ?? 1,
140
+ isolatedBuildTimeoutMs: config.pluginSourceProposals?.isolatedBuildTimeoutMs ?? 180_000,
141
+ offline: config.pluginSourceProposals?.offline ?? true,
142
+ planTtlMs: config.pluginSourceProposals?.planTtlMs ?? 86_400_000,
143
+ }),
144
+ usageLearning: Object.freeze({ enabled: config.usageLearning?.enabled ?? false,
145
+ scanBudgetId: config.usageLearning?.scanBudgetId ?? null,
146
+ scanBudgetAmount: config.usageLearning?.scanBudgetAmount ?? null,
147
+ databasePath: config.usageLearning?.databasePath ?? null, maxPending: config.usageLearning?.maxPending ?? 16,
148
+ lookbackMs: config.usageLearning?.lookbackMs ?? 86_400_000 }),
149
+ });
150
+ if (normalized.enabled && !normalized.scope)
151
+ throw new Error('assistant-growth-driver: enabled requires an explicit owner scope');
152
+ if ((normalized.provider === null) !== (normalized.model === null)) {
153
+ throw new Error('assistant-growth-driver: provider and model must be configured together');
154
+ }
155
+ if (normalized.reasoningEffort !== null && normalized.provider === null) {
156
+ throw new Error('assistant-growth-driver: reasoningEffort requires an explicit provider and model');
157
+ }
158
+ for (const value of [normalized.provider, normalized.model, normalized.reasoningEffort]) {
159
+ if (value !== null && (value.trim() !== value || value.length === 0 || [...value].some(character => {
160
+ const code = character.codePointAt(0);
161
+ return code <= 31 || code === 127;
162
+ }))) {
163
+ throw new Error('assistant-growth-driver: invalid model route');
164
+ }
165
+ }
166
+ if (normalized.workflowOwnerAnchored.enabled && !normalized.enabled) {
167
+ throw new Error('assistant-growth-driver: workflowOwnerAnchored.enabled requires the driver itself to be enabled');
168
+ }
169
+ if (normalized.workflowOwnerAnchored.enabled && !normalized.scope) {
170
+ throw new Error('assistant-growth-driver: workflowOwnerAnchored.enabled requires an explicit owner scope');
171
+ }
172
+ if (normalized.pluginSourceProposals.enabled) {
173
+ if (!normalized.enabled) {
174
+ throw new Error('assistant-growth-driver: pluginSourceProposals.enabled requires the driver itself to be enabled');
175
+ }
176
+ if (!normalized.scope) {
177
+ throw new Error('assistant-growth-driver: pluginSourceProposals.enabled requires an explicit owner scope');
178
+ }
179
+ if (!normalized.pluginSourceProposals.offline)
180
+ throw new Error('assistant-growth-driver: source preparation requires offline mode');
181
+ const repository = normalized.pluginSourceProposals.repository;
182
+ // Canonical TEXT only here (the control-plane service performs the realpath
183
+ // canonicalization against the live filesystem at prepare time): absolute,
184
+ // non-empty and free of '.'/'..' normalization segments.
185
+ if (repository === null || !isAbsolute(repository) || resolve(repository) !== repository) {
186
+ throw new Error('assistant-growth-driver: pluginSourceProposals.repository must be a canonical absolute path when enabled');
187
+ }
188
+ }
189
+ if ((normalized.budgetId === null) !== (normalized.budgetAmount === null)) {
190
+ throw new Error('assistant-growth-driver: budgetId and budgetAmount must be configured together');
191
+ }
192
+ if (normalized.usageLearning.enabled) {
193
+ const path = normalized.usageLearning.databasePath;
194
+ if (!normalized.enabled || !normalized.scope || !normalized.budgetId || normalized.intervalMs !== 0
195
+ || path === null || !isAbsolute(path) || resolve(path) !== path) {
196
+ throw new Error('assistant-growth-driver: usageLearning requires enabled owner scope, budget, absolute databasePath and intervalMs=0');
197
+ }
198
+ const scanBudget = normalized.usageLearning.scanBudgetId;
199
+ if (scanBudget === null || scanBudget.trim() !== scanBudget || scanBudget.length === 0
200
+ || scanBudget.normalize('NFC') !== scanBudget || /[\p{Cc}]/u.test(scanBudget)
201
+ || normalized.usageLearning.scanBudgetAmount === null) {
202
+ throw new Error('assistant-growth-driver: usageLearning requires scanBudgetId and scanBudgetAmount for native discovery');
203
+ }
204
+ }
205
+ return normalized;
206
+ }
207
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}