Skip to content

Releases: Frac0103/dsh-goal-steward

v0.2.0-alpha.9

v0.2.0-alpha.9 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Oct 14:00

[0.2.0-alpha.9] - 2026-10-18

Added

  • L4 实机验证(真实宿主 + 真实模型):用 headless profile 安装发布 tarball,真实 deepseek-official/deepseek-flash 完成一次完整审计闭环(真实加载路径、路由继承、证据包、解析、审计落盘、默认沉默),延迟约 1.4 s。记录见 docs/verification/l4-headless-dogfood.md(含审计原文与复现步骤)。
  • 发布流水线 .github/workflows/release.yml:推送 v* tag → npm pack → 从 CHANGELOG 生成 release notes → 上传 dsh-goal-steward.tgz 资产。v0.2.0-alpha.8 的资产已补传并验证可下载。
  • 文档链接门禁 scripts/check-docs.mjs:9 个 markdown 文件的相对链接与锚点(含生成文档的显式 <a id> 锚点)全部校验,纳入 npm run verify 与 CI。
  • scripts/release-notes.mjs:从 CHANGELOG 提取某个 tag 的发布说明。
  • README 徽章;Desktop / CLI / 手工三种安装路径按真实 CLI 语法重写(Desktop profile 由桌面进程管理,npm CLI 会拒绝操作,需用桌面插件管理器)。

Changed

  • 安装文档不再使用 releases/latest 链接(GitHub 的 latest 会排除 prerelease);改为显式 tag URL。
  • npm run verify = 语法检查 + 文档链接门禁 + 全部测试。

Verified

  • 197 个测试全绿;覆盖率 line 99.62% / branch 91.69% / function 100%(Node 24)。
  • 发布 tarball 通过 dsh plugin --profile <scratch> add file:...tgz 安装并从真实 Host 启动成功。

v0.2.0-alpha.8 — 用户主权:/steward 命令通道

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 13:46

用户主权:/steward 命令通道

否决权不等于主权。评审员改写最终目标必须逐字引用用户原话,但用户自己此前没有一个直接写目标的入口。这一版补上了这个人机通道。

新增

  • /steward 命令面(宿主存在 commands 服务时自动安装;UI-less 宿主自动缺席):
    • /steward / /steward status:最终目标 / 当前目标 / 成功判据 / 硬约束 / revision / 评审与发声次数 / 最近发现 / 审计文件位置;
    • /steward goal <新目标>:用户直接设定最终目标(revision +1、当前目标同步重置),写入 event:"command"、trigger:"principal-command" 审计记录;
    • /steward why:最近 5 条评审结论。
  • 命令由宿主直接执行,不产生模型消息:执行者无法插话、评审员看不到请求;recordInput:false、永不抛错、迟到绑定、卸载即注销。
  • 覆盖率门禁:Node 22/24 CI lane 用 line 99 / branch 90 / function 99 阈值跑测试;新增 npm run test:coverage。
  • 防御性路径测试层(12 条):抛错的会话表面、stream 终态、severity 3 steer 形状等。
  • 理论登记新增机制 principal-command-channel(委托—代理 + RACI + 变更控制)。
  • 设计文档 §5.5「用户主权:给委托人一个直接入口」;架构文档 §12「命令面」。

测试

  • 197 个测试全绿(纯函数/契约 122 + 对抗性 30 + 假上下文 37 + 真实组装 8)。
  • 覆盖率:99.62% line / 91.39% branch / 100% function。
  • 真实组装层使用生产 CommandsRuntime:命令改写账本 → 下一次真实评审以该目标为准 → 命令行与结果都不进入任何模型请求 → 卸载插件后命令不再解析。

Full Changelog: v0.2.0-alpha.7...v0.2.0-alpha.8

v0.2.0-alpha.7 — 换届不换账(审计流水回放继承)

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 13:32

换届不换账:审计流水作为机构记忆

重载或重启后的新评审员,此前会把宪章重新锚定到会话开场指令——用户中途做过的合法重定向会悄悄回滚,工作被拿旧目标审判。这一版把审计流水变成继承档案。

新增

  • 账本与历史结论跨实例继承:新实例在会话第一次审计前回放本会话的审计记录,取最后一份非空账本快照 + 最近 5 条历史结论。
  • 审计快照升级为完整目标对象:goals.final / goals.current 现在包含目标、成功判据、约束与非目标;回放同时兼容旧格式(只有 finalGoal / currentGoal 字符串)的记录,升级不丢历史。
  • 继承是部分的:账本与历史结论继承,reviews / steers / lastReviewTurn 不继承——账本是机构档案,预算是一个任期的运营额度,新任期重新建立节奏。
  • 回放全程 fail-open:文件缺失、坏行、旧格式都不会让治理挂掉;audit: false 时无从回放,行为退回按开场指令重新锚定。
  • 理论登记新增机制 ledger-inheritance(契约理论 + 审计独立性 + 委托—代理)。
  • 设计文档新增 §5.4「换届不换账」;架构文档新增 §11.1「回放」。

测试

  • 145 个测试全绿(纯函数/契约 84 + 对抗性 30 + 假上下文 24 + 真实组装 7)。
  • 新增 12 条:test/restore.test.mjs 10 条回放契约、假上下文 2 条(重载继承、审计关闭时重新锚定)、真实组装 1 条(真实注册表下账本继承)。

注意

  • 审计 schema 变更:goals.finalGoal / goals.currentGoal 被完整对象 goals.final / goals.current 取代。消费审计流水的脚本需要同步;插件自身的回放两种格式都认。

Full Changelog: v0.2.0-alpha.6...v0.2.0-alpha.7

v0.2.0-alpha.6 — 任免与交接(生命周期安全)

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 13:28

任免与交接:治理实例的生命周期

宿主会热重载、禁用、关机,重复的 bundle 配置还可能挂载两次。从这一版起,这些被当作治理语义实现,而不是部署细节。

新增

  • 退役的评审员不再发声:卸载时先置 disposed 门禁、abort() 在飞评审调用,再移除 agent/turn-stopping / agent/disposed 监听器与治理提示词段;卸载后到达的裁决不 steer、不写审计。
  • 重复挂载被拒绝:提示词段名即单例锁,第二个实例 fail-open 放弃安装(记 installation skipped),不会出现双评审。
  • 重载即新任期:卸载后可重新挂载,协议与回合边界评审都恢复,会话状态从头建立。
  • 安装期异常 fail-open:安装失败只记 warn,不阻断宿主。
  • 理论登记新增机制 lifecycle-revocation(委托—代理 + RACI + 三道防线),docs/theory.md 重新生成。
  • 设计文档新增 §5.3「任免与交接:治理角色也有任期」,架构文档新增 §11「生命周期」。

测试

  • 133 个测试全绿(纯函数/契约 74 + 对抗性 30 + 假上下文 23 + 真实组装 6)。
  • 新增 9 条生命周期用例:
    • L2 test/mock/lifecycle.test.mjs(6 条):销毁清理、重复挂载拒绝 + 卸载后重装、安装失败 fail-open、卸载中止在飞调用并丢弃裁决、重载后重新治理、agent 销毁后节奏状态清零。
    • L3 test/compose/lifecycle.compose.test.mjs(3 条):真实注册表下的卸载/重载、真实双挂载只审一次、真实在飞退役(无 plugin 消息、无审计记录)。

Full Changelog: v0.2.0-alpha.5...v0.2.0-alpha.6

v0.2.0-alpha.5 - redirect quote source + audit schema lock

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 13:16

A redirect must quote the principal after the opening mandate

The corroboration gate accepted any principal text, including the opening mandate itself. That is logically impossible as evidence of a change: the mandate is exactly what the stable layer was derived from.

Changes

  • the quote sources now exclude the opening mandate (lib/reviewer.js)
  • the reviewer contract states the quote must come from a later principal message (lib/prompt.js)
  • four new mock-host tests:
    1. a redirect quoting only the opening mandate is guarded and the ledger does not move;
    2. a redirect quoting a later principal message is applied (revision +1, final goal updated);
    3. the audit record schema is locked - field additions/removals fail the suite;
    4. an unwritable audit trail is fail-open - review and steering still work, the turn never breaks.

124 tests (74 unit/contract + 30 redteam + 17 mock-host + 3 real-composition), CI green on Node 20/22/24.

v0.2.0-alpha.4 - redteam tier + redirect corroboration gate

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 13:06

Adversarial testing found a real hole

A model reviewer reads an evidence pack that the executor partially controls. Nothing mechanically prevented it from rewriting the final goal - even though change control says only the principal may do that. A prompt-injected instruction inside the executor's own output could therefore move the stable layer.

The fix: a verbatim-quote gate

redirected (a final-goal rewrite) now requires the reviewer's rationale to quote the principal verbatim - at least 12 normalised characters matched against principal messages only. Executor output, tool results and forged plugin messages can never corroborate a redirect.

  • guard runs before the ledger is touched
  • a failed guard never applies the rewrite, never steers, and audits outcome: "guarded" with reason: "redirect-not-corroborated"
  • the reviewer contract now demands the quote explicitly

Red-team tier (30 tests)

suite attacks
contract attacks severity downgrade/upgrade, drift without taxonomy/evidence/steer, spoofed silent substitution, oversized fields, control-character injection
evidence injection JSON breakout payloads, forged plugin-source audit messages, 200 KB tool arguments, audit-line injection
structural boundary no tools / no network / no subprocess, only audit.js writes files, guard before apply, exactly one agent.steer() call site

Plus one real-composition red line: in a real turn, a forged redirect is guarded, the final goal does not move, and nothing is steered.

Also

  • clampText strips C0/C1 control characters, so model output cannot inject newlines into the audit JSONL or control bytes into a steering message.
  • theory registry gains redirect-corroboration (change control, principal-agent, contract theory); theory doc regenerated (22 mechanisms).
  • 120 tests (74 unit + 30 redteam + 13 mock-host + 3 real-composition).
  • Node 20 CI lane skips the real-composition tier (host services need Node >= 22 Promise.withResolvers); the plugin keeps engines.node >= 20.

Honest limit

Mechanical defenses cannot stop a reviewer model from misjudging (for example a false drift). That is model quality, measured by live data and future real-model certification - not by tests pretending otherwise.

v0.2.0-alpha.3 - real-composition test tier

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 10:12

The real-composition test tier

The official testing policy requires a non-unit REAL-composition test for product-visible plugins. This release adds it: instead of a hand-built fake ctx, the test mounts the real host services and drives a real agent turn. Only the model boundary is scripted.

What is mounted

LlmRuntime -> SessionStore -> SessionProjectionRegistry -> SystemPrompt -> ToolRuntime -> AgentRegistry -> AgentLoop

A real Agent is created, a real user message starts a real turn, and agent/turn-stopping really fires.

What is scripted

Exactly one thing: the llm/stream waterfall. Reviewer requests (options.system starting with the reviewer policy) return a scripted verdict; executor requests (isAgentLoopRequest) return scripted text. Adapter selection happens inside next(), so no adapter, no API key and no network are needed.

What is asserted end to end

  1. the standing governance protocol reaches the assembled model request;
  2. turn-stopping fires on a production turn and the reviewer call leaves through ctx.llm.stream with the session route;
  3. the evidence pack carries the two-level goal ledger anchored to the opening mandate;
  4. the audit JSONL really lands on disk with the new schema (goalChange / goals / parseSource);
  5. a drift verdict travels through agent.steer() into the session log and into the executor's next real model request - the complete correction loop.

Findings recorded along the way

  • @deepseek-ai/dsh-agent-loop-testkit@0.2.0-rc.2 is unusable for third parties: it statically imports @deepseek-ai/dsh-working-directory, which has no 0.2.0-rc.2 publication and is not declared by the package. The same topology is inlined in test-support/compose-mount.mjs with attribution.
  • npm ci must not pass --legacy-peer-deps: the real service packages arrive as peer dependencies.
  • Node's test discovery executes every file under test/, so helpers live in test-support/.

89 tests passing (77 unit + 10 mock-host + 2 real-composition). CI runs this tier on Node 20/22/24. Documentation: docs/testing.md.

v0.2.0-alpha.2 - reasoning-only reviewer reply fallback

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 09:13

Robustness fix from live dogfooding

The audit trail recorded a real failure in the running app:

outcome: error
reason: call-failed: reviewer produced no text
elapsedMs: 5183

A reasoning model can spend its entire output budget on the reasoning block and never emit a text block, so the verdict was lost even though the auditor had done the work.

Fixed

  • maxReviewTokens default 900 -> 2000
  • streamReviewerText() now returns the text block and the reasoning block separately
  • when the text block yields no verdict, the reasoning block is parsed as a fallback
  • the audit trail records parseSource: "text" | "reasoning"
  • 1 regression test (87 tests total)

Deployment note

The desktop profile mounts this package as a live link to the source checkout. Node's ESM cache keeps the previously loaded module for the process lifetime, so the host application must be restarted once to run v0.2 code.

v0.2.0-alpha.10

v0.2.0-alpha.10 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Oct 14:04

[0.2.0-alpha.10] - 2026-10-18

Fixed

  • release workflow 上传的资产名带版本号(dsh-goal-steward-0.2.0-alpha.N.tgz),导致 README 中版本无关的安装 URL(.../releases/download/<tag>/dsh-goal-steward.tgz)404。workflow 现在固定以 dsh-goal-steward.tgz 上传;alpha.9 的资产已回填为稳定名并验证下载。
  • 安装文档中的 releases/latest(GitHub 会排除 prerelease)改为显式 tag URL。

Verified

  • 发布资产安装路径端到端验证:全新 headless profile 执行 dsh plugin --profile <name> add <release URL> → 资产下载安装、dsh.profile.bundles 自动追加、composed config 出现 dsh-goal-steward 行。记录见 docs/verification/l4-headless-dogfood.md 附录。

v0.2.0-alpha.1 - two-level goal ledger (final vs current goal)

Choose a tag to compare

@Frac0103 Frac0103 released this 18 Oct 09:05

Distinguish and adjust the two goals

A single "goal" conflates two control objects. Version 0.2 separates them:

Level Source of truth Change rule
Final goal principal's terminal objective only an explicit principal redirect changes it, and the redirect must quote the principal's words
Current goal objective of the phase in flight it is supposed to move as phases complete, are refined, or are redirected - and every legitimate move is recorded

Change classification

Every audit classifies what it observed:

  • none - work serves the recorded goals; ledger untouched
  • refined - the current goal was clarified or narrowed; final goal unchanged
  • phase_advance - the current goal was achieved; work legitimately moved to the next phase
  • redirected - the principal explicitly replaced the final goal; ledger rewritten
  • silent_substitution - the executor quietly swapped the objective, or the current goal stopped serving the final goal: drift, steered back, and the ledger is never rewritten

This makes "adjust the goal from the conversation" and "prevent goal drift" no longer contradictory: evolution is allowed and recorded; substitution is detected and rejected.

Mechanics

  • lib/goals.js: ledger normalization, classification, revision + capped history
  • reviewer contract gains goal_update (replaces the old charter field)
  • evidence pack gains goal_ledger; steering messages restate both goal levels
  • audit trail gains goalChange / goalApplied / goalRationale / goals{revision,lastChange,finalGoal,currentGoal}
  • 3 new theory-registered mechanisms (MBO objectives hierarchy, mission command, change control); theory doc regenerated
  • 86 tests passing (+21)