npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mstar-harness/dsh

v3.2.6

Published

Morning Star harness dsh (DeepSeek Harness) cordis function plugin — in-process engine gates (status/dispatch/lease) with hard refusal channels.

Readme

@mstar-harness/dsh

English | 中文

dsh

Morning Star 成为一等公民的 dsh(DeepSeek Harness)宿主——一个 cordis 函数插件,将 mstar engine 进程内挂载,实现 engine HostAdapterhost: '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 | 仓库 .mstarc [config] harness_dir,否则按会话工作区探测(.mstar/.agents/.plans/plans/,从会话工作区根目录开始——绝不从启动 cwd) | 显式 harness 根目录;优先于 engine 探测。harness 根不在探测名列表中的仓库必须配置;探测从会话工作区根开始(绝不从启动 cwd)并在那里停止——永不越过会话工作区向上,因此其上方的 harness 目录(如全局 ~/.mstar)永远不会被采纳。 | | enforcement | 'hard' \| 'soft' | compass,否则仅告警 | 按部署覆盖。优先级:Config 优先;否则取 Assignment 自身的 **Enforcement**: hard 头字段(仅派发闸门);否则取仓库 .mstarc [config] enforcement;否则取迭代 compass frontmatter;否则仅告警。Config / .mstarc 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 监听器校验 v3 协调文档目标集——v2 根 {HARNESS_DIR}/status.jsonworkflows/<id>/snapshot.jsonprojects/<id>/residuals.json——各自使用匹配的 engine 校验器(validateStatus = v2 根 / validateWorkflowSnapshot / validateProjectRegister,即 P2 修复的 harnessDocKindOfTarget 形态),外加快照目标的 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_workspacemstar_sdd_task_briefmstar_iteration_gatemstar_design_md_validatemstar_audit_validatemstar_compound_validatemstar_roles_validate 注册到 ctx.toolsmstar_iteration_gate 镜像改用 v3 输入 snapshot_path{HARNESS_DIR}/workflows/<id>/snapshot.json——镜像 mstar iteration gate --workflow <id>;旧的根 status_path 输入随 v1 读取路径移除)。
  • bundled 命令——向 ctx.commands 注册 /iteration-start/iteration-drive/iteration-loop/codebase-audit(来自打包的 harness-commands/ 镜像;每条声明 frontmatter input hint,使 web 客户端 claim /name 并等待用户后续输入而非立即执行;handler 把命令正文 + 用户输入 steer 进接收 agent)。
  • pre-step catalog 行——每个组合后的 agent 步骤都会追加一条统一的 mstar-engine-status catalog 消息:水印(统一 mstar 版本、harness 目录、enforcement)、迭代相位闸门段(解析到 steering compass 时)与工作区状态摘要段(工作区有 status.json 时:plan 注册表、open residual、分支/政策锚点、活跃 lease、知识摘要、compass 方向)。该行是 digest 门控的(每 turn 注入一次、变化时才重发),并共享一次按工作区 TTL 缓存的构建(catalogTtlMs,默认 60 秒)。

Enforcement semantics

默认仅告警:闸门违规记录日志并发出咨询事件(mstar/status-gatemstar/dispatch-gatemstar/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——形状守卫、validateAssignmentFieldsantiRecursionPrecheck、默认分支闸门、头区域强制执行;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 与派发上下文比对(holderworktree_pathworking_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 分支之前)把关 workflowralph 工具调用——这是剩余的不携带 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 的记录路径,完全含容——账本写入失败绝不波及闸门):toolworkflow | ralph)、workflow(归一化后的 meta.name)或 objectivemode(绝不为 off——off 在策略前短路)、判定词汇 ok / advisory / denied / askask 判定是本次扩展:首见 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-runallow 按运行名缓存进 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-seed gateway / fallbacks 设置卡片回滚按钮——操作者覆盖在 revert 前保留);
  • 空 persona——persona 缺失/空白的行,仅限非 seeded 或 overridden-empty(一条告警点名);
  • 遗留键——chainsroles.defaultroles.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 支撑:validateStatusvalidateResidualfindingsCleanupGateresolveCompassEnforcementresolveHarnessDirreadHarnessVersionapplyEnforcement)。分层: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.commandsharness-commands/*.md——仓库根 commands/ 镜像(iteration-startiteration-driveiteration-loopcodebase-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-executePreToolDecision.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 时):plansid(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 | runIdnameagent?(承载的父会话 id) | | agent-start | workflow-agent | runIdseq(1 起始的成员序号)、labelphase?childId | | run-end | workflow-run-end | runIdstopReasoncompleted / 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 闸门(而非本消费者)写入——每个被把关的调用一行(toolworkflow/objectivemode、判定 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 行(窗口内该 runIdworkflow-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 组标签标注当前 plandata-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% 真正解析、.rowListoverflow-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 框),产出纯数据 ZoneViewWorkflowCanvas 以纯 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 注入,经典脚本语义)——见 panel-beautify 迭代的 install-verification.md guide(本地 harness root)。

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——会话中途 activelocked 翻转后最多落后一个 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-toolsdefineTool)、@deepseek-ai/dsh-llm——保持外部,外加仅类型导入的 dsh-llm-fallbacks),运行 build-clientscripts/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.1 devDependency,构建时打入 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 安装到 web profile: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)已导出并测试覆盖,但尚无生产调用方:engine HostAdapter 没有携带内容的技能写入钩子(只有 beforeStatusWrite/beforeDispatch/beforeMerge),且 fs intent 槽位内容盲。接线随未来携带内容的钩子落地;在此之前监听器路径只通过修复逃生咨询执行(从不否决)。
  • CLI HOST_SIGNALS 缺少 subagent token——engine ToolSignal 联合已包含它且 detectHost 能处理,但 packages/cliHOST_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:testsbunx tsc --noEmit -p tests/tsconfig.json)下的值命名空间恒等与逐名类型探测。
  • engine dsh 行待上游化——engine host.ts 的 dsh 改动(DetectResultToolSignalresolveSkillRoot)位于 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 为 registry dependencies 条目且仅类型导入——caret 范围写在 package.json(探测形状断言测试是可执行的漂移闸门)并在构建中 --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)。