技能驱动的 harness/loop 工程化工作流插件。
安装
# npm 包(预构建)
dsh plugin --profile web add @mstar-harness/dsh
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:btspoony/mstar-harness#path:/packages/dsh
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
让 Morning Star 成为一等公民的 dsh(DeepSeek Harness)宿主——一个 cordis 函数插件,将 mstar engine 进程内挂载,实现 engine HostAdapter(host: 'dsh'),守护 {HARNESS_DIR}/status.json 写入(校验 + 咨询;hard 下按修复逃生放行),在 Enforcement: hard 开启时阻止被禁止的 subagent 派发,对挂载技能根下的 SKILL.md 写入执行技能撰写 lint,通过 dsh skill-filesystem 提供者挂载 mstar skills/ 镜像(单一规范挂载),并向每个组合后的 agent 步骤追加一条持久化的 mstar-engine-status catalog 行。随 dsh Loader 应用启动;一切均通过 seam 的拒绝/咨询通道行使职责,从不改动工具本身。
Usage
dsh 应用如何使用本插件——安装路径、配置、挂载时发生什么、强制执行语义。
Install paths
本包以 workspace 包形式发布(workspaces: ["packages/*"]),构建时把 engine 打进 dist/(bun run build;dist 已被 gitignore)。安装途径是 profile bundle,装进现成的 web profile(dsh --profile web——开箱即用的 web 应用 profile,即 dsh web),经 dsh.bundle.patch 清单——一个叠在 dsh-base 默认层之上的补丁层:
一条命令的 CLI 入口(推荐)——npx @mstar-harness/cli init --target dsh 一次性装齐全量能力:它按序运行下面两条 dsh plugin --profile web add 安装(先 mstar bundle,再 dsh-llm-fallbacks),并可用 npx @mstar-harness/cli doctor --target dsh 逐行报告 uninstalled / disabled / mounted。它编排的仍是同一条双命令安装;--no-fallbacks 跳过第二行(连带跳过 seeded 角色——见下文「零配置获得什么」)。
(a)registry 安装(发布形态)——npm 包自带构建好的 dist/(安装时无需构建):
dsh plugin --profile web add @mstar-harness/dsh
(b)local checkout 安装(开发)——包检出本身,用于迭代插件:
cd <repo>/packages/dsh
dsh plugin --profile web add .
dsh plugin --profile <name> add <spec> 首次使用时初始化 profile(web 从出厂模板起步:@deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app),把 <spec> 转发给 profile 目录中的 pnpm,并按已安装状态对账 dsh.profile.bundles 层列表:任何 package.json 声明 dsh.bundle 的依赖都会加入层栈。相对 spec(.、file:/link:)锚定调用目录,因此 add . 须在包检出目录内执行;pnpm 须在 PATH 上。local checkout 需要先执行过 bun run build(本包不使用 prepare 脚本——monorepo 与 cli/opencode 一致,显式构建各包)。细节、层位置与出厂默认见 bundle/README.md——registry 与 local checkout 形态均走同一 pnpm + reconcile 机制。cordis 与 @deepseek-ai/dsh-* 各 seam 均为 peerDependencies——由组合后的 dsh 应用提供。
(c)可选能力:dsh-llm-fallbacks(第二条命令)——基于角色的 subagent 配置能力(见 LLM fallbacks integration)是独立的插件行,须以单独命令安装:
dsh plugin --profile web add dsh-llm-fallbacks
双命令安装即契约——把 dsh-llm-fallbacks 行折叠进本 bundle 的补丁明确否决(roadmap §8.3 F4):loader 没有 insert-if-absent 语义,因此同 id 插入是 duplicate loader entry id 启动失败(整个 dsh 会话无法启动);异 id 插入则插件被挂载两次——对同时直接安装该包的人,会出现两次 apply() 与分裂的 fallback 状态(各自独立的 state store、双份监听器、配置覆盖抽签)。层序为 reconcile 追加序:dsh-llm-fallbacks 落在 dsh-base/llm-retry 之后(其硬性排序要求)并位于 mstar 行之后。单命令多激活是上游功能缺口(reconcile 去重或 insert-if-absent 补丁语义),本仓库无法实施。
零配置获得什么——两条行都装上后(经 CLI 入口或上面两条命令),mstar 插件在 boot 时把 13 个 mode: subagent 的 mstar 角色种子(从打包的 harness-agents/ 镜像派生,排除 project-manager)声明进 fallbacks taxonomy:每个 seeded 角色的 persona 默认取其镜像 description 外加一行强制角色加载引导;seeded 状态保持可 revert(fallbacks/revert-seed 网关 / settings 回滚按钮);运行时 advisory 报告缺失 id 与 persona 覆盖。该 seeds 机制即 B4(iter-20260816-dsh-seeds-bridges 已交付)——installed-deployment e2e(tests/install-e2e.spec.ts)本轮把验证闭环:真实 init --target dsh 安装进临时 DSH_HOME、从安装产物 boot,断言 13 个 id 全部出现在 effective taxonomy 且 persona 非空。不含模型路由、不含 automatch 派发、不含 dsh-tui。
fresh publish 年龄窗口提示:pnpm 的
minimumReleaseAge门禁可能让dsh plugin add <spec>的 range 解析在全新发布后约 24h 内选中旧版本(不含 seeds surface)——窗口过后重跑npx @mstar-harness/cli init --target dsh(或显式 pin 版本)即可收敛到最新 surface。
Configuration
| Key | Type | Default | Meaning |
|---|---|---|---|
harnessDir |
string |
按会话工作区探测(.mstar/ → .agents/ → .plans/ → plans/,从会话工作区根目录开始——绝不从启动 cwd) |
显式 harness 根目录;优先于 engine 探测。harness 根不在探测名列表中的仓库必须配置——例如本 mstar-workflow 仓库自身用 .harness/(维护根,刻意不探测);探测从会话工作区根开始(绝不从启动 cwd)并在那里停止——永不越过会话工作区向上,因此其上方的 harness 目录(如全局 ~/.mstar)永远不会被采纳。 |
enforcement |
'hard' | 'soft' |
compass,否则仅告警 | 按部署覆盖。优先级:Config 优先;否则取 Assignment 自身的 **Enforcement**: hard 头字段(仅派发闸门);否则取迭代 compass frontmatter;否则仅告警。Config soft 是唯一的本地回滚——Assignment 级 soft 不能覆盖 hard compass。 |
dispatchTools |
string[] |
['subagent', 'subagent_fork'] |
派发闸门匹配的委派工具名——dsh preset 的两个委派工具:subagent 及其 fork 兄弟 subagent_fork(两者都携带 Assignment 形态的 { description, prompt } 参数;toolName 配置可重命名实例)。 |
dispatchBinding |
string |
未设置(跳过预检) | 派发方 agent 自身的 harness 角色;Assignment 的 Execute as 等于它即自我递归。 |
roleMap |
Record<string, string> |
未设置 | mstar 角色 id(Execute as)→ dsh-llm-fallbacks 角色 id。仅作日志与未来规则驱动互操作的分类桥——装饰从不读取它(见 LLM fallbacks integration)。 |
rolePersonas |
Record<string, string> |
未设置(打包镜像默认) | mstar 角色 id(Execute as)→ persona 文本;基于角色的 subagent 装饰的覆盖来源——角色匹配的 subagent/start 会把 persona 注册为子会话的 mstar:role-persona system-prompt 段;某角色未设置时使用打包的 harness-agents/ 镜像默认值(见 LLM fallbacks integration)。 |
skillRoots |
string[] |
未设置(不注册自定义根) | 向 dsh skill-filesystem 提供者注册的额外技能根(customSkillDirs 语义——先于用户根扫描)。开发期:镜像 <repo-root>/skills 的绝对路径。 |
bundledSkillDir |
string |
打包的 harness-skills/ 镜像(包相对路径) |
向 dsh skill-filesystem 提供者注册的打包技能根(bundledSkillDir 语义——最后扫描、受信任)。默认取包内自带的 harness-skills/ 镜像(bundle-assets 同步;gitignore)——包相对路径,非 cwd 锚定。显式值优先。 |
catalogTtlMs |
number |
60000 |
pre-step catalog 缓存刷新间隔(毫秒):按工作区缓存的统一 mstar-engine-status 行(水印 + 迭代闸门 + 工作区摘要)多久重读一次 status.json / compass / 知识索引。刷新间隔之间热路径只是时间戳比较 + Map 命中;会话中 plan/compass/residual 的变化会在一个间隔内落地。 |
workflowGate |
'off' | 'warn' | 'ask' | 'hard' |
'warn' |
workflow/ralph 闸门模式(见 Gates → Workflow / ralph gate)。off = 直通且不产生 verdict 行;warn = 仅咨询;ask = 首见名字走审批瀑布(P-c);hard = 策略违规在任何子进程启动前否决。默认 warn 不改任何 hard 行为——除非部署显式选入 ask/hard,闸门仅咨询。 |
workflowNames |
string[] |
未设置 | workflow 名字白名单(P-a):被闸门视为 KNOWN 的 meta.name 值。为空或缺省 ⇒ 每个名字都 unknown(有文档——闸门绝不因缺省而"全放行")。ralph 调用不携带 meta.name——P-a 对其永不适用。 |
bundledSkillDir 默认取包内自带的 harness-skills/ 镜像(见 Skills mount)——显式 Config 值仍然优先。相对覆盖仍是 cwd 锚定(skill-filesystem 以 join() 语义相对 dsh 进程 cwd 解析),因此覆盖默认的部署应在 profile 层传绝对路径(见 bundle/README.md)。
组合后的行集合
profile bundle 组合出以下行——注册表行来自 @deepseek-ai/dsh-base 层,本 bundle 的补丁在其上插入 mstar 行并携带中性默认(即全应用 e2e fixture 启动的行集合):
- name: '@deepseek-ai/dsh-skill' # skill 注册表(ctx.skills)——dsh-base 行
- name: '@deepseek-ai/dsh-tools' # tool 注册表(ctx.tools)——dsh-base 行
- name: '@deepseek-ai/dsh-commands' # command 注册表(ctx.commands)——dsh-base 行
- name: '@mstar-harness/dsh' # 本 bundle 补丁插入(config: {}——插件默认生效)
注册表行先于插件挂载,使 mstar 各闸门、seam 工具与 bundled 命令注册时 ctx.skills / ctx.tools / ctx.commands 已存在。
What the plugin does when mounted
- 状态闸门——
fs/write-intent+fs/edit-intent监听器校验{HARNESS_DIR}/status.json写入(对写入前文档运行 enginevalidateStatus+ 按 plan 的findingsCleanupGate)。 - 派发闸门——
tools/pre-execute监听器作用于委派工具,通过 engine 的单一composeDispatchGate组合(字段闸门、反递归预检、默认分支闸门——与 opencode/omp/CLI 对齐,违规码按构造即相同)校验 subagent Assignment 文本,外加 dsh 租约闸门与 worktree L1/L2 检查。 - 技能撰写 lint——已配置技能根下的
SKILL.md写入运行 engine 技能撰写 lint(lintFrontmatter+lintFiveQuestion)。 - seam lint——harness 下
DESIGN.md/ audit plan / 知识文档 / roles 目录的写入运行各自的 artifact 级 engine lint。 - 模型可见工具——
mstar_sdd_workspace、mstar_sdd_task_brief、mstar_iteration_gate、mstar_design_md_validate、mstar_audit_validate、mstar_compound_validate、mstar_roles_validate注册到ctx.tools。 - bundled 命令——向
ctx.commands注册/iteration-start、/iteration-drive、/iteration-loop、/codebase-audit(来自打包的harness-commands/镜像;每条声明 frontmatterinputhint,使 web 客户端 claim/name并等待用户后续输入而非立即执行;handler 把命令正文 + 用户输入 steer 进接收 agent)。 - pre-step catalog 行——每个组合后的 agent 步骤都会追加一条统一的
mstar-engine-statuscatalog 消息:水印(统一 mstar 版本、harness 目录、enforcement)、迭代相位闸门段(解析到 steering compass 时)与工作区状态摘要段(工作区有status.json时:plan 注册表、open residual、分支/政策锚点、活跃 lease、知识摘要、compass 方向)。该行是 digest 门控的(每 turn 注入一次、变化时才重发),并共享一次按工作区 TTL 缓存的构建(catalogTtlMs,默认 60 秒)。
Enforcement semantics
默认仅告警:闸门违规记录日志并发出咨询事件(mstar/status-gate、mstar/dispatch-gate、mstar/skill-lint 及各 seam 咨询),动作照常继续。Enforcement: hard——来自迭代 compass frontmatter、Assignment 头字段或插件 Config(enforcement: hard)——把违规升级为经 cordis 拒绝通道的真实否决/拒绝:subagent 派发在不调用 next() 的情况下返回 PreToolDecision { kind: 'deny', reason };状态/技能 lint 写入因 intent 瀑布链内容盲而从不硬否决——对已非法的文档按修复逃生放行(hard: true, repair: true 咨询),让修复性写入能落地。Config soft 是唯一的本地回滚;hard 闸门绝非全局默认。
Gates
Status gate
fs/write-intent + fs/edit-intent 监听器(以 prepend 注册,确保先于 dsh-fs-policy 执行)对 {HARNESS_DIR}/status.json 的写入把关:基于当前磁盘文档运行 validateStatus + 按 plan 的 findingsCleanupGate(文档只解析一次——无 TOCTOU 双重读取)。闸门从不抛出:每次决策都以 mstar/status-gate 咨询事件呈现,并通过 next() 委托 intent 瀑布链。告警模式(默认)在有违规时记录日志并发出事件。hard 模式对已非法的文档按**修复逃生(repair escape)**放行(error 级日志 + hard: true, repair: true 咨询)——intent 瀑布链不携带写入内容,若对非法文档硬否决,反而会卡死修复性写入本身。意外内部错误在两种模式下都降级为放行并发出 degraded: true 咨询(错误隔离包络);首次破坏文档的写入本身无法在此 seam 上被否决(见 Known Limitations)。
Dispatch gate
tools/pre-execute 监听器作用于委派工具:解析载荷中的 Assignment 文本,在头区域上运行 engine 的单一派发闸门组合(composeDispatchGate——形状守卫、validateAssignmentFields、antiRecursionPrecheck、默认分支闸门、头区域强制执行;opencode/omp/CLI 绑定使用同一组合,违规码按构造即相同),外加 dsh 侧 worktree L1/L2 检查与租约闸门。拒绝通道为不调用 next() 而返回 PreToolDecision { kind: 'deny', reason };告警模式记录日志、发出 mstar/dispatch-gate 并委托。非 Assignment 提示与非委派工具保持惰性。两种模式下 engine 故障都降级为放行,且降级可观测:catch 路径发出 degraded: true 的插件自有咨询 + error 日志,使 hard 部署能察觉控制失效而非静默放行。以 prepend 注册,防止更早挂载的决策监听器把本闸门短路在不可达处。
Lease gate
在 opencode 字段集之上新增:对声明 Execution mode: sdd 或 plan 行为 InProgress 的可写派发,对照 {HARNESS_DIR}/status.json 运行 verifyPlanExecutionLease 与派发上下文比对(holder、worktree_path、working_branch)。违规使用 dsh 侧 lease.dispatch.* 命名空间;只读角色完全跳过该检查。缺失 status.json 对 sdd 派发不再是静默放行:发出 lease.dispatch.unverifiable(告警模式下为 advisory,hard 下为 deny)——没有状态文件就无法确认 execution_lease。非 SDD 派发保持降级放行(无租约义务)。所有 Assignment 字段读取都限定在 engine assignmentHeaderRegion 内(正文中引用的示例不会泄漏进头字段)。
Skill lint gate
作用于已配置技能根下 SKILL.md 文件的 fs/write-intent 监听器,对写入前的磁盘文档运行 engine 技能撰写 lint(lintFrontmatter + lintFiveQuestion——与 CLI mstar skill lint 组合一致)。该槽位内容盲(intent 瀑布链只携带 (target, actor)):文件缺失 = 首次创建 = 放行;磁盘文档干净 = 静默放行;告警模式下有违规 = 咨询 + 委托;hard 模式下有违规 = 修复逃生——文档已经非法,本次写入可能就是修复本身(error 级日志 + hard: true, repair: true 咨询,携带强制执行后的 hardBlocked 判定)。强制执行解析方式与其他闸门相同(Config 覆盖优先,否则取迭代 compass,否则仅告警)。闸门从不抛出;读取失败与意外错误降级为放行并发出 degraded: true 咨询。类型化 hard 否决(SkillLintVetoError,码 skill-lint.veto)位于传入文档分支(lintSkillWrite)——当前接线见 Known Limitations。
Workflow / ralph gate
tools/pre-execute 的一个分支(位于 subagent prompt 分支之前)把关 workflow 与 ralph 工具调用——这是剩余的不携带 Assignment 文本、模型可达的扇出路径。它匹配固定工具名(workflow / ralph);重命名后的 workflow 实例不在范围(名字守卫是固定默认)。非 workflow 工具不受影响——subagent 分支照旧拥有它们,语义不变。
四级模式(Config workflowGate,默认 warn):off(直通,无 verdict 行)、warn(仅咨询)、ask(首见名字走 dsh 审批瀑布——{kind:'ask'},上游 fail-closed;本闸门不自造应答器)、hard(策略违规在任何子进程启动前否决)。策略是单一决策点——P-b 租约归属最先运行并抢占 P-a/P-c,然后才是 P-a 名字白名单,最后 P-c 首见 ask。
| 策略 | off |
warn(默认) |
ask |
hard |
|---|---|---|---|---|
P-b:调用工作区存在 InProgress 且无 execution_lease 覆盖的 plan |
allow(闸门短路 off) |
warn——放行 + 咨询(workflow.lease.uncovered)+ 一条 warn |
warn——放行 + 咨询 + 一条 warn(ask 通道只服务首见名字,绝不替代工作区红线) | deny——在任何子进程启动前否决(workflow.lease.uncovered),reason 引用 plan id |
P-a:workflow 名字 ∈ workflowNames(非空列表) |
allow(短路) | allow——无咨询(P-a 在任何模式下都放行) | allow——无 ask | allow |
| P-a:workflow 名字 unknown(空/缺省列表 ⇒ 每个名字都 unknown) | allow(短路) | warn——放行 + 咨询(workflow.name.unknown)+ 一条 warn |
ask(首见)→ {kind:'ask'};之后复用缓存决策(allow/deny)——已解析名字绝不再 ask |
deny——在任何子进程启动前否决(workflow.name.unknown),reason 点名该名字 |
ralph(无 meta.name——无白名单身份) |
allow(短路) | allow——P-a/P-c 永不适用 | allow——P-a/P-c 永不适用 | allow——P-a/P-c 永不适用;P-b 仍适用(uncovered 时 deny) |
默认 warn 的理由。 默认 warn 使闸门绝不让部署意外吃硬阻断:除非操作者显式选入 ask(人工 ask 通道)或 hard(否决),闸门仅咨询。workflowNames 空/缺省使每个名字都 unknown——闸门绝不因缺省而"全放行",但默认模式把这一点变成咨询而非阻断。
与 Enforcement: hard 的交互。 workflow 闸门的模式是它自己的 Config 旋钮——跨切面的 Enforcement: hard 解析(compass / Assignment 头字段 / Config enforcement)不会升级 workflowGate。hard-enforcement 部署仍按已配置模式运行 workflow 闸门(默认 warn = 仅咨询),除非同时设置 workflowGate: 'ask' 或 'hard';反之 workflowGate: 'hard' 与跨切面解析无关地否决。二者不可混淆:workflow 闸门只在部署把模式选入时才关闭 "Enforcement: hard 下的未把关扇出" 缺口。
Fail-open 边缘(有文档,绝不崩溃合规调用)。(1)畸形参数——workflow 调用缺少非空字符串 meta.name(控制字符归一化之后),或 ralph 调用缺少字符串 objective → 在每个模式下(hard 亦然)直通 + 一条 warn,且无 verdict 行(未产生策略判定)。只含控制字符的名字归一化为空 → 视为畸形。(2)status.json 不可读——经含容解析器路径的 P-b 状态读取抛出 → 仅本次调用的 P-b 降级 + 一条 warn;P-a/P-c(基于名字,无状态依赖)照常运行。闸门从不抛出:每次读取都是结构化的。
Verdict 账本行。 每个被把关的调用都在 agent-flow 账本记录一条持久化 workflow-verdict 行(P2 账本 plan 的记录路径,完全含容——账本写入失败绝不波及闸门):tool(workflow | ralph)、workflow(归一化后的 meta.name)或 objective、mode(绝不为 off——off 在策略前短路)、判定词汇 ok / advisory / denied / ask(ask 判定是本次扩展:首见 ask 本身也是被把关的调用,其行携带 ask 直到审批瀑布解析——"每次被把关的调用一行")。违规码来自判定、绝不猜测:workflow.name.unknown(P-a)vs workflow.lease.uncovered(P-b)。fail-open 路径(畸形参数 / 状态不可读)不记录;未解析出 harness 目录的调用跳过该行(与派发记录路径相同的静默 no-op)。
P-c 答案观测 seam。 闸门无法观测 ask 结果——工具注册表的 serviceAsk 在内部消费审批结果。run-start 观测就是答案 seam:被 ALLOW 的 ask 执行调用 → 持久化 tool-workflow/run-start 会话事件落入父会话日志 → workflow-ledger 消费者记录 W-B2 workflow-run 行并把 allow 按运行名缓存进 apply 作用域的 WorkflowAskCache。被 DENY 的答案不产生运行 → 无观测 → ask 模式下下一次同名调用重新 ask(fail-closed——无授权证据,绝不发明 allow)。缓存键在两个 seam 都是归一化(剥离 ASCII 控制字符)不截断的名字——闸门合成 meta.name 与观测记录 runName 都走同一个 normalizeWorkflowName,因此含控制字符的名字(au\u0000dit)永远无法卡死缓存(ask 一次、同一键观测),>1024 字符的名字仍以完整名字为键(账本行的展示名字单独截断;身份轴从不截断)。缓存是 apply 作用域的——新 apply(HMR 重载)从空开始,因此未解析的首见名字每次调用都会重新 ask,直到一次观测(或显式 record())落地。缓存记录抛错时观测降级为一条 warn——账本行已追加,运行不受影响。
P-b 抢占。 租约红线最先运行:调用工作区存在 uncovered 的 InProgress plan 意味着在 plan 恢复前不应启动任何可写扇出子进程——与 workflow 名字无关(与 Assignment 键控的租约闸门同一条红线),对 ralph 同样适用。warn/ask 下仅咨询(放行 + 一条 warn);ask 通道绝不替代工作区红线。
LLM fallbacks integration
可选的 dsh-llm-fallbacks 插件(以第二条命令安装——见 Install paths)驱动基于角色的 subagent 配置:角色匹配的 subagent 派发会把配置的 persona 注入子会话的 system prompt。mstar 插件将其声明为 registry dependencies 条目并仅作类型导入——dist/ 对该包无打包运行时导入(仅 3 处命名该包的字符串字面量——探测的 loader 条目匹配与两条装饰日志——绝非导入;构建中的 --external dsh-llm-fallbacks 仍是对未来库形态导入的护栏);互操作是决策点能力探测,绝不读取其他插件的模块内部。
能力探测
挂载状态的两个视图(决策点即时读取,无缓存——loader 并发挂载条目):
fallbacksService(ctx)——插件被 apply 期间命名的 cordis 服务(ctx.get('llm-fallbacks'));HMR/纤程切换窗口内即使 loader 条目仍在,服务也为undefined(条目是声明式的,比纤程活得久)。fallbacksMounted(ctx)——能力视图,服务优先 + loader 条目回退:名为dsh-llm-fallbacks的 loader 条目存在、启用(尊重entry.disabled与 group 行)且纤程存活。
状态区分:mounted(服务已 apply——完整能力)、unmounted(无条目:未安装 fallbacks 插件——mstar 能力降级,绝不中断)、disabled(条目存在但禁用/分组——能力关闭),以及 HMR 窗口(条目在、服务缺——loader 回退覆盖)。
基于角色的装饰
装饰挂在 subagent/start EMIT 上——而非 tools/pre-execute(工具参数是深度冻结快照;persona/agentOptions 来自 tool-subagent 自己的 Config,绝不来自调用参数)。同步监听器经 ctx.get('agents')?.get(info.id) 解析已发布的子会话,当子会话的种子任务提示为 Assignment 形态时,把 persona 注册为子会话的 agent 作用域 mstar:role-persona system-prompt 段(order 1——紧随部署 persona 槽之后;子会话销毁时自动卸载)。角色身份使用与派发闸门相同的 engine Assignment 头语法。persona 查找是单一 personaFor 链——rolePersonas[executeAs] → 打包镜像默认值 → 跳过——绝不以 roleMap 或 fallbacks 挂载状态为前提。
零配置默认值:当 rolePersonas 未为某角色配置条目时,persona 取自打包的 harness-agents/ 镜像——构建时由 bundle-assets 从仓库根 agents/ 同步(随发布 tarball 携带;包相对路径解析,任意启动 cwd 均可用)。镜像文件名主干即角色 id;默认值为其 frontmatter description 块标量。镜像 shell 在 frontmatter mode 缺失或为 subagent 时才有资格——primary shell(project-manager)绝不作为 subagent persona 默认值。默认值 description 若含插值风险(配对的 {{/}})则在提取时告警并跳过(绝非启动抛错);shell 改动(mtime 变化)会在下一次决策点读取时重新提取。镜像缺失(未运行 bundle-assets)时查找仅走配置,配置也未命中时每次 apply 记一条 debug。
未挂载的降级为同通道 + 一条 debug 日志:无 fallbacks 条目 → persona 仍经完全相同的装饰通道注入(来自 mstar Config 或 harness-agents 镜像默认值),仅多一条来源可辨的 debug 日志;已挂载 → 一条携带服务版本的 info 级互操作日志。监听器绝不抛出——agents 服务缺失、子会话无法解析、非 Assignment 或角色未匹配的提示均跳过/无操作(派发本身永不受影响)。
persona 文本约束:dsh system-prompt 以严格 {{variable}} 插值渲染 persona 文本,因此 persona 值绝不能包含与后文 }} 配对的 {{(渲染器在子会话提示组装时对未知/畸形引用直接抛错——会破坏每一次角色匹配的派发)。Config schema 会在插件挂载时以清晰报错拒绝此类 rolePersonas 值。不带后续 }} 的孤立 {{ 按字面散文渲染(安全);转义规则是改用单花括号或改写措辞。persona 文本保持简短(几句话);长度在部署侧设限。
角色 seeds 与采纳建议(Adoption advisory)
当可选的 dsh-llm-fallbacks 能力已挂载(第二条安装命令——见 Install paths)时,mstar 插件会向 fallbacks seed registry 零配置声明 13 个 mode: subagent mstar 角色 seed:persona = harness-agents/ 镜像 description(原样)+ 一行强制加载引导(Load mstar-roles (references/<role-id>.md) and the role's Required Skill Dependencies before acting.);含 {{...}} 插值风险的 persona 跳过并告警,绝不声明。声明会合并保留 readback 中当前已 seeded 的非 mstar id——例如上游包在其自身 apply 时自声明的 7 个 omp 风格 preset 角色:上游 declare 全量替换 registry,若不保留,mstar-only 批会摘掉 preset id 的 seeded 注记(行仍在,仅失去 seeded)。声明在每次 fallbacks(重新)apply(HMR/纤程切换)时幂等重放——绝不用一次性 latch——因此两种 boot 顺序(presets 先或 mstar 先)都收敛到同一 20-id 全 seeded registry。
一条只告警的采纳建议通道(日志器 mstar/fallbacks-advisory)每次 apply 只跑一遍——apply 时先尝试一次;当 fallbacks 行在 dsh 之后挂载(loader 并发挂载条目)时,改在首个 subagent/start 决策点只跑一遍。服务存在时,通道先 await 幂等 re-declare(闭合 boot 竞争窗口)再读取有效状态(getEffectiveRoles),并按每类至多一条告警有界报告:
- 缺失 mstar 角色——无有效行的 mstar id(一条告警列出全部;id 集合派生自
harness-agents/镜像——绝不硬编码;无镜像 → 检查跳过并记一条 debug); - persona 覆盖——行 persona 与 seed 默认值不同的 mstar 角色(一条告警点名 + revert 入口:
fallbacks/revert-seedgateway / fallbacks 设置卡片回滚按钮——操作者覆盖在 revert 前保留); - 空 persona——
persona缺失/空白的行,仅限非 seeded 或 overridden-empty(一条告警点名); - 遗留键——
chains、roles.default、roles.list[].label/.description、悬空roles.rules[].role引用,经已应用服务自带的detectLegacyKeys(一条告警引用其语义); - declare 跳过/冲突——本地跳过(
interpolation/no-persona)+ 上游跳过/冲突(码persona-source——操作者覆盖保留)合并为一条告警;默认已 seeded 静默(一条 debug 点名)。
loader 回退路径(无服务)保留结构化 roles.list 读取(缺失 id / 空 persona;无 revert 入口——无 seeds 面;遗留键检查跳过——绝不重新实现)。行配置缺失或非对象、或 roles.list 不可读 → 跳过并记一条 debug。该建议绝不写入 fallbacks 配置——唯一写路径是经已发布 seeds 面的幂等 seeds re-declare(无差异 → 上游零设置写入)——绝不抛出,且 fallbacks 未挂载时不调用:它是信号,不是闸门。
配置面
| Key | Type | Default | Meaning |
|---|---|---|---|
roleMap |
Record<string, string> |
未设置 | mstar 角色 id → fallbacks 角色 id。仅作日志与未来规则驱动互操作的分类桥——装饰按设计不使用(persona 注入以 rolePersonas/镜像为源)。 |
rolePersonas |
Record<string, string> |
未设置(打包镜像默认) | mstar 角色 id → persona 文本;装饰的覆盖来源——某角色无条目时使用镜像默认值。 |
Service
apply 构造 ctx.dshMstar(engine 支撑:validateStatus、validateResidual、findingsCleanupGate、resolveCompassEnforcement、resolveHarnessDir、readHarnessVersion、applyEnforcement)。分层:P1 各闸门是本包内与 engine 同置的包装器,直接导入 engine(同一插件,构建时打包 engine);ctx.dshMstar 是供 inject 消费者使用的组合/测试外观;宿主适配器(下节)是面向宿主的门面。两条路径共用 engine 这唯一语法源。伴随入口 @mstar-harness/dsh/invariant 以文档化的空安装器保留包所有权。
Host adapter
插件以 DshHostAdapter 实现 engine HostAdapter 契约(host: 'dsh'),并以 ctx.dshHostAdapter 服务暴露。检测:engine detectHost 将 dsh 委派工具名——ToolSignal subagent(模型可见的 dsh subagent 工具)——映射为 'dsh',在 omp 之后、kimi/zcode/codex 之前求值;混合会话按固定顺序让位于更早的行。适配器与插件内闸门共用同一套校验核心(单一代码路径):beforeStatusWrite(path, doc) 在宿主提供文档时校验传入文档,否则走磁盘文档回退(文件缺失 = 首次创建 = 放行);beforeDispatch(assignment) 运行字段 + 分支 + 反递归闸门并携带强制执行后的 hardBlocked 判定(租约闸门留在监听器侧——它绑定该钩子不携带的 ToolExecution 会话上下文);beforeMerge(lease) 是 engine validateIntegrationMergeLease 的薄包装(向 status.json 的预留写入是 P3 seam)。log 默认路由到 dsh ctx 日志器 mstar/host-adapter。
dsh 的冻结技能根形态(engine resolveSkillRoot('dsh', …))为 $DSH_BUNDLED_SKILL_DIR/<name>[/<rel>]——解析器只定义技能相对路径解析器(resolveAssetPath)所用的规范形态;它不挂载目录。挂载由插件负责(下一节)。
Skills mount
mstar 技能通过 dsh skill-filesystem 提供者以单一规范挂载接入:插件把配置的根注册为一个提供者(providerName: 'mstar'、includeDefaultRoots: false——隔离,绝不看到宿主应用自身的项目/用户技能),上文的 engine 形态是共享的技能根契约。两条 Config 路径填充它:
| 路径 | 机制 | 时机 |
|---|---|---|
| Bundled 默认 | bundledSkillDir 默认取包内自带的 harness-skills/ 镜像——仓库根 skills/(19 个 mstar-* + pm)由 bundle-assets 在构建/postinstall 时同步(gitignore),按包相对路径解析(非 cwd 锚定——任意启动 cwd 都可用) |
发布包 / 无覆盖的任何部署 |
| 自定义根 | skillRoots / 显式 bundledSkillDir → skill-filesystem customSkillDirs / bundledSkillDir 条目(显式值优先) |
本地开发 / 测试 / 使用不同镜像的部署 |
打包镜像是单一规范挂载:技能内容只在仓库根 skills/ 镜像中存一份并同步进包(与 opencode 的 harness-skills/ 相同),mstar 技能在任何地方都保持可独立使用。不重复加载:opencode 插件在自己的包里携带同一批技能,因此 dsh 只能通过这条 skill-filesystem 路径挂载它们。
开发期现实:@deepseek-ai/dsh-skill-filesystem 运行时是 peer stub(契约镜像的注册,无文件 watcher),因此挂载通过真实组合(stub + 实际镜像 skills/ 的 frontmatter,用 engine lintSkillFrontmatter 校验)验证;真实运行时组合(真实 seam 包、watcher、$DSH_BUNDLED_SKILL_DIR 环境变量流)是部署目标,不在本包测试套件覆盖内。
Commands
插件把 bundled 的 mstar 命令(omp/opencode 对齐面)注册到 ctx.commands:harness-commands/*.md——仓库根 commands/ 镜像(iteration-start、iteration-drive、iteration-loop、codebase-audit)由 bundle-assets 在构建/postinstall 时同步(gitignore)。每条注册读取命令的 name/description/input frontmatter;声明了 input hint 的注册会将其作为 input.hint 公布,使 dsh web 客户端的决策表从「脱离式裸执行」翻转为 leadingInput claim——菜单点选后把 /name 插入输入框(命令色 token + ghost hint),按 Enter 才提交,用户可以键入后续参数(与 /plan、/goal、/advisor 相同的交互)。handler 把命令正文以 USER source 消息 steer 进接收 agent(dsh-plan-mode 命令先例——source: { kind: 'user' },模型把正文当作要执行的任务而非注入上下文;即 dsh-commands 的「经接收 Agent 显式调度模型可见工作」路径),用户键入的参数以 ## User input 小节追加在正文后,返回成功结果。注册以 ctx.inject(['commands'], …) 延迟进行——与工具注册相同的可选单元模式——插件在无 commands 服务时也能启动;镜像缺失(未跑 bundle-assets)则不注册任何命令。
Engine seam mapping
每个 engine 模块都挂到一条 dsh 表面——除 lint 模块的 plan/tdd fs 闸门外均已交付(延后项;见 Known Limitations):
| Engine 模块 | dsh seam | 状态 |
|---|---|---|
| core(applyEnforcement、GateResult/Severity) | 跨切面否决/拒绝 | 已交付(P1) |
| path(resolveHarnessDir) | harness 目录探测 + {HARNESS_DIR}/status.json 目标匹配 |
已交付(P1) |
| status(validateStatus、validateResidual、findingsCleanupGate) | status.json 的 fs/write-intent + fs/edit-intent |
已交付(P1) |
| lease(verifyPlanExecutionLease、validateIntegrationMergeLease) | exec 租约:tools/pre-execute(派发闸门内);merge 租约:HostAdapter.beforeMerge |
已交付(P1 exec / P3 merge) |
| dispatch(composeDispatchGate、isReadOnlyAssignmentRole、parseAssignmentFields) | 作用于 subagent 工具的 tools/pre-execute(PreToolDecision.deny 阻断);agent/pre-step 咨询 |
已交付(P1) |
| host(resolveSkillRoot、HostAdapter) | engine host.ts 检测行 + 插件适配器(host: 'dsh') |
已交付(P2) |
| skill-authoring(lintFrontmatter、lintFiveQuestion) | skill-filesystem 根 + 对 SKILL.md 的 fs/write-intent |
已交付(P2) |
| lint(lintSkillFrontmatter、planQualityBar、assertSddTddTriple) | 未接线——plan/tdd 的 fs 闸门为延后项;lintSkillFrontmatter 仅运行于 skills-mount 测试套件 |
延后 |
| agent catalog | MessageSourceMap mstar-engine-status(模型可见 ⟺ 已记录) |
已交付(P2) |
| sdd(sddWorkspace、taskBrief) | 注册在 ctx.tools 上的 defineTool 包装 |
已交付(P3) |
| iteration(evaluatePhaseGate、parseCompassFrontmatter) | agent/pre-step + iteration 闸门 |
已交付(P3) |
| worktree(l1PreDispatchCheck、l2PreDispatchCheck) | tools/pre-execute L1/L2(派发闸门内) |
已交付(P3) |
| design-md / audit / compound / roles | fs/write-intent + 注册在 ctx.tools 上的 defineTool 包装 |
已交付(P3) |
Engine-status catalog
一个咨询式 agent/pre-step 瀑布监听器向每个组合后的步骤追加一条 mstar-engine-status catalog MessageSource(kind/form: 'catalog' 契约,镜像 dsh tool-skill 先例):模型可见的 <mstar_engine_status> 块渲染水印字段——mstar 版本(插件自身清单;单一版本不变量把打包的 engine 钉在同一版本)、harness 目录(解析后的 {HARNESS_DIR},缺失为 none)、enforcement(compass 模式,soft / hard (compass))——以及 迭代相位闸门段(当 steering compass + status.json 可解析时:迭代 id、transition、all-plans-done、闸门判定 + 违规码——即 mstar iteration gate 工具结果形态)与 工作区状态摘要段(当工作区有 status.json 时):plans(id(status) 注册表)、residuals(按 severity 的 open 计数)、branch(base → target、spec 集成)、policy(push 政策、worktree 模式、control 根)、leases(活跃 plan 执行租约:持有者 + worktree)、knowledge(知识索引文档数与分类)与 direction(steering compass 的 problem statement 一句话)。监听器先调用 next() 并基于委托后的决策追加——从不否决步骤、从不替换已组合的消息。模型可见 ⟺ 已记录:持久化的 catalog 形态 source 在模型面向的散文旁记录了其发布的事实,会话日志无需重新解析该块即可重建该行(dsh packages/AGENTS.md)。fiber 销毁即移除监听器(HMR 安全)。
该行是 digest 门控的:按 agent+workspace,每个 turn 只注入一次,仅当渲染文本变化时重新注入——20 步的 turn 只显示一次 catalog,而不是 20 次。source 共享同一按工作区缓存条目:显式 harnessDir 时在 boot 构建(否则在工作区首次 pre-step 构建),并按 TTL 刷新(catalogTtlMs,默认 60 秒)——刷新间隔之间热路径只是时间戳比较 + Map 命中,会话中 plan/compass/residual 的变化在一个间隔内落地。
Agent-flow ledger(workflow 行)
agent-flow 账本——{HARNESS_DIR}/agent-flow.jsonl,即 catalog 的 state.agentFlow 证据所读的同一 JSONL——同样记录 workflow / ralph 扇出运行:一个会话事件消费者(日志器 mstar/workflow-ledger,apply 时注册)把四个持久化的 tool-workflow/* 会话事件映射为三种新账本类型。事实来源是持久化会话事件——追加进调用方父会话的日志(仅顶层运行;嵌套 transport 调用上游不记录任何东西),而不是内存中的 workflow/* emits(roadmap §10.4 N4):会话日志才是可回放的事实,因此消费者以 apply 时冷扫描(构造期种子事件从不进 firehose——firstLiveSeq)加实时 session/event firehose 监听覆盖它,按持久化逐会话水位线(会话日志 seq 位置)去重——水位线持久化到 {HARNESS_DIR}/workflow-ledger-cursors.json(账本旁的小型有界 sidecar,temp 文件 + rename 原子写入)。
tool-workflow/* 事件 |
账本行 | 字段 |
|---|---|---|
run-start |
workflow-run |
runId、name、agent?(承载的父会话 id) |
agent-start |
workflow-agent |
runId、seq(1 起始的成员序号)、label、phase?、childId |
run-end |
workflow-run-end |
runId、stopReason(completed / cancelled / error) |
tool-workflow/agent-end 是上游成员簿记,没有账本类型(成员 outcome 有意不持久化),被过滤掉。可选字段(agent / phase)缺席时从序列化行省略(lossless-JSON 纪律);三种类型共用账本的 AGENT_FLOW_MAX_EVENTS 截断 + 大小门禁,畸形行读取时收敛为 undefined(绝不重序列化)。展示字段(name / label / phase)在边界确定性限长(WORKFLOW_LEDGER_MAX_NAME_LENGTH 1024、WORKFLOW_LEDGER_MAX_LABEL_LENGTH 512——超长值以 … 标记截断);id 尺寸字段(runId / childId,上限 512)超长时整行跳过——绝不截断成碰撞。
第四种类型 workflow-verdict 由 workflow/ralph 闸门(而非本消费者)写入——每个被把关的调用一行(tool、workflow/objective、mode、判定 ok/advisory/denied/ask、违规 code)——见 Gates → Workflow / ralph gate。展示身份字段(workflow / objective)同样带 1024 字符上限;判定的违规码绝不猜测(P-a workflow.name.unknown vs P-b workflow.lease.uncovered)。
去重与回放范围。 持久化水位线即去重机制:冷热重叠以及插件重应用/重启(重注册读取持久化水位线而非从空游标开始)下每个 (runId, kind, seq) 只产一行。apply 之后创建、带构造期种子日志(恢复/分叉会话——其种子从不进 firehose)的会话会在上游 session/created 事件上冷扫描一次,水位线同样保证该回填幂等。水位线 sidecar 有界(每 harness 会话数上限,驱逐优先已不在线的会话)且完全受控:水位线不可读/不可写时降级为仅内存并告警一次——重启后会重录(诚实的去重欠录,绝不丢数据、绝不阻塞)。
childId 关联 + 成员计数。 workflow-agent 行保留已发布成员的 childId(子会话 id);运行的展示 name 只存在于 workflow-run 行,面板为 agent/end 行经窗口查找解析(同一 runId——成员行本身不带名称)。面板把成员 COUNT 挂到 workflow-run 行(窗口内该 runId 的 workflow-agent 行数;窗口有界——被 ≤50 事件窗口截掉的成员如实缺席,绝不猜 0)。
深度咨询(观察时)。 agent-start 时,消费者经 sessions.get(childId) 解析子会话,当其 header.delegationDepth ≥ 2 时告警——每个运行至多一次(per-runId 闩锁),日志器 mstar/workflow-ledger。仅观察时,绝不是拒绝通道:子会话读取抛出只降级咨询本身,绝不影响行或运行。
零行为变更保证。 消费者仅观察:零门禁——每次读取与追加都 try/catch 包裹;账本写入失败绝不崩溃或改变 workflow 运行;会话读取抛出只记一条 warn 并继续。sessions 服务经 ctx.get('sessions') 结构化读取——对 @deepseek-ai/dsh-session 无运行时依赖。
挂载顺序说明。 消费者只在 apply 时 sessions 服务可用时激活——dsh-session 行必须先于 mstar 行挂载(标准 web profile 顺序即如此)。dsh-session 后于插件挂载(或缺失)的组合静默降级:一条 debug 日志(sessions service absent — workflow-ledger consumer disabled)且不记录任何行——绝不是错误,绝不是运行损坏。
面板可见性。 三种 workflow 行经现有事件行样式(无重设计)渲染在 事件记录(Event Log)tab 的 Agent 流转事件分区:摘要身份是运行 NAME(agent/end 行经窗口查找解析;回退 runId → 「未知」),详情体新增四个 workflow 字段——run-id / name / members / stop-reason(缺失 → 「—」)——expected/settled 席位渲染「—」(workflow 行不是角色派发——不存在 settle 配对,与 settle 行同先例)。未知 kind 字符串渲染为通用行(kind 原文、无 workflow 字段)——绝不丢弃、绝不猜测。catalog 摘要把 workflow 行计为独立 workflow 桶(模型行 by role: workflow N)——绝不并入派发角色计数。
Web 客户端插件(工作流面板)
本包为 dsh web profile 提供浏览器客户端半体,在已安装的 mstar bundle 行上被自动发现(package.json 的 dsh.client 声明 + exports["./client"] → dist/client.js——上游 web dsh.client 发现逻辑扫描 loader entries,并把每个客户端的 exports["./client"] 解析进 boot 图)——无需独立 profile 层或安装步骤(spec §6.1)。web 应用在 /plugins/@mstar-harness/dsh/client.js 提供该 bundle,并经 closure-factory loader 握手加载(window.__ModuleLoader__.load({ id, factory }))。
客户端入口在 conversation.view view ring 注册一个 tab(id: 'mstar-workflow'、order: 20——trajectory 先例形态),经 mstar-panel locale 命名空间命名为 "MStar 工作流"(zh)/ "MStar Workflow"(en)。面板即 MStar 工作流布局:右侧固定 300px sidebar——计划(≤5 时间倒序 + +N more)、未决残留 findings(≤10、severity chip、溢出提示)、策略(enforcement 首位 + push / worktree / control worktree)、租约、知识、方向——其下为底部 fixed 小面板(版本 + harness 目录;小字号 muted、不随 sidebar digest 滚动;原 header 行已移除),主体为 HTML/CSS zone dashboard,外加新鲜度 footer(last-updated HH:MM:SS + catalog 重发刷新说明)。branches 区块已移出 sidebar 迁入迭代区(plan 20260810-panel-canvas-zones)。860px 以下 sidebar 堆叠到主区下方。
canvas 区是会话日志中最新一条 mstar-engine-status catalog 行的纯渲染(数据来自 useSession 快照——刷新跟随快照,不轮询):页面撑满 Tab(无整页滚动——zone 容器是唯一滚动主体),zone dashboard(替代 react-flow 循环图,plan 20260810-panel-canvas-zones)排布三区——迭代区(Step 1–5 竖排 stepper + Step N/5 徽标、激活高亮 / 未激活暗淡态;steps 为四态状态机——current / next / done / idle(plan 20260812-panel-f5-iteration-zone-fix Task 1):current 之前的步骤投影为 done「已完成」(已完成的 Step 1 不得在 Step 2 current 时显示为待命 idle),next 为唯一前向目标,idle 仅为 schema 余项——分支面板:迭代 base / 目标分支 / spec 集成分支,仅激活时渲染;展开态头部为左右分栏——分支(左小半,宽度受约束——flex: 0 1 260px + max-width: 280px,不再随容器撑宽;<860px 竖排时重置为内容高度)+ Steps(右大半,flex: 1 1 0 吸收剩余宽度),经 data-iteration-head-split,窄宽回退堆叠,无激活迭代时无分支面板;当前步跟随 steering compass:compassStatus: 'active'(Phase 1 进行中)→ Step 1(iteration-start)为当前步且 verdict 为 unknown——无 PASS/FAIL 徽标——plan 20260811-panel-f4-iteration-zone);迭代信息 Section 由任务迭代与代理执行两 tab 共用(plan 20260812-panel-f5-design-system Task 8,用户第 4 轮决策 #4——单一 IterationInfoSection 组件,两 tab 渲染同一 view.iteration 块:摘要 + steps + 分支);任务区(5 列 kanban:Todo / InProgress / InReview / Done / blocked-unknown——Blocked 与原有 unknown 兜底合并为单列,标题「受阻/未知」/「Blocked / Unknown」,plan 20260813-panel-quick-fixes Task 1——带计数徽标;每列渲染行数统一以 PLAN_CAP 封顶,超限显示可点击的「更多」/「收起」展开按钮(data-kanban-more 锚点)展开全量——投影保留全部 plan 行,封顶只是渲染关注点、绝不丢弃)与代理执行区(四个 EXPECTED_ROLE_FLOW stage/phase 列——review-edit-chain → sdd-implement → qc-tri → qa-gate(终点阶段;原 sdd-task-review 阶段已删除,其 SDD L2 审查者现为管线内角色 code-reviewer,v2.1.1)——严格四列布局、无独立 unknown 列(plan 20260812-panel-f5-design-system Task 5,用户 2026-08-12 第二轮决策——原 plan 20260812-panel-f5-agent-layout 的最右 unknown 列被取代):general 桶下沉至 qa-gate 列底部 unknown 子分区(data-sub-bucket="unknown" 标题行「unknown / 未匹配角色」,位于末张 qa-gate 卡之后,其下排布 general 卡;独立 on-demand 列已于 agent-layout plan 移除);explore 已移除——无卡无列。sdd-implement 列按投影 entity.bucket 拆为子桶(绝非渲染猜测):上方 implementor 分区——按 stage 原始顺序的 flow 角色(fullstack-dev / fullstack-dev-2 / frontend-dev),随后是 on-demand 角色(ops-engineer / prompt-engineer,带 按需徽标——无独立 on-demand 列)——与下方 sdd-reviewer 分区(code-reviewer,SDD L2 task reviewer),带 implementor / sdd-reviewer 标题标签;zone: 'on-demand' 实体位于 implementor 分区内,zone: 'general' 实体渲染于 qa-gate 列底部 unknown 子分区。画布按两个左右并排的 Phase 分组排布(plan 20260812-panel-f5-design-system Task 8,用户第 4 轮决策 #2;左右排列 per plan 20260813-panel-agent-canvas-legend-layout Task 2):左:Phase 1 组(review-edit-chain——顺序完成的 Review & Edit 链:product-manager → architect → writing-specialist)+ 右:Phase 2 组(sdd-implement → qc-tri → qa-gate——循环迭代 plans),顶部对齐(各组标签行共享同一 y = PAD_Y),各带组标签行;Phase 2 组标签标注当前 plan(data-canvas-group-plan = 投影 activePlanId = state.plans[] 中首个 InProgress plan_id;多个进行中 → +N more 诚实计数;无 → 灰字「无进行中 plan」)。subagent 实体卡按 role 聚合:同一角色跨 session 合并为一张卡 ×N,所有 off-roster 派发(原 generalPurpose SDD 审查者、scout、匿名 role === '')归入唯一 general 桶实体——卡以 role 为标题(role id);agent session id / 任务标签(planId#taskId)走在记录行上、不作卡标题——卡片显示 role chip / 状态点 / ×N 计数;执行中实体带 business glow-pulse 高亮(施加于圆角 .card-body——卡片为唯一圆角元素,无方形外轮廓叠加,plan 20260812-panel-f5-design-system Task 5),无证据 stage 渲染虚线「待执行」占位(含预期 role chips),无证据 KNOWN_AGENTS 成员渲染虚线 idle 卡(14 角色 roster 永不隐藏),头部显示 N 执行中 · M 待执行 摘要;卡片携带投影 透明度分级(plan 20260812-panel-f5-design-system Task 4,design doc §3):emphasis: 'current' | 'next' | 'off' | null——迭代当前阶段角色 100% chrome 全强度、后续阶段预期角色 75%、已过阶段 / 无阶段角色(on-demand、general)45%,null(无迭代 / transition 不可解析)不覆盖——恒为 chrome alpha 混合(--mstar-canvas-emphasis-* token;绝不整卡 opacity,状态点与 running 辉光保持不透明)。已结算实体带独立绿色完成框 + 绿 ✓(plan 20260812-panel-f5-design-system Task 8,用户第 4 轮决策 #1/#3:data-agent-done="true"——圆角卡片体 success 边框 + 1px ring + 状态点绿 ✓,全强度 evidence 态)——仅当 emphasis ≠ 'off';off 档角色(已过阶段 / 无阶段 on-demand + general)显示灰字圆点、绝不显示完成标记(第 4 轮 #3:已完成状态不出现在无阶段角色上)。画布只投影当前迭代的派发证据(plan 20260813-panel-quick-fixes Task 2):steering compass iterationId 活跃时取之,否则经 catalog plans[].iterationRefs 推导最近迭代(8 位日期前缀 + doneAt 最大的 plan 的 refs);可证明跨迭代的事件不产生实体/连线(roster 常驻 idle 卡),无 plan / 未知 plan / 独立 plan 的派发绝不隐藏。状态诚实(Task 2):advisory 不再终态——软执法派发落到配对 settle(有 settle 绿 ✓ 已完成、无 settle 显示执行中),denied 仍为终态;advisory verdict 仍在事件记录页呈现。画布图例位于视口下方(Task 3,自上方移下,用户 2026-08-13 反馈)。连线(plan 20260812-panel-f5-design-system Task 5,design doc §2):expected 阶段骨架箭头与带动画的 next 边(原 @keyframes agent-dash-flow dash-flow 箭头,plan 20260810-panel-agent-flow-zone)已移除——流转顺序由固定列序 + 列标签暗示、当前位置由 running 辉光 + 状态点承担——仅余两类语义线:证据驱动的 actual 交接线(同 plan ts 相邻派发实体键对、过滤 general 端点、同对实体键至多 1 条)以 bezier C 曲线绘制,锚定卡片 4 端口(上/下/左/右四边中点;静止不可见、hover 显示为小圆点),箭头尖端退让至端口外 10px standoff——箭头沿线在锚点处的局部切线(H1),任何线的描边/箭头不穿过文字(H2:standoff + 侧隙路由,design doc §2.0/§2.5/§2.6;plan 20260813-panel-quick-fixes Task 3 收紧——同列纵向流的中线会穿过中间卡片体时改走列左侧隙带(正向与反向;如 fullstack-dev → frontend-dev 跳过 idle 的 fullstack-dev-2),反向水平 bezier 保持方向感知控制点位于端点之间、不再向相邻列鼓包)——外加双向监督线(plan 20260812-panel-f5-agent-layout Task 1/2)——sdd-implement 列内一条静态设计知识子桶边(implementor ↔ sdd-reviewer——mstar-sdd 相互监督契约),现锚定于列外侧隙垂直锚点(x = 卡片右缘 + 18px,垂直 bezier 流,箭头沿垂直切线——design doc §2.5/§2.7);默认 dim 虚线,投影 evidenced 为真时亮起 business 实线(证据驱动点亮,绝不伪造激活))——agent 流转事件条迁入**「事件记录」tab 日志页**(spec F1.5,plan 20260811-panel-event-log):非 canvas 日志页——Agent 流转事件 / 违规记录 两个分区,每条可展开原生 <details> 呈现完整 catalog 字段(缺失字段显示「—」,绝不捏造),空态 muted;两个分区在锁定高度的左右两列 grid(repeat(2, minmax(0, 1fr)))中并排——页面整体不再滚动,各分区固定标题、列表内部滚动(plan 20260813-panel-quick-fixes Task 4 修复根因——面板根节点接入宿主 data-conversation-composer-overlay 全高 opt-in,使 height:100% 真正解析、.rowList 的 overflow-y: auto 在分区内部滚动、宿主页面不再整页滚动,底部按宿主发布 --dsh-composer-height 预留悬浮 composer 间隙)——1200px 以下回退为两个 50/50 锁定行(data-event-log-* 锚点族不变,plan 20260811-panel-f3-agent-general);canvas 左下角 fixed AgentEventDock 与底部 fixed footer 条随页面落地而移除(无双份日志,spec §5)。空分支(spec §2,plan 20260812-panel-f5-agent-layout Task 3):waiting 保留 muted hint;无 harness 时渲染居中未激活态卡片——文件夹图标 + 「未检测到 Morning Star harness」标题 + hint 文案(详细面板保持未激活——无 tab、无 sidebar——检测到 harness 后自动呈现;data-mstar-empty="no-harness" 锚点保留在标题上,data-mstar-graph 在主容器上)。1200px 以下三区纵向堆叠。投影为纯函数 projectGraph(source)(schema 常量与 catalog 证据严格分离;永不 throw;缺失字段显式降级为空态/最后已知态——muted 空态,绝无橙色 warn 框),产出纯数据 ZoneView;WorkflowCanvas 以纯 HTML/CSS 渲染。
依赖:zone dashboard 不携带任何图库——@xyflow/react devDependency(此前构建期内联进 dist/client.js)随 react-flow 渲染层一并移除(plan 20260810-panel-canvas-zones),唯一消费者是 @xyflow/react/dist/style.css 的 plain-.css text loader 也已删除(CLIENT_EXTERNALS 不变——react / react-dom 与 @deepseek-ai/dsh-client-* 平台模块保持外部)。构建脚本端到端断言移除成立:产物不得含 xyflow/reactflow 标记、@deepseek-ai/* 值导入为 0、无 import.meta / ESM 语句——web loader 以经典 <script> 执行插件 bundle,字面 import.meta 是 parse-time SyntaxError(zustand v4 的 import.meta.env 读取已在构建期 define 消除;见本迭代 install-verification guide §6)。本 plan 收口时的体积:145,159 B raw / 29,460 B gzip(以各迭代 install-verification guide 为重新测量 SSOT——react-flow 移除后缩至约 85 KB,代理执行区实体渲染落地后回升,F5 透明度分级 + 连线重构后再度增长)。
安装 / 验证(客户端半体与服务器半体走同一条 bundle 行安装):
cd <repo>/packages/dsh
bun run build # dist/client.js(closure-factory CJS)+ dist/client.d.ts
# corepack 机器(仓库根声明 packageManager: bun):命令前加 COREPACK_ENABLE_PROJECT_SPEC=0
dsh plugin --profile web add <abs packages/dsh path> # 同一 profile bundle 安装
dsh web # 启动 → 服务 /plugins/@mstar-harness/dsh/client.js
本地已验证(install-verification guide):boot 图包含客户端 entry(@mstar-harness/dsh 携声明的 inject 面)、/plugins/<id>/client.js 路由服务的正是构建产物(rev = 内容 sha1)、浏览器握手 materialize 出插件入口(inject + apply + CSS 注入,经典脚本语义)——见 .mstar/iterations/iter-20260809-mstar-panel-beautify/guides/install-verification.md。
Known Limitations(本迭代):迭代 stepper 的 Step 1(iteration-start)在 steering compass status: active(Phase 1 进行中——catalog compassStatus 字段)时为当前步,且不携带 PASS/FAIL 徽标(Phase 1 无 gate 判定);Step 5(merge-ready)永远不会是当前步——engine 相位门只评估 Phase 2→3→4(merge-ready 从不是 gate transition);仅当 Step 4(pr-delivery)为当前步时渲染 next,其余为 idle;当前步跟随 TTL 刷新的 compassStatus——会话中途 active→locked 翻转后最多落后一个 catalog 间隔(60 秒)(有界、已记录的陈旧;绝不给出错误判定);代理实体状态按精确配对派生(paired settle 携带的 (agent, role, planId, taskId) 标识精确配对到对应派发——QC tri N=3 并发下各卡各自结算;未配对派发保持 running,绝不捏造);无 steering compass 时的「当前迭代」过滤按 plan id(8 位日期前缀)+ doneAt 推导迭代——确定性、已记录的启发式,且只丢弃可证明跨迭代的事件);不回溯 resumed 长日志的历史行(服务端每 turn 首步必重发,digest 门控);无自定义顶层槽位(不改 dsh-private 布局的前提下,conversation.view tab 是唯一的会话级面板位——spec §1)。面板验收为双轨:in-loop 浏览器 harness 验证(对重建 bundle,见迭代 guides iter-20260810-panel-zones/guides/)+ 用户重启后 GUI 终验——重跑步骤见 install-verification guide §8。R1(浏览器观察)已于 2026-08-10 关闭归档。
Development
命令(在 packages/dsh 下执行):覆盖率门禁为 src/ 逐文件 100%(dsh 测试策略);构建命令把 src 条目 bun 打包进 dist/(内联 engine 与 schemastery;@deepseek-ai/cordis 与运行时 seam 导入——@deepseek-ai/dsh-skill-filesystem、@deepseek-ai/dsh-tools(defineTool)、@deepseek-ai/dsh-llm——保持外部,外加仅类型导入的 dsh-llm-fallbacks),运行 build-client(scripts/build-client-bundle.ts——按 spec §6.2 产出的 closure-factory CJS 浏览器 bundle dist/client.js)并输出 tsc 声明。
bun test --coverage
bunx tsc --noEmit
bun run build
bun run test 会先构建客户端 bundle(pretest 钩子执行 build-client——manifest-contract 套件断言 dist/client.js 存在);fresh checkout 下直接 bun test 会以 bun run build 提示失败而非裸断言。
开发期 seam 表面(类型、事件形态、运行时)是来自公开 npm registry(registry.npmjs.org,无需根 .npmrc)的真实 @deepseek-ai/dsh-* 包(bun 默认自动安装 peer)。
Model Experience
Request surface and condition
What the model sees
每个组合后的步骤携带一条 mstar-engine-status catalog 用户消息(<mstar_engine_status> 水印块——见 Engine-status catalog 一节)。闸门决策额外添加:派发否决以注册表物化的 PreToolDecision { kind: 'deny', reason } 错误呈现;状态闸门以 mstar/status-gate 咨询呈现(告警放行、hard 修复逃生或降级放行);派发闸门以 mstar/dispatch-gate 咨询呈现(告警放行或降级);技能 lint 闸门以 mstar/skill-lint 咨询呈现(告警放行、hard 修复逃生或降级放行)。每条模型可见的行都能从会话日志重建(catalog 形态 source + 咨询事件)。
Leaf 交付纪律(PM 2026-08-12):leaf 子代理在最终(closing)消息中交回完成报告,不通过 report 工具交付——dsh tool-subagent-report 默认 reportDelivery: quiet 会把报告投递到父代理的 next-step 队列,父代理 turn 结束(无 step 边界)后报告会滞留队列。closing 消息是可靠交付通道;report 保留给「中途发现、需要父代理改变下一步」的发现(SSOT:skills/mstar-host/references/dsh.md → PM dispatch)。
Token effect
catalog 向每个组合后的步骤追加一条固定、稳定的用户消息(小的常量块——除每步一行外不随会话长度增长;按会话摘要去重是 P3 项)。否决与咨询文本仅在闸门触发时存在。
KV Cache effect
catalog 行在委托之后追加到组合步骤消息的末尾——请求前缀(system prompt 与先前消息)不受影响,因此插件既不创建也不失效前缀缓存状态;尾部行跨步骤逐字节相同。工具错误文本随违规变化,但从不参与请求前缀。
Known Limitations and Deferred Work
- 开发期 seam 从 npm registry 解析 ——
@deepseek-ai/dsh-*各 seam 仅为 peerDependencies(运行时由宿主提供);开发期 typecheck/测试/构建从公开 npm registry(registry.npmjs.org,无需根.npmrc)解析(bun 默认自动安装 peer)。全部运行时 seam 导入在构建时外部化(--external @deepseek-ai/cordis / @deepseek-ai/dsh-skill-filesystem / @deepseek-ai/dsh-tools / @deepseek-ai/dsh-llm——发布的dist/导入它们而非内联占位代码);闸门通过真实注册表/fs 工具执行的同一ctx.waterfall派发来验证。本包套件直接运行来自 npm registry 的真实 seam 包——不再有提交的peer-stubs/占位、不再有本地 link farm。 - 反递归绑定为 Config 声明 —— dsh 在工具执行上下文上不暴露每 agent 角色,故
dispatchBinding声明单一部署级角色;Execute as不同的 Assignment 无法被识别为自我递归,多角色派发方需要按实例拆分插件。 - 租约闸门有意与 opencode 分叉 —— opencode 的
beforeDispatch不运行租约检查;dsh 租约闸门是新增的(lease.dispatch.*码),且仅对可写 SDD/InProgress 派发触发,故对齐覆盖字段集而非租约面。 - 已采纳 engine 共享组合 —— 派发闸门核心即 engine 的单一
composeDispatchGate(与 opencode/omp/CLI 对齐,字段/分支/反递归违规码按构造即相同),compass frontmatter 解析器即 engine 的共享parseCompassFrontmatter(本地 dsh 镜像与 CLI 副本均已删除——不再有可漂移的分叉)。两者都运行在 dsh 头区域切片上;租约 + worktree L1/L2 检查仍为叠加上去的 dsh 侧扩展。 - engine 单一版本钉定 ——
@mstar-harness/engine为精确2.1.1devDependency,构建时打入dist/(绝非运行时依赖);readHarnessVersion()读取 bundle 旁的 dsh 包清单 ——2.1.1,按单一版本不变量与钉定的 engine 相等。 - Schemastery 空数组物化 —— 省略的可选 ARRAY Config 键会物化为
[];派发键通过.default(undefined)保留省略语义,未来任何可选数组键都必须同样处理。 - 载荷边界 —— 派发闸门校验委派载荷(Assignment 文本),而非子代理的运行时行为;如需向模型可见的子活动建面,事后经
subagent/start观察仍为可选项。 - 状态闸门因 seam 设计而内容盲——
fs/write-intent/fs/edit-intent瀑布链只携带(target, actor),从不携带写入内容,因此首次把合法status.json写坏的写入在两种模式下都会通过(闸门只校验写入前的磁盘文档)。hard 模式因此从不否决状态写入:对已非法文档按修复逃生放行(error 级咨询,hard: true, repair: true),让修复性写入能落地。恢复路径:就地修复文档(闸门允许)或删除status.json让 harness 重建;hard 部署应监控repair: true咨询。 - 缺失
status.json的租约行为——sdd 可写派发遇到缺失状态文件会发出lease.dispatch.unverifiable(告警下 advisory,hard 下 deny);非 SDD 派发无租约义务,保持静默降级放行。 - 闸门匹配跟随
displayPath——状态闸门按 fs target 的解析后displayPath匹配。后端报告工作区相对路径、harness 目录为符号链接、或远程/URI target 时永不匹配,闸门对其惰性(无误报);受守护的 harness 写入请使用绝对本地路径。 - design-md seam 作用域为全局 basename 匹配——
isSeamTarget('design-md')匹配文件系统上任意DESIGN.md/DESIGN.dark.md,无论解析出的{HARNESS_DIR}/ 仓库根是什么。因此对不遵循 mstar token 格式的外部项目 DESIGN.md 的写入,在 hard 模式下会在 harness 之外记录 error 级修复逃生咨询(hard: true, repair: true)——一个嘈杂的误报面(写入从不被阻断)。有意为之(「工件即文件本身,无论设计位于何处」);在 harness 目录可解析时把作用域收窄到仓库根是可能的后续项。 - audit seam 作用域匹配任意深度上的任意
plans/audit-*段——isAuditPlanTarget扫描所有路径段,因此与 mstar 无关的目录树(例如带有plans/audit-*布局的依赖或兄弟项目)在写入时会收到 mstar audit 状态块 + 秘密 lint。与 design-md 作用域同类(仅咨询,从不阻断);该布局是 mstar-audit 文档化的 Phase 4 形态,因此匹配是有意为之。 <root>/mstar-roles/SKILL.md上 skill-lint × roles seam 双重触发——当某个已配置技能根包含mstar-roles目录(开发期的仓库根镜像情形,以及发布形态的打包镜像)时,对mstar-roles/SKILL.md的一次写入会同时触发技能撰写 lint 闸门与 roles seam 闸门(hard 下两条咨询 / 两条修复逃生日志)。两个校验器都合理适用——双重 lint 仅为咨询,并非正确性破坏;「作用域互不重叠」的性质只在四个 seam 之间成立,不跨技能闸门。- 内容盲的 skill-lint 盲区——
fs/write-intent槽位只携带(target, actor):首次创建的传入内容不被 lint,合法→非法覆盖在监听器路径上无法检出(它只 lint 写入前的磁盘文档)。告警/hard 咨询只呈现已存在的磁盘违规——与状态闸门同类限制。 - 显式相对
bundledSkillDir覆盖锚定 cwd——skill-filesystem 对相对打包根按普通join()语义解析到 dsh 进程 cwd。插件的默认打包根是包内自带的harness-skills/镜像,按包相对路径解析(非 cwd 锚定——任意启动 cwd 都可用);只有显式的相对覆盖继承 cwd 锚定,因此覆盖默认的部署应在 profile 层传绝对路径(见bundle/README.md)。 - Bundled 镜像是构建期同步——
harness-skills/+harness-commands/由bundle-assets在构建/postinstall 时产出(仓库根skills/+commands/镜像;gitignore)。未跑bundle-assets的检出不挂载 bundled 技能、不注册命令(默认挂载惰性,而非报错)。 - profile-bundle 安装到
webprofile:registry 与 local checkout——dsh plugin --profile web add @mstar-harness/dsh(registry)与add <本地检出>为受支持途径,均走同一 pnpm + reconcile 机制(reconcile 步骤把@mstar-harness/dsh并入dsh.profile.bundles)。local checkout 需要先执行bun run build——本包没有prepare脚本(monorepo 显式构建各包),未构建的检出会装入空的dist/。 lintSkillWrite类型化否决尚未接入生产——传入文档分支的 hard 否决(SkillLintVetoError,码skill-lint.veto)已导出并测试覆盖,但尚无生产调用方:engineHostAdapter没有携带内容的技能写入钩子(只有beforeStatusWrite/beforeDispatch/beforeMerge),且 fs intent 槽位内容盲。接线随未来携带内容的钩子落地;在此之前监听器路径只通过修复逃生咨询执行(从不否决)。- CLI
HOST_SIGNALS缺少subagenttoken——engineToolSignal联合已包含它且detectHost能处理,但packages/cli的HOST_SIGNALS尚未更新,mstar host detect --signals subagent会拒绝,直到上游化时更新 CLI 列表。 - 入口是
src/gates/*之上的模块索引——拆分已交付:src/index.ts(371 行)从各 gate 模块(_shared/status/skill-lint/seams/dispatch/catalog/tools/adapter)原样 re-export 冻结的 47 名导出面(28 值导出 + 19 type-only 名;Config计一次),并保留插件 manifest、单一 cordis augmentation 点、命令注册与apply()启动接线。导出面由tests/export-surface.spec.ts冻结——运行时值导出集 +typecheck:tests(bunx tsc --noEmit -p tests/tsconfig.json)下的值命名空间恒等与逐名类型探测。 - engine dsh 行待上游化——engine
host.ts的 dsh 改动(DetectResult、ToolSignal、resolveSkillRoot)位于 mstar-workflow engine 镜像,计划经用户授权的上游 PR 合入 mstar-harness;mstar-host技能镜像(§ Detect / § Resolve loaded skill root /references/dsh.md)随之一并更新。 - 迭代 stepper:Step 1 为 compass 驱动,Step 5 为 schema 驱动——zone dashboard 的 Step 1(iteration-start)在 steering compass
status: active(Phase 1 进行中)时为当前步(无 gate 判定 → 无 PASS/FAIL 徽标);Step 5(merge-ready)是 engine 闸门永不点亮为当前的 schema 常量(transition 只覆盖 Phase 2→3→4,merge-ready 从不是 gate transition);仅当 Step 4 为当前步时作为next渲染,其余为 idle——已记录于迭代 guide,非缺陷。完整面板限制清单见 Web 客户端插件一节。 dsh-llm-fallbacks为 registrydependencies条目且仅类型导入——声明^0.2.0(caret 范围允许 0.2.1+;探测形状断言测试是可执行的漂移闸门)并在构建中--external,因此dist/无打包运行时导入(仅 3 处命名该包的字符串字面量——探测的 loader 条目匹配与两条装饰日志;建议日志写作fallbacks);激活是单独显式安装(双命令契约),绝不传递。库形态依赖存在是为未来值导入无需改 manifest 即可解析;--external仍是护栏。- 本批次未交付角色→模型覆盖——把角色路由到 fallbacks
model(或经 fallbacks 规则路由 persona)需要改写启动请求上的子会话agentOptions,但启动请求选项由调用方控制(tool-subagent 自己的 Config;调用参数仅为description/prompt/run_in_background,且深度冻结)。等待上游fallbacks-explicit-role-tool或 N-B1 systemPrompt 采纳(roadmap §10.4)。 - 装饰是最小化的每子会话段,而非 N-B1 systemPrompt 采纳——
mstar:role-persona是子上下文上的一个 agent 作用域段;无 harness 规则段、无 PromptContext、无变量。N-B1(roadmap §10.4)日后可吸收或替换该通道而不改变可观察行为(AC-3)。 - persona 注入与 fallbacks 无关——
dsh-llm-fallbacks只路由 LLM 失败;装饰从不依赖它。未挂载 → 同一 persona 经同一通道来自 mstar Config,仅多一条 debug 日志(AC-4)。若组合中缺ctx.get('agents')(无 dsh-agent),装饰以一条 debug 日志跳过。 - fork 门禁仅默认开启;显式
dispatchTools可省略subagent_fork——自定义dispatchTools列表整体覆盖默认(既有重命名模式),因此自行声明列表的部署须包含subagent_fork才能继续门禁 fork 派发。 - persona 值绝不能包含
{{...}}——dsh system-prompt 以严格{{variable}}插值渲染 persona 文本,对与后文}}配对的{{(未知/畸形/未定义引用)直接抛错,会破坏每一次角色匹配派发的子会话提示组装。Config schema 在插件挂载时以清晰报错拒绝此类rolePersonas值;转义规则是改用单花括号或改写措辞(不带后续}}的孤立{{按字面散文渲染)。 - fallbacks HMR 重挂后的 seeds 再收敛受 seeded-only preservation 设计边界限制——seed registry 是每次 apply 的内存态,纤程切换(HMR / 设置编辑)会丢弃它并让双方 declarer 从头重放。mstar re-declare 只合并保留已 seeded 的 id(seeded-only,设计使然),因此在 preset-last 提交顺序下,preset 行的 seeded 注记不会被 re-declare 恢复——它们在下一次 fallbacks apply 时恢复(上游 preset 自声明重新播种)。
llm-fallbacks服务消失时 advisory 一次性 latch 会重新武装(inject teardown),因此下一个决策点会重新收敛 mstar 侧;preset 侧是 seeded-only preservation 设计的有文档说明的暂时现象。 - 咨询跳过原因
no-persona亦涵盖 extraction 失败——在 extraction 期被拒绝的镜像默认(例如含{{...}}插值风险)会在合并的 declare-outcome 行中以no-persona呈现(extraction 在风险门之前就返回无可用的 persona);逐 id 的 extraction 诊断保留在 debug 通道(mstar/fallbacks-advisory/mstar/fallbacks-seeds)。
链接
同类插件
Q00/ouroboros#integrations/dsh-plugin★ 5530
通过 DSH MCP 客户端挂载 Ouroboros 的纯配置包,在 DSH 中提供 36 个涵盖需求访谈、Seed、执行、评估与演化流程的工具。
NanmiCoder/dsh-agent-teams★ 529
AgentTeams 多智能体团队。
EthanYoQ/AI-Novel-Writer#dsh-ai-novel-writer★ 385
安装专用 AI 小说创作预设与工作台:提供带修订号的本地项目资产、紧凑侧边工作台,以及需要原生审批的逐文件变更。
orziz/odai#odai-dsh-plugin★ 87
面向整个 DSH profile 的治理与路由 bundle,提供可配置的压缩调用与本地作用域语义记忆;兼容 DSH 0.1.0-rc.6 与 0.1.0-rc.7。
icetomoyo/dsh_workflow★ 80
把 UltraCode 式多 Agent 调度带给 DSH:可生成、可保存、可治理、可观察、可恢复的 Workflow 层。
titanwings/dsh-automation★ 53
定时任务:让 Coding 任务按计划在全新 Agent Session 中运行,保留可审计历史。