@mstar-harness/dsh 3.7.2 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # Blob hashes (git hash-object) of each side as of the last confirmation that
3
3
  # both languages say the same thing (dsh i18n contract: a pair is three
4
4
  # sibling files; editing either side obligates re-confirming and re-recording).
5
- README.md: 189bec515fe5fce73de5afad7e2d1678e0f55ea5
6
- README.zh.md: 05affb493e99da9b45d0b8dd2743ccedaecc0b11
5
+ README.md: 5d6f594ff5a64d84c2e5900d3118f744351cf32b
6
+ README.zh.md: 054b5415b2fa53e5bfae1e78d22e3a9625886b4a
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  English | [中文](README.zh.md)
4
4
 
5
- ![dsh](https://img.shields.io/badge/dsh-0.1.2--rc.1-4B32C3.svg)
5
+ ![dsh](https://img.shields.io/badge/dsh-0.1.5--rc.1-4B32C3.svg)
6
6
 
7
7
  [Morning Star](https://github.com/btspoony/mstar-harness) as a first-class dsh (DeepSeek Harness) host — a cordis function plugin that mounts the mstar engine in-process, implements the engine `HostAdapter` (`host: 'dsh'`), guards `{HARNESS_DIR}/status.json` writes (validate + advisory; repair-escape under hard), blocks disallowed subagent dispatches when `Enforcement: hard` is on, lints `SKILL.md` writes under the mounted skill roots, mounts the mstar `skills/` mirror through the dsh skill-filesystem provider (single canonical mount), and appends a durable `mstar-engine-status` catalog row to every composed agent step. Boot with a dsh Loader app; everything acts through the seam's refusal/advisory channels, never by patching the tools.
8
8
 
@@ -233,7 +233,7 @@ Every engine module attaches to a dsh surface — delivered except the lint modu
233
233
  | host (resolveSkillRoot, HostAdapter) | engine host.ts detection row + plugin adapter (`host: 'dsh'`) | delivered (P2) |
234
234
  | skill-authoring (lintFrontmatter, lintFiveQuestion) | skill-filesystem roots + `fs/write-intent` on SKILL.md | delivered (P2) |
235
235
  | lint (lintSkillFrontmatter, planQualityBar, assertSddTddTriple) | not wired — plan/tdd fs gates are a deferral; `lintSkillFrontmatter` runs only in the skills-mount test suite | deferred |
236
- | agent catalog | MessageSourceMap `mstar-engine-status` (model-visible ⟺ logged) | delivered (P2) |
236
+ | agent catalog | first-party `plugin` catalog source (the anchor) + `/api/mstar/engineStatus` snapshot read (model-visible ⟺ logged) | delivered (P2) |
237
237
  | sdd (sddWorkspace, taskBrief) | `defineTool` wrappers registered on `ctx.tools` | delivered (P3) |
238
238
  | iteration (evaluatePhaseGate, parseCompassFrontmatter) | `agent/pre-step` + iteration gate | delivered (P3) |
239
239
  | worktree (l1PreDispatchCheck, l2PreDispatchCheck) | `tools/pre-execute` L1/L2 (inside the dispatch gate) | delivered (P3) |
@@ -241,7 +241,7 @@ Every engine module attaches to a dsh surface — delivered except the lint modu
241
241
 
242
242
  ## Engine-status catalog
243
243
 
244
- An advisory `agent/pre-step` waterfall listener appends ONE **`mstar-engine-status`** catalog MessageSource to every composed step (the `kind`/`form: 'catalog'` contract, mirroring the dsh tool-skill precedent): the model-visible `<mstar_engine_status>` block renders the watermark fields — **mstar version** (plugin own manifest; the single-version invariant pins the bundled engine to the same version), **harness dir** (resolved `{HARNESS_DIR}`, `none` when absent), and **enforcement** (compass mode, `soft` / `hard (compass)`) — plus the **iteration phase-gate section** (when a steering compass + `status.json` resolve: iteration id, transition, all-plans-done, gate verdict + violation codes — the `mstar iteration gate` tool result shape) and the **workspace-state digest section** (when the workspace has a `status.json`): **plans** (`id(status)` registry), **residuals** (open counts by severity), **branch** (base → target, spec integration), **policy** (push policy, worktree mode, control root), **leases** (active plan execution leases: holder + worktree), **knowledge** (knowledge-index doc count + categories) and **direction** (the steering compass's problem-statement one-liner). The listener calls `next()` first and builds on the delegated decision — it never vetoes a step and never replaces the composed messages. Model-visible ⟺ logged: the durable `catalog`-form source records the facts it published beside the model-facing prose, so the session log reconstructs the row without re-parsing the block (dsh packages/AGENTS.md). Fiber disposal removes the listener (HMR-safe).
244
+ An advisory `agent/pre-step` waterfall listener appends ONE **`mstar-engine-status`** catalog MessageSource to every composed step — the first-party `plugin` arm, exactly `{ kind: 'plugin', plugin: 'mstar-engine-status', form: 'catalog' }` and **no other member** (mirroring the dsh tool-skill precedent): the model-visible `<mstar_engine_status>` block renders the watermark fields — **mstar version** (plugin own manifest; the single-version invariant pins the bundled engine to the same version), **harness dir** (resolved `{HARNESS_DIR}`, `none` when absent), and **enforcement** (compass mode, `soft` / `hard (compass)`) — plus the **iteration phase-gate section** (when a steering compass + `status.json` resolve: iteration id, transition, all-plans-done, gate verdict + violation codes — the `mstar iteration gate` tool result shape) and the **workspace-state digest section** (when the workspace has a `status.json`): **plans** (`id(status)` registry), **residuals** (open counts by severity), **branch** (base → target, spec integration), **policy** (push policy, worktree mode, control root), **leases** (active plan execution leases: holder + worktree), **knowledge** (knowledge-index doc count + categories) and **direction** (the steering compass's problem-statement one-liner). The listener calls `next()` first and builds on the delegated decision — it never vetoes a step and never replaces the composed messages. Model-visible ⟺ logged: the persisted source carries no facts — the row is the durable **anchor** and the exact emitted payload is snapshotted per session at `{HARNESS_DIR}/snapshots/engine-status.json` in this same digest-gated emission, so the session log plus that store reconstruct the row without re-parsing the block (dsh packages/AGENTS.md). No released session-format edge admits extra members on a message source, so nothing but the `plugin` arm is ever written there. The workflow panel reads that snapshot on demand over the host's shared `/api` typert gateway: the **host gateway owns the route** (a plugin cannot register one; a plain `connection.rpc.handle` channel mounts through `webServer` on the calling fiber and would pend this row's boot — the mechanism this package deliberately does not use) and this package contributes the `mstar/engineStatus` endpoint descriptor through an optional `ctx.typert.register(...)` child. The browser half calls `connection.rpc.call('/api', 'mstar/engineStatus', { args: { sessionId, cwd } })` and receives that session's stored snapshot, or an explicit `unavailable` reason (never another session's data, never silently-empty fields). **Trust boundary, stated plainly:** the endpoint authenticates nothing of its own — the transport fence (host/origin + browser auth) establishes only that the caller is a page this host served, so *possession of a `(sessionId, cwd)` pair plus reachability of the local `/api` gateway is the capability*. An answer is scoped to the REQUEST: the lookup is keyed by the asserted id, the stored record's `cwd` must equal both the asserted and the server-resolved session `cwd`, and the client re-checks the echoed id and workspace before rendering — so one session's request can never be served another session's row. The payload is a workspace digest (version, harness dir, enforcement, plan/residual/lease counters) that the panel's own session transcript already exposes; it is not treated as a secret, and the distinct `unavailable` reasons make the endpoint a weak session-existence oracle for a caller who already holds the id. Fiber disposal removes the listener (HMR-safe).
245
245
 
246
246
  The row is **digest-gated**: per agent+workspace it is injected once per turn and re-injected only when its rendered text changed — a 20-step turn shows the catalog once, not 20 times. The source shares ONE per-workspace cache entry, built at boot for an explicit `harnessDir` (else on the workspace's first pre-step) and TTL-refreshed (`catalogTtlMs`, default 60 s) — the hot path is a timestamp compare + Map lookup between refreshes, and a mid-session plan/compass/residual change lands within one interval.
247
247
 
package/README.zh.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [English](README.md) | 中文
4
4
 
5
- ![dsh](https://img.shields.io/badge/dsh-0.1.2--rc.1-4B32C3.svg)
5
+ ![dsh](https://img.shields.io/badge/dsh-0.1.5--rc.1-4B32C3.svg)
6
6
 
7
7
  让 [Morning Star](https://github.com/btspoony/mstar-harness) 成为一等公民的 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 的拒绝/咨询通道行使职责,从不改动工具本身。
8
8
 
@@ -232,7 +232,7 @@ mstar 技能通过 dsh skill-filesystem 提供者以**单一规范挂载**接入
232
232
  | host(resolveSkillRoot、HostAdapter) | engine host.ts 检测行 + 插件适配器(`host: 'dsh'`) | 已交付(P2) |
233
233
  | skill-authoring(lintFrontmatter、lintFiveQuestion) | skill-filesystem 根 + 对 SKILL.md 的 `fs/write-intent` | 已交付(P2) |
234
234
  | lint(lintSkillFrontmatter、planQualityBar、assertSddTddTriple) | 未接线——plan/tdd 的 fs 闸门为延后项;`lintSkillFrontmatter` 仅运行于 skills-mount 测试套件 | 延后 |
235
- | agent catalog | MessageSourceMap `mstar-engine-status`(模型可见 ⟺ 已记录) | 已交付(P2) |
235
+ | agent catalog | 一方 `plugin` catalog source(锚点)+ `/api/mstar/engineStatus` 快照读取(模型可见 ⟺ 已记录) | 已交付(P2) |
236
236
  | sdd(sddWorkspace、taskBrief) | 注册在 `ctx.tools` 上的 `defineTool` 包装 | 已交付(P3) |
237
237
  | iteration(evaluatePhaseGate、parseCompassFrontmatter) | `agent/pre-step` + iteration 闸门 | 已交付(P3) |
238
238
  | worktree(l1PreDispatchCheck、l2PreDispatchCheck) | `tools/pre-execute` L1/L2(派发闸门内) | 已交付(P3) |
@@ -240,7 +240,7 @@ mstar 技能通过 dsh skill-filesystem 提供者以**单一规范挂载**接入
240
240
 
241
241
  ## Engine-status catalog
242
242
 
243
- 一个咨询式 `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 安全)。
243
+ 一个咨询式 `agent/pre-step` 瀑布监听器向每个组合后的步骤追加**一条** **`mstar-engine-status`** catalog MessageSource——一方 `plugin` 臂,即恰好 `{ kind: 'plugin', plugin: 'mstar-engine-status', 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()` 并基于委托后的决策追加——从不否决步骤、从不替换已组合的消息。模型可见 ⟺ 已记录:持久化的 source 不携带任何事实——该行是持久化的**锚点**,其**实际发出**的 payload 在同一次 digest 门控发射时按会话快照到 `{HARNESS_DIR}/snapshots/engine-status.json`,因此「会话日志 + 该存储」无需重新解析该块即可重建该行(dsh packages/AGENTS.md)。任何已发布的会话格式边界都不接受 message source 上的多余成员,故 `source` 上永远只写 `plugin` 臂。工作流面板通过宿主共享的 `/api` typert 网关按需读取该快照:**路由由宿主网关持有**(插件无法注册路由;`connection.rpc.handle` 的普通信道会经由调用 fiber 上的 `webServer` 挂载、并使本行的 boot 挂起——本包刻意不走该机制),本包只经可选 `ctx.typert.register(...)` 子单元贡献 `mstar/engineStatus` 端点描述符。浏览器半体调用 `connection.rpc.call('/api', 'mstar/engineStatus', { args: { sessionId, cwd } })`,得到该会话自己的已存快照,或带原因的显式 `unavailable`(绝不返回其它会话的数据、绝不静默空字段)。**信任边界,如实说明:**该端点自身不做任何鉴权——传输层围栏(host/origin + 浏览器鉴权)只证明调用方是本宿主自己服务的页面,因此*持有 `(sessionId, cwd)` 组合 + 能访问本机 `/api` 网关即为能力*。应答按**请求**限定:查询以被断言的 id 为键,存储记录的 `cwd` 必须同时等于断言值与服务端解析出的会话 `cwd`,客户端在渲染前还会复核回显的 id 与工作区——因此一个会话的请求绝不会被返回另一个会话的记录。payload 是工作区摘要(版本、harness 目录、enforcement、plan/residual/lease 计数),面板自身的会话记录本就暴露这些信息;它不被当作机密,而不同的 `unavailable` 原因会让该端点对已持有 id 的调用方成为一个弱的「会话是否存在」探针。fiber 销毁即移除监听器(HMR 安全)。
244
244
 
245
245
  该行是 **digest 门控**的:按 agent+workspace,每个 turn 只注入一次,仅当渲染文本变化时重新注入——20 步的 turn 只显示一次 catalog,而不是 20 次。source 共享**同一**按工作区缓存条目:显式 `harnessDir` 时在 boot 构建(否则在工作区首次 pre-step 构建),并按 TTL 刷新(`catalogTtlMs`,默认 60 秒)——刷新间隔之间热路径只是时间戳比较 + Map 命中,会话中 plan/compass/residual 的变化在一个间隔内落地。
246
246
 
package/bundle/README.md CHANGED
@@ -99,7 +99,14 @@ boot the web app serves the closure-factory CJS bundle at
99
99
 
100
100
  The client entry registers a `conversation.view` view-ring tab
101
101
  (`id: 'mstar-workflow'`, `order: 20`), labeled **"MStar 工作流" / "MStar
102
- Workflow"**, rendering the latest `mstar-engine-status` catalog row as the
102
+ Workflow"**, rendering the latest `mstar-engine-status` catalog **anchor** row
103
+ — the persisted source is the bare first-party `plugin` arm
104
+ (`{ kind: 'plugin', plugin: 'mstar-engine-status', form: 'catalog' }`), and the
105
+ payload is fetched from the host's `/api/mstar/engineStatus` endpoint (the
106
+ shared `/api` typert gateway owns the route; the panel's browser half calls
107
+ `connection.rpc.call('/api', 'mstar/engineStatus', { args: { sessionId, cwd } })`
108
+ and renders the session's stored snapshot, or an explicit unavailable reason) —
109
+ as the
103
110
  **MStar Workflow layout**: a right sidebar (plans ≤5 time-desc + `+N more`,
104
111
  open residual findings ≤10 with severity chips + overflow hint, policy with
105
112
  enforcement first, leases, knowledge, direction) over a bottom **fixed meta
@@ -2,13 +2,19 @@
2
2
  * Morning Star workflow panel — dsh client plugin entry (spec §4.1):
3
3
  * `inject` (cordis service waits) + `apply(ctx: ClientContext)`.
4
4
  *
5
- * On apply: registers the `mstar-panel` dictionaries, then waits for the
6
- * ui-conversation `conversation.view` declaration and registers the panel as
7
- * a view tab (`id: 'mstar-workflow'`, `order: 20`, locale-following label
8
- * thunk — the trajectory precedent shape). The tab label re-reads through
9
- * `ctx.locale.bind(NS)` so a locale switch flips it without re-registering.
5
+ * On apply: creates the engine-status client over the client `connection`
6
+ * service (the panel's data path is the host's shared `/api` typert gateway —
7
+ * the persisted catalog row is only the anchor), registers the `mstar-panel`
8
+ * dictionaries, then waits for the ui-conversation `conversation.view`
9
+ * declaration and registers the panel as a view tab (`id: 'mstar-workflow'`,
10
+ * `order: 20`, locale-following label thunk — the trajectory precedent shape).
11
+ * The tab label re-reads through `ctx.locale.bind(NS)` so a locale switch
12
+ * flips it without re-registering.
13
+ *
14
+ * The client is created ONCE per apply and disposed with the fiber, so a
15
+ * reloaded plugin starts from a clean snapshot cache.
10
16
  */
11
17
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
12
- /** Cordis service faces the plugin waits for (spec §4.4: slots + sessions + locale). */
18
+ /** Cordis service faces the plugin waits for (spec §4.4: slots + sessions + locale + the wire). */
13
19
  export declare const inject: string[];
14
20
  export declare function apply(ctx: ClientContext): void;
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * Morning Star workflow panel page — the `conversation.view` tab component
3
- * (spec §4.2): pure render of the latest `mstar-engine-status` catalog row.
3
+ * (spec §4.2): render of the session's engine-status snapshot.
4
4
  *
5
- * Inputs: the session standard kit (`ConvViewProps`) and the typed `t` seat
6
- * (`locale: 'mstar-panel'`). The catalog row + message time come from the
7
- * `useMstarEngineStatus()` hook riding the kit's `useChat` selector (spec
8
- * §5) — the render body is a pure function of (source, lastUpdated, t).
5
+ * Inputs: the session standard kit (`ConvViewProps` + the session-list seat),
6
+ * the plugin's engine-status client (bound to the client `connection` service
7
+ * by the plugin entry) and the typed `t` seat (`locale: 'mstar-panel'`). The
8
+ * `useMstarEngineStatus()` hook turns the anchor row + the served snapshot
9
+ * into ONE explicit render state (spec §5) — the render body is a pure
10
+ * function of (state, payload, snapshot `at`, t).
9
11
  *
10
12
  * Layout (spec panel-tabs §2): root grid
11
13
  * `"main sidebar"` fills the Tab (height 100%, overflow hidden — the page
@@ -26,27 +28,47 @@
26
28
  * `<details>` expansion, replacing
27
29
  * the muted placeholder AND the AgentEventDock — 无双份日志).
28
30
  *
29
- * Empty branches (spec §2): waiting / no-harness render no tabs / no
30
- * sidebar. Waiting keeps the muted hint; the no-harness branch renders a
31
- * CENTERED inactive-state card (icon + title + hint, plan
32
- * T3 — replaces the left-aligned hint) with
33
- * the freshness footer; the no-harness main keeps `data-mstar-graph` on its
34
- * content container. Degradation stays total: `projectGraph` never throws;
35
- * no iteration → the IterationTaskPage's collapsed muted head (spec §8);
36
- * `state` null / plans missing → muted kanban skeleton.
31
+ * Empty branches (spec §2): waiting / loading / unavailable / no-harness render
32
+ * no tabs and no sidebar — each with its OWN anchor and copy, so a degraded
33
+ * read is never mistakable for an empty workspace. Waiting keeps the muted
34
+ * hint; loading states the pending read; unavailable carries the
35
+ * machine-readable reason; the no-harness branch renders a CENTERED
36
+ * inactive-state card (icon + title + hint) with the freshness footer, and its
37
+ * main keeps `data-mstar-graph` on the content container. Degradation stays
38
+ * total: `projectGraph` never throws; no iteration → the IterationTaskPage's
39
+ * collapsed muted head (spec §8); `state` null / plans missing → muted kanban
40
+ * skeleton.
37
41
  */
38
42
  import * as React from 'react';
39
43
  import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client';
40
44
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
41
- import type { MstarEngineStatusSource } from '../../types.ts';
45
+ import type { SessionId } from '@deepseek-ai/dsh-session';
46
+ import type { MstarEngineStatusPayload } from '../../types.ts';
47
+ import type { MstarEngineStatusClient } from './engine-status-client.ts';
42
48
  import { type PanelTab } from './TabNav.tsx';
49
+ import { type UseSessions } from './use-mstar-engine-status.ts';
43
50
  export interface MstarPanelViewProps extends ConvViewProps {
44
51
  /** Namespace-bound translate seat (`locale: 'mstar-panel'`). */
45
52
  t: TranslateNS<'mstar-panel'>;
53
+ /**
54
+ * Current session identity — the session standard kit's own prop. Declared
55
+ * here (rather than inherited) because this package does not depend on the
56
+ * ui-session adapter that merges the session-kit declarations into
57
+ * `ConvViewProps`; the view ring always supplies it at runtime.
58
+ */
59
+ sessionId?: SessionId;
60
+ /** Host session-list selector hook (the global standard seat, same reason). */
61
+ useSessions?: UseSessions;
62
+ /**
63
+ * The plugin's engine-status client (bound to the client `connection`
64
+ * service by the plugin entry). Absent only in a composition that injects
65
+ * no transport — the panel then reports the explicit `unavailable` state.
66
+ */
67
+ engineStatus?: MstarEngineStatusClient;
46
68
  }
47
69
  export interface PanelContentProps {
48
70
  tab: PanelTab;
49
- source: MstarEngineStatusSource;
71
+ source: MstarEngineStatusPayload;
50
72
  t: TranslateNS<'mstar-panel'>;
51
73
  }
52
74
  /**
@@ -61,4 +83,4 @@ export interface PanelContentProps {
61
83
  * AgentEventDock — 无双份日志, the dock is removed with this plan).
62
84
  */
63
85
  export declare function PanelContent({ tab, source, t }: PanelContentProps): React.JSX.Element;
64
- export declare function PanelView({ t, useChat }: MstarPanelViewProps): React.JSX.Element;
86
+ export declare function PanelView({ t, useChat, useSessions, sessionId, engineStatus }: MstarPanelViewProps): React.JSX.Element;
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Client half of the engine-status channel: the per-session snapshot cache the
3
+ * panel reads and the `/api/mstar/engineStatus` fetch that fills it.
4
+ *
5
+ * WHY a cache outside React: the panel is a browser bundle and the payload
6
+ * lives on the HOST filesystem (the persisted catalog row is only the anchor —
7
+ * its `source` is the frozen three-member first-party arm). The data therefore
8
+ * arrives over the host's shared typert `/api` gateway, asynchronously and
9
+ * repeatedly (every new anchor row asks again). Keeping that state in a small
10
+ * observable store — rather than component state — gives one request per
11
+ * (session, anchor) across re-renders, survives the panel unmounting, and lets
12
+ * the render path read it synchronously.
13
+ *
14
+ * KEYING, not adjacency: entries are keyed by session id, and a response is
15
+ * validated against the session that was REQUESTED
16
+ * ({@link parseEngineStatusResult}) — session A's panel can never render
17
+ * session B's snapshot.
18
+ *
19
+ * GENERATIONS: a new connection generation makes every wire-derived byte
20
+ * suspect, so `invalidate()` bumps a generation counter, drops the cache and
21
+ * clears the in-flight registry; a request answered after the bump is discarded
22
+ * on arrival ({@link MstarEngineStatusClient.write}) and the next render
23
+ * re-issues it. Without the fence an in-flight pre-reconnect answer would
24
+ * repopulate the cache and then suppress the repull the invalidation exists to
25
+ * force.
26
+ *
27
+ * DEADLINES: the gateway is a network hop, so one request is bounded
28
+ * ({@link MstarEngineStatusClientOptions.timeoutMs}) and a request that
29
+ * outlives its budget degrades to the explicit `unavailable('timeout:…')`
30
+ * reason instead of pinning `loading` for a whole turn. A served snapshot is
31
+ * likewise re-pulled on a modest interval
32
+ * ({@link MstarEngineStatusClientOptions.refreshIntervalMs}) — D3's "explicit
33
+ * refresh", never per agent-flow event. A refresh asks for the anchor it saw,
34
+ * so it never overwrites a newer anchor's answer ({@link
35
+ * MstarEngineStatusClient.write}).
36
+ *
37
+ * The store is written ONLY from a response continuation (never during a
38
+ * render), so reading it through `useSyncExternalStore` stays within React's
39
+ * snapshot contract.
40
+ *
41
+ * @module @mstar-harness/dsh/client/panel/engine-status-client
42
+ */
43
+ import type { ConnectionRpcResult } from '@deepseek-ai/dsh-client-connection/client';
44
+ import { ENGINE_STATUS_CHANNEL, ENGINE_STATUS_ENDPOINT } from '../../engine-status-wire.ts';
45
+ import { type MstarEngineStatusFetch } from './guards.ts';
46
+ export { ENGINE_STATUS_CHANNEL, ENGINE_STATUS_ENDPOINT };
47
+ /** Deadline for one `/api/mstar/engineStatus` request (a hanging gateway must not pin `loading`). */
48
+ export declare const ENGINE_STATUS_REQUEST_TIMEOUT_MS = 5000;
49
+ /** How often a served snapshot is re-pulled (D3's "explicit refresh", modest interval). */
50
+ export declare const ENGINE_STATUS_REFRESH_INTERVAL_MS = 30000;
51
+ /**
52
+ * Structural face of the client `connection` service the panel needs — the
53
+ * generic RPC caller of the shared gateway. Declared structurally (not
54
+ * imported) so the bundle stays free of any runtime dependency on the
55
+ * transport package: the host injects `@deepseek-ai/dsh-client-connection`
56
+ * through the client manifest.
57
+ */
58
+ export interface MstarEngineStatusConnection {
59
+ readonly rpc: {
60
+ call(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise<ConnectionRpcResult<unknown>>;
61
+ };
62
+ /**
63
+ * Connection generations: a new generation means every wire-derived byte is
64
+ * suspect, so the cache is dropped and the panel repulls.
65
+ */
66
+ readonly generation?: {
67
+ subscribe(listener: () => void): () => void;
68
+ };
69
+ }
70
+ /** Optional timings (test seams; production uses the two constants above). */
71
+ export interface MstarEngineStatusClientOptions {
72
+ /** Per-request deadline in ms (`0` disables the bound). */
73
+ readonly timeoutMs?: number;
74
+ /** Refresh interval in ms (`0` disables the interval). */
75
+ readonly refreshIntervalMs?: number;
76
+ }
77
+ /** One session's cached answer, tagged with the anchor row it answers. */
78
+ export interface MstarEngineStatusEntry {
79
+ /** Message time of the anchor row this answer belongs to (staleness key). */
80
+ readonly anchorTime: number;
81
+ /** The workspace directory the answer was requested for (reused by a refresh). */
82
+ readonly cwd: string;
83
+ /** When the answer landed — the refresh clock (never the anchor row's time). */
84
+ readonly fetchedAt: number;
85
+ readonly fetch: MstarEngineStatusFetch;
86
+ }
87
+ /** The observable store value: at most one entry per session. */
88
+ export interface MstarEngineStatusSnapshot {
89
+ readonly entries: ReadonlyMap<string, MstarEngineStatusEntry>;
90
+ }
91
+ /**
92
+ * The panel's engine-status client: one `/api/mstar/engineStatus` request per
93
+ * (session, anchor row), cached per session and observable by React.
94
+ */
95
+ export declare class MstarEngineStatusClient {
96
+ private readonly connection;
97
+ private snapshot;
98
+ private readonly listeners;
99
+ private readonly inFlight;
100
+ private readonly abort;
101
+ /** Refreshes in flight, keyed by session (one per session, alongside the anchor requests). */
102
+ private readonly refreshing;
103
+ private readonly timeoutMs;
104
+ private readonly refreshIntervalMs;
105
+ private refreshTimer;
106
+ private generationDisposer;
107
+ /** Connection generation: bumped by {@link invalidate}; a mismatched answer is dropped. */
108
+ private generation;
109
+ private disposed;
110
+ /**
111
+ * @param connection - the client `connection` service, or undefined in a
112
+ * composition without one (the panel then reports `unavailable`).
113
+ * @param options - request deadline / refresh interval (test seams).
114
+ */
115
+ constructor(connection: MstarEngineStatusConnection | null | undefined, options?: MstarEngineStatusClientOptions);
116
+ /** Current store value (stable reference until a response lands). */
117
+ getSnapshot: () => MstarEngineStatusSnapshot;
118
+ /** Subscribe to store writes (`useSyncExternalStore` face). */
119
+ subscribe: (listener: () => void) => (() => void);
120
+ /**
121
+ * Ensure the session's snapshot for ONE anchor row is being fetched. Safe to
122
+ * call on every render: an entry that already answers this anchor, and a
123
+ * request already in flight for it, are both no-ops.
124
+ * @param sessionId - the session the panel is showing.
125
+ * @param cwd - the session's workspace directory (the host cross-checks it
126
+ * against the session and the stored snapshot; an unknown cwd is not
127
+ * asserted, the panel degrades explicitly instead).
128
+ * @param anchorTime - message time of the anchor row this request answers.
129
+ */
130
+ ensure(sessionId: string, cwd: string, anchorTime: number): void;
131
+ /**
132
+ * Drop every cached answer (a new connection generation invalidates the wire
133
+ * data) and fence off the requests already on the wire: their answers belong
134
+ * to the previous generation and must never repopulate the cache, or the
135
+ * repull this invalidation exists to force would be suppressed by them.
136
+ */
137
+ invalidate(): void;
138
+ /** Stop accepting writes, abort in-flight requests and end the refresh interval (plugin teardown). */
139
+ dispose(): void;
140
+ /**
141
+ * Re-pull every served snapshot on a modest interval: the host keeps emitting
142
+ * on each digest-gated `agent/pre-step`, and a panel left open on an idle
143
+ * session would otherwise never see a newer snapshot. Deliberately NOT tied to
144
+ * agent-flow events, and never in flight twice for one session.
145
+ */
146
+ private startRefreshTimer;
147
+ /**
148
+ * One refresh pass over the cache: every entry older than the refresh
149
+ * interval is re-pulled for the SAME anchor (the anchor only moves when the
150
+ * host appends a newer row, which already triggers its own request). Public
151
+ * as the interval's deterministic test seam; the interval calls it.
152
+ */
153
+ refresh(): void;
154
+ /**
155
+ * One request → one validated entry. Never throws: a fault, a missing
156
+ * connection and an exceeded deadline are all explicit reasons.
157
+ * @returns the answer (also published through {@link write} when the
158
+ * generation it was issued under is still current).
159
+ */
160
+ private fetch;
161
+ /**
162
+ * Bound one request: the request is aborted at the deadline and the caller
163
+ * gets the explicit timeout reason. A gateway that never answers must not pin
164
+ * `loading` (and with it the panel) for a whole turn.
165
+ */
166
+ private withDeadline;
167
+ /**
168
+ * Publish one answer (the only writer — always outside a render).
169
+ *
170
+ * An answer issued under a superseded connection generation is DROPPED: it
171
+ * describes the connection that is gone, and publishing it would both render
172
+ * pre-reconnect data as `ok` and suppress the repull `invalidate()` forces
173
+ * (the stale answer would satisfy `ensure`'s anchor check).
174
+ *
175
+ * An answer for a SUPERSEDED anchor is dropped for the same class of reason:
176
+ * a refresh issues its request for the anchor it saw, and a newer anchor row
177
+ * can be answered in the meantime, so publishing on arrival would overwrite a
178
+ * newer snapshot with an older one under a refreshed cache clock and no
179
+ * staleness marker. `ensure` already refuses an older anchor, which is why
180
+ * this only ever happens through {@link refresh}.
181
+ */
182
+ private write;
183
+ /** The store write itself (no generation test — see {@link write}). */
184
+ private writeEntry;
185
+ /** Notify subscribers, isolating a throwing listener. */
186
+ private notify;
187
+ }
@@ -74,7 +74,7 @@
74
74
  * with a transition past Phase 2 (an inconsistent harness state) degrades to the existing transition-driven current-step logic
75
75
  * (Step 2→4) — backward compatible, `active` semantics unchanged.
76
76
  */
77
- import type { MstarEngineStatusSource } from '../../../types.ts';
77
+ import type { MstarEngineStatusPayload } from '../../../types.ts';
78
78
  import { type AgentZone, type PhaseId, type PlanStateId } from './schema.ts';
79
79
  /** Current-step verdict from `gate.ok` (spec §3). */
80
80
  export type PhaseVerdict = 'pass' | 'fail' | 'unknown';
@@ -441,7 +441,7 @@ export interface ZoneView {
441
441
  plans: boolean;
442
442
  };
443
443
  }
444
- export declare function projectGraph(source: MstarEngineStatusSource | null): ZoneView;
444
+ export declare function projectGraph(source: MstarEngineStatusPayload | null): ZoneView;
445
445
  /**
446
446
  * `projectAgents(source, currentStep): AgentZoneView` — the agents zone (spec
447
447
  * §4 + §6.2). `currentStep` is the ITERATION's current step (1-based into
@@ -481,7 +481,7 @@ export declare function projectGraph(source: MstarEngineStatusSource | null): Zo
481
481
  * annotates the current plan; degraded/empty branches include the note too
482
482
  * (it is a state.plans annotation, independent of the ledger evidence).
483
483
  */
484
- export declare function projectAgents(source: MstarEngineStatusSource | null, currentStep: number | null): AgentZoneView;
484
+ export declare function projectAgents(source: MstarEngineStatusPayload | null, currentStep: number | null): AgentZoneView;
485
485
  /** One row of the pairing walk — the identity a PAIRED settle carries (spec R1: exact identity pairing,
486
486
  * never owner+time guessing). The kind is the FULL projected kind union:
487
487
  * workflow/unknown rows are walk no-ops (they carry no paired marker) —
@@ -525,7 +525,7 @@ export declare function pairSettleIndexes(rows: readonly PairingRow[]): Readonly
525
525
  * the server's empty view → present with 0 events → no events either (the
526
526
  * `agents` skeleton carries `empty`).
527
527
  */
528
- export declare function projectFlowEvents(source: MstarEngineStatusSource | null): {
528
+ export declare function projectFlowEvents(source: MstarEngineStatusPayload | null): {
529
529
  events: FlowEventView[];
530
530
  unexpected: FlowEventView[];
531
531
  };
@@ -1,12 +1,61 @@
1
1
  /**
2
- * Field-level degradation guards for the runtime `mstar-engine-status` source
2
+ * Field-level degradation guards for the runtime `mstar-engine-status` payload
3
3
  * (spec §2.4): the client does not exhaustively validate the union — it
4
- * narrows by `kind`, then degrades per field. Unknown/missing values render
5
- * as `unknown`, never as guessed values.
4
+ * narrows, then degrades per field. Unknown/missing values render as
5
+ * `unknown`, never as guessed values.
6
+ *
7
+ * This module ALSO carries the one place that validates untrusted input
8
+ * exhaustively: {@link parseEngineStatusResult}, which turns the
9
+ * `/api/mstar/engineStatus` wire envelope into the panel's explicit state. The
10
+ * payload is a remote answer the panel never authored, so a malformed
11
+ * envelope degrades to `unavailable` — never to a half-parsed view.
6
12
  */
13
+ import type { MstarEngineStatusPayload } from '../../types.ts';
7
14
  /** String field: non-empty string, else null (missing → `unknown`). */
8
15
  export declare function str(value: unknown): string | null;
9
16
  /** Boolean field: real boolean, else null. */
10
17
  export declare function bool(value: unknown): boolean | null;
11
18
  /** Count field: finite number, else null. */
12
19
  export declare function count(value: unknown): number | null;
20
+ /** Plain-object record (null and arrays are not records), else null. */
21
+ export declare function record(value: unknown): Record<string, unknown> | null;
22
+ /**
23
+ * The engine-status state the panel renders from: either the host's stored
24
+ * snapshot emission, or the explicit reason the snapshot is unavailable.
25
+ * There is deliberately no third "empty" shape — a degraded read is ALWAYS an
26
+ * `unavailable` carrying a reason, never a silently-empty payload.
27
+ */
28
+ export type MstarEngineStatusFetch = {
29
+ readonly status: 'ok';
30
+ /** The exact catalog payload the host stored for this session. */
31
+ readonly payload: MstarEngineStatusPayload;
32
+ /** ISO timestamp of the served snapshot — the panel's freshness marker. */
33
+ readonly at: string;
34
+ /** The agent turn the row was emitted for. */
35
+ readonly turn: number;
36
+ } | {
37
+ readonly status: 'unavailable';
38
+ readonly reason: string;
39
+ };
40
+ /**
41
+ * Validate one `/api/mstar/engineStatus` response into the panel's state.
42
+ *
43
+ * The whole envelope is untrusted: the transport result (`{ok, value}` /
44
+ * `{ok: false, error}`), the endpoint result (`status` + its fields) and the
45
+ * payload object. Every branch that cannot be read in full answers the
46
+ * explicit `unavailable` state with a machine-readable reason; the host's own
47
+ * `unavailable` reason is surfaced verbatim.
48
+ *
49
+ * @param raw - the value returned by `connection.rpc.call` (untrusted).
50
+ * @param sessionId - the session this client ASKED for; a response naming any
51
+ * other session is refused (`session-mismatch`) — one session's request can
52
+ * never render another session's data.
53
+ * @param cwd - the workspace this client ASSERTED in the same request; the host
54
+ * echoes the record's `cwd`, so a response naming another workspace is refused
55
+ * (`cwd-mismatch`) rather than rendered as this session's snapshot. The
56
+ * comparison is exact byte equality: the host matched the asserted string
57
+ * against its own record verbatim, so a normalising comparison here would
58
+ * accept a workspace the host itself refused.
59
+ * @returns the validated snapshot state, or the explicit unavailable state.
60
+ */
61
+ export declare function parseEngineStatusResult(raw: unknown, sessionId: string, cwd?: string): MstarEngineStatusFetch;
@@ -122,7 +122,7 @@ import type { LocaleDictOf } from '@deepseek-ai/dsh-client-ui-slots';
122
122
  /** Locale namespace id for the workflow-viz panel. */
123
123
  export declare const NS = "mstar-panel";
124
124
  /** Panel dictionary keys (union of every translatable string the panel renders). */
125
- export type PanelKey = 'view.mstar-workflow' | 'tab.tasks' | 'tab.agents' | 'tab.events' | 'page.iteration.not-started' | 'page.iteration.expand' | 'page.iteration.collapse' | 'event-log.section.events' | 'event-log.section.violations' | 'event-log.empty' | 'event-log.empty.events' | 'event-log.empty.violations' | 'event-log.field.role' | 'event-log.field.agent' | 'event-log.field.stage' | 'event-log.field.plan' | 'event-log.field.task' | 'event-log.field.category' | 'event-log.field.time' | 'event-log.field.kind' | 'event-log.field.status' | 'event-log.field.expected' | 'event-log.field.settled' | 'event-log.field.duration' | 'event-log.field.run-id' | 'event-log.field.name' | 'event-log.field.members' | 'event-log.field.stop-reason' | 'event-log.field.severity' | 'event-log.field.code' | 'event-log.field.message' | 'event-log.kind.dispatch' | 'event-log.kind.settle' | 'event-log.yes' | 'event-log.no' | 'empty.waiting' | 'empty.no-harness' | 'empty.no-harness-hint' | 'watermark.version' | 'watermark.harness' | 'watermark.none' | 'panel.unknown' | 'graph.pass' | 'graph.fail' | 'zone.legend.title' | 'zone.legend.agent-running' | 'zone.legend.agent-settled' | 'zone.legend.agent-idle' | 'zone.iteration.step-label' | 'zone.iteration.step-badge' | 'zone.iteration.step.current' | 'zone.iteration.step.next' | 'zone.iteration.step.done' | 'zone.iteration.step.idle' | 'zone.phase.iteration-start' | 'zone.phase.autonomous-execute' | 'zone.phase.iteration-close' | 'zone.phase.pr-delivery' | 'zone.phase.merge-ready' | 'zone.branches.title' | 'zone.branches.iteration-base' | 'zone.branches.target' | 'zone.branches.spec-integration' | 'zone.tasks.title' | 'zone.tasks.total' | 'zone.tasks.no-plans' | 'zone.tasks.more' | 'zone.tasks.collapse' | 'zone.project.title' | 'zone.project.milestones' | 'zone.project.residuals' | 'zone.project.none' | 'zone.state.Todo' | 'zone.state.InProgress' | 'zone.state.InReview' | 'zone.state.Done' | 'zone.state.blocked-unknown' | 'zone.agents.title' | 'zone.agents.summary' | 'zone.agents.on-demand' | 'zone.agents.unknown-sub' | 'zone.agents.bucket.implementor' | 'zone.agents.bucket.reviewer' | 'zone.agents.group.phase-1' | 'zone.agents.group.phase-2' | 'zone.agents.group.phase-n' | 'zone.agents.group.plan' | 'zone.agents.group.no-plan' | 'zone.agents.group.plan-more' | 'flow.empty' | 'flow.settle-only' | 'flow.degraded' | 'flow.unexpected' | 'flow.in-flight' | 'flow.settled-ok' | 'flow.error' | 'flow.advisory' | 'flow.denied' | 'state.title' | 'state.selection' | 'state.selection.history' | 'state.plans' | 'state.residuals' | 'state.policy' | 'state.leases' | 'state.knowledge' | 'state.direction' | 'state.none' | 'state.enforcement' | 'state.enforcement.hard' | 'state.enforcement.soft' | 'state.plans.more' | 'state.residual.more' | 'state.policy.push' | 'state.policy.worktree' | 'state.policy.control-worktree' | 'state.knowledge.docs' | 'freshness.last-updated' | 'freshness.refresh-note';
125
+ export type PanelKey = 'view.mstar-workflow' | 'tab.tasks' | 'tab.agents' | 'tab.events' | 'page.iteration.not-started' | 'page.iteration.expand' | 'page.iteration.collapse' | 'event-log.section.events' | 'event-log.section.violations' | 'event-log.empty' | 'event-log.empty.events' | 'event-log.empty.violations' | 'event-log.field.role' | 'event-log.field.agent' | 'event-log.field.stage' | 'event-log.field.plan' | 'event-log.field.task' | 'event-log.field.category' | 'event-log.field.time' | 'event-log.field.kind' | 'event-log.field.status' | 'event-log.field.expected' | 'event-log.field.settled' | 'event-log.field.duration' | 'event-log.field.run-id' | 'event-log.field.name' | 'event-log.field.members' | 'event-log.field.stop-reason' | 'event-log.field.severity' | 'event-log.field.code' | 'event-log.field.message' | 'event-log.kind.dispatch' | 'event-log.kind.settle' | 'event-log.yes' | 'event-log.no' | 'empty.waiting' | 'empty.loading' | 'empty.unavailable' | 'empty.no-harness' | 'empty.no-harness-hint' | 'watermark.version' | 'watermark.harness' | 'watermark.none' | 'panel.unknown' | 'graph.pass' | 'graph.fail' | 'zone.legend.title' | 'zone.legend.agent-running' | 'zone.legend.agent-settled' | 'zone.legend.agent-idle' | 'zone.iteration.step-label' | 'zone.iteration.step-badge' | 'zone.iteration.step.current' | 'zone.iteration.step.next' | 'zone.iteration.step.done' | 'zone.iteration.step.idle' | 'zone.phase.iteration-start' | 'zone.phase.autonomous-execute' | 'zone.phase.iteration-close' | 'zone.phase.pr-delivery' | 'zone.phase.merge-ready' | 'zone.branches.title' | 'zone.branches.iteration-base' | 'zone.branches.target' | 'zone.branches.spec-integration' | 'zone.tasks.title' | 'zone.tasks.total' | 'zone.tasks.no-plans' | 'zone.tasks.more' | 'zone.tasks.collapse' | 'zone.project.title' | 'zone.project.milestones' | 'zone.project.residuals' | 'zone.project.none' | 'zone.state.Todo' | 'zone.state.InProgress' | 'zone.state.InReview' | 'zone.state.Done' | 'zone.state.blocked-unknown' | 'zone.agents.title' | 'zone.agents.summary' | 'zone.agents.on-demand' | 'zone.agents.unknown-sub' | 'zone.agents.bucket.implementor' | 'zone.agents.bucket.reviewer' | 'zone.agents.group.phase-1' | 'zone.agents.group.phase-2' | 'zone.agents.group.phase-n' | 'zone.agents.group.plan' | 'zone.agents.group.no-plan' | 'zone.agents.group.plan-more' | 'flow.empty' | 'flow.settle-only' | 'flow.degraded' | 'flow.unexpected' | 'flow.in-flight' | 'flow.settled-ok' | 'flow.error' | 'flow.advisory' | 'flow.denied' | 'state.title' | 'state.selection' | 'state.selection.history' | 'state.plans' | 'state.residuals' | 'state.policy' | 'state.leases' | 'state.knowledge' | 'state.direction' | 'state.none' | 'state.enforcement' | 'state.enforcement.hard' | 'state.enforcement.soft' | 'state.plans.more' | 'state.residual.more' | 'state.policy.push' | 'state.policy.worktree' | 'state.policy.control-worktree' | 'state.knowledge.docs' | 'freshness.last-updated' | 'freshness.refresh-note';
126
126
  declare module '@deepseek-ai/dsh-client-ui-slots' {
127
127
  interface LocaleNamespaceMap {
128
128
  'mstar-panel': PanelKey;
@@ -10,9 +10,9 @@
10
10
  */
11
11
  import * as React from 'react';
12
12
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
13
- import type { MstarEngineStatusSource } from '../../types.ts';
13
+ import type { MstarEngineStatusPayload } from '../../types.ts';
14
14
  export interface PanelMetaProps {
15
15
  t: TranslateNS<'mstar-panel'>;
16
- source: MstarEngineStatusSource;
16
+ source: MstarEngineStatusPayload;
17
17
  }
18
18
  export declare function PanelMeta({ t, source }: PanelMetaProps): React.JSX.Element;
@@ -8,10 +8,10 @@
8
8
  */
9
9
  import * as React from 'react';
10
10
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
11
- import type { MstarEngineStatusSource, MstarHarnessState } from '../../types.ts';
11
+ import type { MstarEngineStatusPayload, MstarHarnessState } from '../../types.ts';
12
12
  export interface SidebarProps {
13
13
  t: TranslateNS<'mstar-panel'>;
14
14
  state: MstarHarnessState | null;
15
- source: MstarEngineStatusSource;
15
+ source: MstarEngineStatusPayload;
16
16
  }
17
17
  export declare function Sidebar({ t, state, source }: SidebarProps): React.JSX.Element;
@@ -13,11 +13,11 @@
13
13
  */
14
14
  import * as React from 'react';
15
15
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
16
- import type { MstarEngineStatusSource, MstarHarnessState } from '../../types.ts';
16
+ import type { MstarEngineStatusPayload, MstarHarnessState } from '../../types.ts';
17
17
  export interface StateSectionProps {
18
18
  t: TranslateNS<'mstar-panel'>;
19
19
  state: MstarHarnessState;
20
20
  /** Top-level enforcement flag (spec §2.1) — NOT part of the state digest. */
21
- enforcement: MstarEngineStatusSource['enforcement'];
21
+ enforcement: MstarEngineStatusPayload['enforcement'];
22
22
  }
23
23
  export declare function StateSection({ t, state, enforcement }: StateSectionProps): React.JSX.Element;