@mstar-harness/dsh 3.8.1 → 3.8.3
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 +2 -2
- package/README.md +16 -6
- package/README.zh.md +16 -6
- package/dist/client/panel/engine-status-client.d.ts +84 -6
- package/dist/client/panel/graph/project-graph.d.ts +26 -13
- package/dist/client/panel/guards.d.ts +41 -1
- package/dist/client/panel/locale.d.ts +1 -1
- package/dist/client/panel/pages/AgentListPage.d.ts +1 -1
- package/dist/client/panel/sidebar.d.ts +3 -2
- package/dist/client/panel/state-section.d.ts +25 -3
- package/dist/client/panel/use-mstar-engine-status.d.ts +28 -4
- package/dist/client.js +346 -48
- package/dist/engine-status-endpoint.d.ts +85 -8
- package/dist/engine-status-store.d.ts +91 -1
- package/dist/engine-status-wire.d.ts +9 -0
- package/dist/gates/_shared.d.ts +61 -9
- package/dist/gates/adapter.d.ts +32 -2
- package/dist/gates/agent-flow.d.ts +312 -60
- package/dist/gates/catalog.d.ts +58 -37
- package/dist/gates/dispatch.d.ts +11 -2
- package/dist/gates/goal-bridge.d.ts +10 -130
- package/dist/gates/plan-mode-bridge.d.ts +20 -11
- package/dist/gates/role-persona.d.ts +16 -0
- package/dist/gates/steering.d.ts +41 -0
- package/dist/gates/workflow-ledger.d.ts +31 -4
- package/dist/gates/workflow-selection.d.ts +41 -20
- package/dist/index.js +1206 -392
- package/dist/types.d.ts +36 -11
- package/harness-commands/amazing-e2e-check.md +10 -0
- package/harness-commands/amazing-pr-review.md +2 -0
- package/harness-commands/codebase-audit.md +2 -0
- package/harness-commands/iteration-drive.md +1 -1
- package/harness-skills/mstar-artifacts/references/plan-files-and-reports.md +2 -2
- package/harness-skills/mstar-artifacts/references/plan-quality-bar.md +14 -12
- package/harness-skills/mstar-artifacts/templates/plan.main.md +19 -6
- package/harness-skills/mstar-audit/SKILL.md +5 -5
- package/harness-skills/mstar-coding-behavior/SKILL.md +8 -8
- package/harness-skills/mstar-dispatch-gates/SKILL.md +9 -7
- package/harness-skills/mstar-e2e/SKILL.md +40 -0
- package/harness-skills/mstar-e2e/references/report-template.md +32 -0
- package/harness-skills/mstar-engine-legacy/references/qc-seat-n-restatements.md +3 -3
- package/harness-skills/mstar-harness-core/SKILL.md +14 -1
- package/harness-skills/mstar-host/SKILL.md +3 -1
- package/harness-skills/mstar-host/references/_shared/host-role-binding-core.md +1 -1
- package/harness-skills/mstar-host/references/cursor.md +1 -1
- package/harness-skills/mstar-host/references/dsh-workflow-scripts.md +424 -0
- package/harness-skills/mstar-host/references/dsh.md +180 -51
- package/harness-skills/mstar-host/references/kimi.md +3 -3
- package/harness-skills/mstar-host/references/omp.md +3 -3
- package/harness-skills/mstar-host/references/parallel-dispatch.md +6 -6
- package/harness-skills/mstar-host/references/zcode.md +4 -4
- package/harness-skills/mstar-iteration/SKILL.md +1 -1
- package/harness-skills/mstar-iteration/references/phase-1-prepare.md +2 -2
- package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +3 -3
- package/harness-skills/mstar-review-qc/SKILL.md +4 -4
- package/harness-skills/mstar-review-qc/references/review-responsibility-boundaries.md +9 -7
- package/harness-skills/mstar-roles/SKILL.md +2 -0
- package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +9 -0
- package/harness-skills/mstar-roles/references/ops-engineer.md +3 -0
- package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +12 -9
- package/harness-skills/mstar-roles/references/project-manager/qa-trigger-matrix.md +7 -5
- package/harness-skills/mstar-roles/references/project-manager/qc-and-residuals.md +2 -2
- package/harness-skills/mstar-roles/references/project-manager/routing-and-dev-allocation.md +2 -2
- package/harness-skills/mstar-roles/references/project-manager.md +4 -2
- package/harness-skills/mstar-roles/references/qa-engineer/acceptance-gate.md +12 -13
- package/harness-skills/mstar-roles/references/qa-engineer.md +5 -4
- package/harness-skills/mstar-roles/references/qc-specialist/deep-review-lenses.md +5 -5
- package/harness-skills/mstar-roles/references/qc-specialist/report-template.md +2 -0
- package/harness-skills/mstar-roles/references/qc-specialist/reviewer-checklist.md +1 -1
- package/harness-skills/mstar-roles/references/qc-specialist/reviewer-workflow.md +5 -4
- package/harness-skills/mstar-roles/references/qc-specialist-shared.md +3 -1
- package/harness-skills/mstar-sdd/SKILL.md +17 -9
- package/harness-skills/mstar-sdd/references/file-handoffs.md +40 -20
- package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +9 -4
- package/harness-skills/mstar-sdd/references/implementer-prompt.md +11 -6
- package/harness-skills/mstar-sdd/references/sticky-implementer-session.md +4 -2
- package/harness-skills/mstar-sdd/references/task-reviewer-prompt.md +8 -4
- package/package.json +2 -2
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:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 38694c86b3d4bc15bb04dbcdb2a76756ceb2df72
|
|
6
|
+
README.zh.md: 74284ed74c76697032700864da84b7ec3e407be5
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ How a dsh app consumes the plugin — install paths, configuration, what mounts
|
|
|
14
14
|
|
|
15
15
|
The package ships as a workspace package (`workspaces: ["packages/*"]`) with the engine bundled into `dist/` at build time (`bun run build`; dist is gitignored). The install path is the **profile bundle**, added to the shipped `web` profile (`dsh --profile web` — the ready-made web app profile, `dsh web`), through the `dsh.bundle.patch` manifest — a patch layer mounted over the dsh-base defaults:
|
|
16
16
|
|
|
17
|
-
**One-command CLI entry (recommended)** — `npx @mstar-harness/cli init --target dsh` installs the full capability in one go: it runs the two `dsh plugin --profile web add` installs below in order (the mstar bundle first, then `dsh-llm-fallbacks`), and `npx @mstar-harness/cli doctor --target dsh` reports each plugin row as `uninstalled` / `disabled` / `mounted
|
|
17
|
+
**One-command CLI entry (recommended)** — `npx @mstar-harness/cli init --target dsh` installs the full capability in one go: it runs the two `dsh plugin --profile web add` installs below in order (the mstar bundle first, then `dsh-llm-fallbacks`), and `npx @mstar-harness/cli doctor --target dsh` reports each plugin row as `uninstalled` / `disabled` / `mounted` / `drifted` (`drifted` = the fallbacks row is installed at a version other than the pinned one; `init --target dsh` re-adds the pin, `doctor` exits non-zero until then). It is the same two-command install, orchestrated; `--no-fallbacks` skips the second row (and with it the seeded roles — see What you get below).
|
|
18
18
|
|
|
19
19
|
**(a) Registry install (published form)** — the npm package carries the built `dist/` (no build step on install):
|
|
20
20
|
|
|
@@ -74,7 +74,9 @@ The shipped headless template auto-initializes on first use (`@deepseek-ai/dsh-b
|
|
|
74
74
|
| `bundledSkillDir` | `string` | packaged `harness-skills/` mirror (package-relative) | Bundled skill root registered with the dsh skill-filesystem provider (`bundledSkillDir` semantics — scanned last, trusted). Defaults to the package's OWN `harness-skills/` mirror (synced by `bundle-assets`; gitignored) — package-relative, NOT cwd-anchored. An explicit value wins. |
|
|
75
75
|
| `catalogTtlMs` | `number` | `60000` | Pre-step catalog cache refresh interval (ms): how often the per-workspace unified `mstar-engine` catalog row (watermark + iteration gate + workspace-state digest) re-reads `status.json` / the compass / the knowledge index. The hot path is a timestamp compare + cache hit between refreshes; a mid-session plan/compass/residual change lands within one interval. |
|
|
76
76
|
| `workflowGate` | `'off' \| 'warn' \| 'ask' \| 'hard'` | `'warn'` | Workflow/ralph gate mode (see Gates → Workflow / ralph gate). `off` = pass-through with no verdict row; `warn` = advisory-only; `ask` = first-seen names route through the approval waterfall (P-c); `hard` = policy violations veto before any child starts. Default `warn` changes NO hard behavior — the gate is advisory-only unless the deployment opts into `ask`/`hard`. |
|
|
77
|
-
| `workflowNames` | `string[]` | unset | Workflow name allowlist (P-a): `meta.name` values treated as KNOWN by the gate. Empty or absent ⇒ **every** name is unknown (documented — the gate is NOT "allow all" by omission). Ralph calls carry no `meta.name` — P-a never applies to them. |
|
|
77
|
+
| `workflowNames` | `string[]` | unset | Workflow name allowlist (P-a): `meta.name` values treated as KNOWN by the gate. Empty or absent ⇒ **every** name is unknown (documented — the gate is NOT "allow all" by omission). Ralph calls carry no `meta.name` — P-a never applies to them. Recommended for the mstar read-only fan-out path: `['mstar-qc-tri', 'mstar-audit-fanout', 'mstar-pr-seats']`. |
|
|
78
|
+
|
|
79
|
+
**Recommended operator overlay.** The three recommended `workflowNames` above cover the mstar read-only fan-out path (plan QC tri, large-repo `/codebase-audit`, `/amazing-pr-review deep`); listing them is an operator overlay in the profile layer, never an mstar default. With the shipped empty list every name is *unknown*, which under the default `workflowGate: 'warn'` is one `workflow.name.unknown` advisory the run survives. A production deployment that also wants unknown names vetoed sets `workflowGate: 'hard'`; the shipped default stays `'warn'`.
|
|
78
80
|
|
|
79
81
|
`bundledSkillDir` defaults to the package's OWN `harness-skills/` mirror (see Skills mount) — an explicit Config value still wins. A relative override remains **cwd-anchored** (skill-filesystem `join()` semantics against the dsh process cwd), so deployments overriding the default should pass an **absolute path in the profile layer** (see `bundle/README.md`).
|
|
80
82
|
|
|
@@ -173,7 +175,7 @@ Persona delivery rides dsh's NATIVE `SubagentStartRequest.persona` slot (`@deeps
|
|
|
173
175
|
|
|
174
176
|
### Role seeds + adoption advisory
|
|
175
177
|
|
|
176
|
-
When the optional `dsh-llm-fallbacks` capability is **mounted** (the second install command — see Install paths), the mstar plugin **zero-config declares the 13 `mode: subagent` mstar role seeds** into the fallbacks seed registry: persona = the `harness-agents/` mirror `description` (verbatim) + one mandatory-load guide line (`Load mstar-roles (references/<role-id>.md) first — identity comes before skills; load topic skills only when the Assignment activates them via its Skill presets field.`); a persona carrying the `{{...}}` interpolation hazard is skipped + warned, never declared. The declaration **merge-preserves the currently-seeded non-mstar ids** from the readback — e.g. the
|
|
178
|
+
When the optional `dsh-llm-fallbacks` capability is **mounted** (the second install command — see Install paths), the mstar plugin **zero-config declares the 13 `mode: subagent` mstar role seeds** into the fallbacks seed registry: persona = the `harness-agents/` mirror `description` (verbatim) + one mandatory-load guide line (`Load mstar-roles (references/<role-id>.md) first — identity comes before skills; load topic skills only when the Assignment activates them via its Skill presets field.`); a persona carrying the `{{...}}` interpolation hazard is skipped + warned, never declared. The declaration **merge-preserves the currently-seeded non-mstar ids** from the readback — e.g. the 5 upstream preset roles the upstream package self-declares at its own apply: upstream `declare` REPLACES the whole registry, so without preservation a mstar-only batch would strip preset ids of their seeded annotations (rows remain, unseeded). The declaration re-fires idempotently on every fallbacks (re-)apply (HMR/fiber swap) — never from a one-shot latch — so either boot order (presets first or mstar first) converges to the same 18-id fully-seeded registry. Boot-time convergence is a bounded retry: the provider's seed write channel binds one macrotask after its apply, so a first-attempt reject with `seeds: settings service is unavailable` inside that apply window is retried (3 attempts across the provider's apply window) and a transient reject converges on its own; only if every attempt ultimately fails does the declaration log exactly one terminal error, while the advisory's decision-point re-declare stays available as the retry path. **No manual `roles.list` edit is required.**
|
|
177
179
|
|
|
178
180
|
A warn-only advisory pass (logger `mstar/fallbacks-advisory`) runs **once per apply** — attempted at apply and, when the fallbacks row mounts after `dsh` (the loader mounts entries concurrently), once at the first `subagent/start` decision point. With the service present, the pass FIRST awaits the idempotent re-declare (closing the boot race) then reads the EFFECTIVE state (`getEffectiveRoles`) and reports, bounded to **at most one warn per category**:
|
|
179
181
|
|
|
@@ -245,9 +247,17 @@ An advisory `agent/pre-step` waterfall listener appends ONE **`mstar-engine`** c
|
|
|
245
247
|
|
|
246
248
|
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
249
|
|
|
248
|
-
## Agent-flow ledger
|
|
250
|
+
## Agent-flow ledger
|
|
251
|
+
|
|
252
|
+
The agent-flow ledger lives in the ACTIVE workflow dir — `{HARNESS_DIR}/workflows/<id>/agent-flow.jsonl` (JSON Lines, bounded to the most recent 500 events) — the same JSONL the catalog's `state.agentFlow` evidence reads. With no active lifecycle the record is SKIPPED with a one-time warn — never the harness root, never a terminal snapshot dir. It records the ACTUAL subagent dispatch and settle evidence (advisory and try/catch-contained — a failing ledger write never blocks a dispatch or a settle):
|
|
253
|
+
|
|
254
|
+
- **Dispatch** — one row per Assignment-shaped dispatch, recording the dispatch identity: `role` (normalized at the write boundary — trimmed, with ONE leading `@` stripped, so `@explore` and `explore` are one actor, not two), `planId`, the Assignment `Task N` tag as `taskId`, `taskCategory`, and the verdict.
|
|
255
|
+
- **Settle** — recorded ONLY for a REAL paired completion. A foreground call settles in the `tools/post-execute` listener; a `{ kind: 'background', jobId }` result is paired on the registry **`jobId`** (a jobs-registry key, never a child session id) and settles when `ctx.inject(['jobs'])` → `jobs.onJobDone` reports the terminal snapshot (`completed → ok` / `killed → denied` / `failed → error`, `durationMs` when available). Every paired settle carries the dispatch identity (the `Task N` tag stays `taskId`; `taskRef` is reserved for the registry job id and rides on a background settle only) plus an OPTIONAL `childId` — a foreground `runId`, or a background child id the catalog join already supplied. A missing or oversized optional id omits the FIELD only: the real completion still records, and an id is never truncated or re-keyed. Unpaired payloads record NOTHING — never a fabricated settle.
|
|
256
|
+
- **`subagent-link` (nonterminal)** — the child session id a dispatch actually started, published upstream as a PARENT-OWNED `subagent/catalog` session event (`label` = the delegation `description`; the continuable path appends it BEFORE the tool returns). A per-dispatch CALL WINDOW join — slot reservation at pre-execute, eligibility on a valid `background` / `continuable` result, an `eventAt(seq)` catch-up scan plus ONE live root-context `session/event` observer — correlates that catalog child back to the dispatch identity (`role` / `planId` / `taskId`, plus `taskRef` for a background one-shot) in the DISPATCH's own workflow dir. It is an IDENTITY record, **not** a completion: no `outcome`, no `verdict`, no `paired` marker. The join is apply-scoped — no whole-history cold scan and no `session/created` backfill, so a catalog written before apply can never label a newer dispatch — and a dispatch whose provider emits no catalog simply has no link row.
|
|
257
|
+
|
|
258
|
+
### Workflow rows
|
|
249
259
|
|
|
250
|
-
The
|
|
260
|
+
The same ledger also records **workflow / ralph fan-out runs**: a session-event consumer (logger `mstar/workflow-ledger`, registered at apply) maps the FOUR durable `tool-workflow/*` session events into three new ledger kinds. Source of record is the **durable session events** appended into the CALLING PARENT session's log (top-level runs only — nested transport calls record nothing upstream), **not** the in-memory `workflow/*` emits (roadmap §10.4 N4): the session log is the replayable truth, so the consumer covers it with a **cold scan at apply** (constructor-seeded events never hit the firehose — `firstLiveSeq`) plus a live **`session/event` firehose** listener, deduped by ONE **durable per-session watermark** — the session-log `seq` position — persisted to `{HARNESS_DIR}/workflows/<id>/workflow-ledger-cursors.json` (a small bounded sidecar next to the ledger, written atomically temp-file + rename).
|
|
251
261
|
|
|
252
262
|
| `tool-workflow/*` event | Ledger row | Fields |
|
|
253
263
|
| --- | --- | --- |
|
|
@@ -259,7 +269,7 @@ The agent-flow ledger — `{HARNESS_DIR}/agent-flow.jsonl`, the same JSONL the c
|
|
|
259
269
|
|
|
260
270
|
A FOURTH kind, **`workflow-verdict`**, is written by the workflow/ralph GATE (not this consumer) — one row per gated call (`tool`, `workflow`/`objective`, `mode`, verdict `ok`/`advisory`/`denied`/`ask`, violation `code`) — see Gates → Workflow / ralph gate. Display identity fields (`workflow` / `objective`) carry the same 1024-char cap; the verdict's violation code is never guessed (P-a `workflow.name.unknown` vs P-b `workflow.lease.uncovered`).
|
|
261
271
|
|
|
262
|
-
**Dedupe + replay scope.** The durable watermark is the dedupe mechanism: **one row per `(runId, kind, seq)`** across cold+live overlap AND across plugin **re-applies / restarts** — a re-registration consults the persisted watermark instead of starting with empty cursors. A session **created after apply** with a constructor-seeded log (resumed / forked conversation — its seeds never publish on the firehose) is cold-scanned **once** on the upstream `session/created` event, and the watermark keeps that backfill idempotent too. The watermark sidecar is bounded (per-harness session cap, eviction preferring sessions no longer live) and fully contained: an unreadable/unwritable watermark degrades to in-memory-only with one warn — a restart then re-records (honest under-dedupe, never data loss, never gating).
|
|
272
|
+
**Dedupe + replay scope.** The durable watermark is the dedupe mechanism: **one row per `(runId, kind, seq)`** across cold+live overlap AND across plugin **re-applies / restarts** — a re-registration consults the persisted watermark instead of starting with empty cursors. A session **created after apply** with a constructor-seeded log (resumed / forked conversation — its seeds never publish on the firehose) is cold-scanned **once** on the upstream `session/created` event, and the watermark keeps that backfill idempotent too. A **forked** conversation's scan starts at its `inheritedEventCount`: the inherited prefix is the parent session's history, so the child records only its **own** events — never a second copy of the parent's rows attributed to the child. The watermark sidecar is bounded (per-harness session cap, eviction preferring sessions no longer live) and fully contained: an unreadable/unwritable watermark degrades to in-memory-only with one warn — a restart then re-records (honest under-dedupe, never data loss, never gating).
|
|
263
273
|
|
|
264
274
|
**childId linkage + member counts.** The `workflow-agent` row preserves the published member's `childId` (the child session id); the run's display `name` lives on the `workflow-run` row only, and the panel resolves it for agent/end rows via the window lookup (same `runId` — a member row itself carries no name). The panel attaches the member COUNT to the `workflow-run` row (the window's `workflow-agent` rows for that `runId`; window-bound — members truncated out of the ≤50-event window are honestly absent, never a 0 guess).
|
|
265
275
|
|
package/README.zh.md
CHANGED
|
@@ -14,7 +14,7 @@ dsh 应用如何使用本插件——安装路径、配置、挂载时发生什
|
|
|
14
14
|
|
|
15
15
|
本包以 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 默认层之上的补丁层:
|
|
16
16
|
|
|
17
|
-
**一条命令的 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
|
|
17
|
+
**一条命令的 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` / `drifted`(`drifted` = fallbacks 行的安装版本不等于 pin;`init --target dsh` 会按 pin 重新 add,在此之前 `doctor` 以非零退出)。它编排的仍是同一条双命令安装;`--no-fallbacks` 跳过第二行(连带跳过 seeded 角色——见下文「零配置获得什么」)。
|
|
18
18
|
|
|
19
19
|
**(a)registry 安装(发布形态)**——npm 包自带构建好的 `dist/`(安装时无需构建):
|
|
20
20
|
|
|
@@ -73,7 +73,9 @@ dsh plugin --profile headless add @mstar-harness/dsh
|
|
|
73
73
|
| `bundledSkillDir` | `string` | 打包的 `harness-skills/` 镜像(包相对路径) | 向 dsh skill-filesystem 提供者注册的打包技能根(`bundledSkillDir` 语义——最后扫描、受信任)。默认取包内自带的 `harness-skills/` 镜像(`bundle-assets` 同步;gitignore)——包相对路径,**非** cwd 锚定。显式值优先。 |
|
|
74
74
|
| `catalogTtlMs` | `number` | `60000` | pre-step catalog 缓存刷新间隔(毫秒):按工作区缓存的统一 `mstar-engine` 行(水印 + 迭代闸门 + 工作区摘要)多久重读一次 `status.json` / compass / 知识索引。刷新间隔之间热路径只是时间戳比较 + Map 命中;会话中 plan/compass/residual 的变化会在一个间隔内落地。 |
|
|
75
75
|
| `workflowGate` | `'off' \| 'warn' \| 'ask' \| 'hard'` | `'warn'` | workflow/ralph 闸门模式(见 Gates → Workflow / ralph gate)。`off` = 直通且不产生 verdict 行;`warn` = 仅咨询;`ask` = 首见名字走审批瀑布(P-c);`hard` = 策略违规在任何子进程启动前否决。默认 `warn` 不改任何 hard 行为——除非部署显式选入 `ask`/`hard`,闸门仅咨询。 |
|
|
76
|
-
| `workflowNames` | `string[]` | 未设置 | workflow 名字白名单(P-a):被闸门视为 KNOWN 的 `meta.name` 值。为空或缺省 ⇒ **每个**名字都 unknown(有文档——闸门**绝不**因缺省而"全放行")。ralph 调用不携带 `meta.name`——P-a 对其永不适用。 |
|
|
76
|
+
| `workflowNames` | `string[]` | 未设置 | workflow 名字白名单(P-a):被闸门视为 KNOWN 的 `meta.name` 值。为空或缺省 ⇒ **每个**名字都 unknown(有文档——闸门**绝不**因缺省而"全放行")。ralph 调用不携带 `meta.name`——P-a 对其永不适用。mstar 只读扇出路径推荐值:`['mstar-qc-tri', 'mstar-audit-fanout', 'mstar-pr-seats']`。 |
|
|
77
|
+
|
|
78
|
+
**推荐的 operator 覆盖层。** 上表三个推荐 `workflowNames` 覆盖 mstar 只读扇出路径(plan QC tri、大型仓库 `/codebase-audit`、`/amazing-pr-review deep`);写入它们是 profile 层的操作者覆盖,绝非 mstar 默认。出厂空列表下每个名字都是 *unknown*,在默认 `workflowGate: 'warn'` 下这只是运行会存活的一条 `workflow.name.unknown` 咨询。生产部署若还要否决 unknown 名字,可设置 `workflowGate: 'hard'`;出厂默认仍为 `'warn'`。
|
|
77
79
|
|
|
78
80
|
`bundledSkillDir` 默认取包内自带的 `harness-skills/` 镜像(见 Skills mount)——显式 Config 值仍然优先。相对覆盖仍是 **cwd 锚定**(skill-filesystem 以 `join()` 语义相对 dsh **进程 cwd** 解析),因此覆盖默认的部署应在 **profile 层传绝对路径**(见 `bundle/README.md`)。
|
|
79
81
|
|
|
@@ -172,7 +174,7 @@ persona 交付走 dsh 原生的 `SubagentStartRequest.persona` 槽(`@deepseek-
|
|
|
172
174
|
|
|
173
175
|
### 角色 seeds 与采纳建议(Adoption advisory)
|
|
174
176
|
|
|
175
|
-
当可选的 `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) first — identity comes before skills; load topic skills only when the Assignment activates them via its Skill presets field.`);含 `{{...}}` 插值风险的 persona 跳过并告警,绝不声明。声明会**合并保留 readback 中当前已 seeded 的非 mstar id**——例如上游包在其自身 apply 时自声明的
|
|
177
|
+
当可选的 `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) first — identity comes before skills; load topic skills only when the Assignment activates them via its Skill presets field.`);含 `{{...}}` 插值风险的 persona 跳过并告警,绝不声明。声明会**合并保留 readback 中当前已 seeded 的非 mstar id**——例如上游包在其自身 apply 时自声明的 5 个上游 preset 角色:上游 `declare` **全量替换** registry,若不保留,mstar-only 批会摘掉 preset id 的 seeded 注记(行仍在,仅失去 seeded)。声明在每次 fallbacks(重新)apply(HMR/纤程切换)时幂等重放——绝不用一次性 latch——因此两种 boot 顺序(presets 先或 mstar 先)都收敛到同一 18-id 全 seeded registry。boot 时收敛经 bounded retry(有界重试):上游的 seed 写通道在其 apply 之后一个 macrotask 才绑定,因此 apply 窗口内首次尝试被 `seeds: settings service is unavailable` 拒绝时会重试(跨上游 apply 窗口的 3 次尝试),暂时性拒绝自行收敛;仅当所有尝试最终失败时,声明才记录恰好一条终态错误,同时 advisory 的决策点 re-declare 仍可用作 retry 路径。**无需手动编辑 `roles.list`。**
|
|
176
178
|
|
|
177
179
|
一条只告警的采纳建议通道(日志器 `mstar/fallbacks-advisory`)**每次 apply 只跑一遍**——apply 时先尝试一次;当 fallbacks 行在 `dsh` 之后挂载(loader 并发挂载条目)时,改在首个 `subagent/start` 决策点只跑一遍。服务存在时,通道**先 await 幂等 re-declare**(闭合 boot 竞争窗口)再读取**有效状态**(`getEffectiveRoles`),并按**每类至多一条告警**有界报告:
|
|
178
180
|
|
|
@@ -244,9 +246,17 @@ mstar 技能通过 dsh skill-filesystem 提供者以**单一规范挂载**接入
|
|
|
244
246
|
|
|
245
247
|
该行是 **digest 门控**的:按 agent+workspace,每个 turn 只注入一次,仅当渲染文本变化时重新注入——20 步的 turn 只显示一次 catalog,而不是 20 次。source 共享**同一**按工作区缓存条目:显式 `harnessDir` 时在 boot 构建(否则在工作区首次 pre-step 构建),并按 TTL 刷新(`catalogTtlMs`,默认 60 秒)——刷新间隔之间热路径只是时间戳比较 + Map 命中,会话中 plan/compass/residual 的变化在一个间隔内落地。
|
|
246
248
|
|
|
247
|
-
## Agent-flow ledger
|
|
249
|
+
## Agent-flow ledger
|
|
250
|
+
|
|
251
|
+
agent-flow 账本位于**当前活动 workflow 目录**——`{HARNESS_DIR}/workflows/<id>/agent-flow.jsonl`(JSON Lines,保留最近 500 条)——即 catalog 的 `state.agentFlow` 证据所读的同一 JSONL。无活动生命周期时记录被**跳过**并只告警一次——绝不写 harness 根,绝不写终态快照目录。它记录**真实的** subagent 派发与结算证据(咨询式、try/catch 含容——账本写入失败绝不阻断派发或结算):
|
|
252
|
+
|
|
253
|
+
- **派发(dispatch)**——每个 Assignment 形态的派发一行,记录派发身份:`role`(在写入边界归一化——去首尾空白并剥掉**一个**前导 `@`,故 `@explore` 与 `explore` 是同一 actor 而非两个角色)、`planId`、Assignment 的 `Task N` 标签记为 `taskId`、`taskCategory` 与判定。
|
|
254
|
+
- **结算(settle)**——仅为**真实配对**的完成记录。前台调用在 `tools/post-execute` 监听器结算;`{ kind: 'background', jobId }` 结果按注册表 **`jobId`** 配对(jobs 注册表键,绝非子会话 id),待 `ctx.inject(['jobs'])` → `jobs.onJobDone` 报告终态快照时结算(`completed → ok` / `killed → denied` / `failed → error`,可用时附 `durationMs`)。每条配对结算都携带派发身份(`Task N` 标签仍是 `taskId`;`taskRef` 专用于注册表 job id,仅后台结算携带)外加**可选** `childId`——前台 `runId`,或 catalog 关联已提供的后台子会话 id。可选 id 缺失或超长时**只省略该字段**:真实完成照常记录,id 绝不截断、绝不重键。未配对载荷**不记录任何东西**——绝不伪造结算。
|
|
255
|
+
- **`subagent-link`(非终态)**——某次派发实际启动的子会话 id,由上游以**父会话自有**的 `subagent/catalog` 会话事件发布(`label` = 委派 `description`;continuable 路径在工具返回**之前**追加)。逐派发的**调用窗口**关联——pre-execute 预留槽位、有效 `background` / `continuable` 结果使其可选中、`eventAt(seq)` 补扫加**一个**活的根上下文 `session/event` 观察者——把该 catalog 子会话关联回派发身份(`role` / `planId` / `taskId`,后台 one-shot 另带 `taskRef`),写入**该派发自己的** workflow 目录。它是**身份记录**,**不是**完成:无 `outcome`、无 `verdict`、无 `paired` 标记。该关联为 apply 作用域——无全历史冷扫描、无 `session/created` 回填,故 apply 之前写入的 catalog 绝不可能给更晚的派发贴标签——而 provider 不发出 catalog 的派发就是没有 link 行。
|
|
256
|
+
|
|
257
|
+
### Workflow 行
|
|
248
258
|
|
|
249
|
-
|
|
259
|
+
同一账本还记录 **workflow / ralph 扇出运行**:一个会话事件消费者(日志器 `mstar/workflow-ledger`,apply 时注册)把四个持久化的 `tool-workflow/*` 会话事件映射为三种新账本类型。事实来源是**持久化会话事件**——追加进**调用方父会话**的日志(仅顶层运行;嵌套 transport 调用上游不记录任何东西),而**不是**内存中的 `workflow/*` emits(roadmap §10.4 N4):会话日志才是可回放的事实,因此消费者以 **apply 时冷扫描**(构造期种子事件从不进 firehose——`firstLiveSeq`)加实时 **`session/event` firehose** 监听覆盖它,按**持久化逐会话水位线**(会话日志 `seq` 位置)去重——水位线持久化到 `{HARNESS_DIR}/workflows/<id>/workflow-ledger-cursors.json`(账本旁的小型有界 sidecar,temp 文件 + rename 原子写入)。
|
|
250
260
|
|
|
251
261
|
| `tool-workflow/*` 事件 | 账本行 | 字段 |
|
|
252
262
|
| --- | --- | --- |
|
|
@@ -258,7 +268,7 @@ agent-flow 账本——`{HARNESS_DIR}/agent-flow.jsonl`,即 catalog 的 `state
|
|
|
258
268
|
|
|
259
269
|
**第四种类型 `workflow-verdict`** 由 workflow/ralph 闸门(而非本消费者)写入——每个被把关的调用一行(`tool`、`workflow`/`objective`、`mode`、判定 `ok`/`advisory`/`denied`/`ask`、违规 `code`)——见 Gates → Workflow / ralph gate。展示身份字段(`workflow` / `objective`)同样带 1024 字符上限;判定的违规码绝不猜测(P-a `workflow.name.unknown` vs P-b `workflow.lease.uncovered`)。
|
|
260
270
|
|
|
261
|
-
**去重与回放范围。** 持久化水位线即去重机制:**冷热重叠**以及**插件重应用/重启**(重注册读取持久化水位线而非从空游标开始)下每个 `(runId, kind, seq)` 只产一行。**apply 之后创建**、带构造期种子日志(恢复/分叉会话——其种子从不进 firehose)的会话会在上游 `session/created`
|
|
271
|
+
**去重与回放范围。** 持久化水位线即去重机制:**冷热重叠**以及**插件重应用/重启**(重注册读取持久化水位线而非从空游标开始)下每个 `(runId, kind, seq)` 只产一行。**apply 之后创建**、带构造期种子日志(恢复/分叉会话——其种子从不进 firehose)的会话会在上游 `session/created` 事件上**冷扫描一次**,水位线同样保证该回填幂等。**分叉**会话的扫描从其 `inheritedEventCount` 开始:继承来的前缀属于父会话的历史,因此子会话只记录**自己**的事件——绝不会把父会话的行以子会话身份再记一份。水位线 sidecar 有界(每 harness 会话数上限,驱逐优先已不在线的会话)且完全受控:水位线不可读/不可写时降级为仅内存并告警一次——重启后会重录(诚实的去重欠录,绝不丢数据、绝不阻塞)。
|
|
262
272
|
|
|
263
273
|
**childId 关联 + 成员计数。** `workflow-agent` 行保留已发布成员的 `childId`(子会话 id);运行的展示 `name` 只存在于 `workflow-run` 行,面板为 agent/end 行经窗口查找解析(同一 `runId`——成员行本身不带名称)。面板把成员 COUNT 挂到 `workflow-run` 行(窗口内该 `runId` 的 `workflow-agent` 行数;窗口有界——被 ≤50 事件窗口截掉的成员如实缺席,绝不猜 0)。
|
|
264
274
|
|
|
@@ -22,7 +22,13 @@
|
|
|
22
22
|
* on arrival ({@link MstarEngineStatusClient.write}) and the next render
|
|
23
23
|
* re-issues it. Without the fence an in-flight pre-reconnect answer would
|
|
24
24
|
* repopulate the cache and then suppress the repull the invalidation exists to
|
|
25
|
-
* force.
|
|
25
|
+
* force. A PICKER COMMIT uses the same fence PER SESSION
|
|
26
|
+
* ({@link MstarEngineStatusClient.invalidateSession}): the durable binding
|
|
27
|
+
* changed, so an in-flight pre-pick answer must not land — and the session's
|
|
28
|
+
* cached entry, which still answers the anchor row (a pick writes no row),
|
|
29
|
+
* must be re-pulled for its `binding` while the last emitted `payload` stays on
|
|
30
|
+
* screen (the plans / Event Log are the last MODEL emission until the next real
|
|
31
|
+
* one).
|
|
26
32
|
*
|
|
27
33
|
* DEADLINES: the gateway is a network hop, so one request is bounded
|
|
28
34
|
* ({@link MstarEngineStatusClientOptions.timeoutMs}) and a request that
|
|
@@ -41,9 +47,10 @@
|
|
|
41
47
|
* @module @mstar-harness/dsh/client/panel/engine-status-client
|
|
42
48
|
*/
|
|
43
49
|
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 };
|
|
50
|
+
import { ENGINE_STATUS_CHANNEL, ENGINE_STATUS_ENDPOINT, SELECT_WORKFLOW_ENDPOINT } from '../../engine-status-wire.ts';
|
|
51
|
+
import { type MstarEngineStatusFetch, type MstarSelectWorkflowFetch } from './guards.ts';
|
|
52
|
+
export { ENGINE_STATUS_CHANNEL, ENGINE_STATUS_ENDPOINT, SELECT_WORKFLOW_ENDPOINT };
|
|
53
|
+
export type { MstarSelectWorkflowFetch };
|
|
47
54
|
/** Deadline for one `/api/mstar/engineStatus` request (a hanging gateway must not pin `loading`). */
|
|
48
55
|
export declare const ENGINE_STATUS_REQUEST_TIMEOUT_MS = 5000;
|
|
49
56
|
/** How often a served snapshot is re-pulled (D3's "explicit refresh", modest interval). */
|
|
@@ -84,9 +91,28 @@ export interface MstarEngineStatusEntry {
|
|
|
84
91
|
readonly fetchedAt: number;
|
|
85
92
|
readonly fetch: MstarEngineStatusFetch;
|
|
86
93
|
}
|
|
87
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* The picker state of ONE session (D4 control feedback, never a selection
|
|
96
|
+
* source of truth): idle, a submission awaiting the host, the acknowledged
|
|
97
|
+
* workflow id, or the explicit failure reason. The panel disables a second
|
|
98
|
+
* submission while `pending` and shows `failed` beside the picker instead of a
|
|
99
|
+
* fake selection.
|
|
100
|
+
*/
|
|
101
|
+
export type MstarSelectionState = {
|
|
102
|
+
readonly state: 'idle';
|
|
103
|
+
} | {
|
|
104
|
+
readonly state: 'pending';
|
|
105
|
+
} | {
|
|
106
|
+
readonly state: 'selected';
|
|
107
|
+
readonly workflowId: string;
|
|
108
|
+
} | {
|
|
109
|
+
readonly state: 'failed';
|
|
110
|
+
readonly reason: string;
|
|
111
|
+
};
|
|
112
|
+
/** The observable store value: at most one entry per session (+ its picker state). */
|
|
88
113
|
export interface MstarEngineStatusSnapshot {
|
|
89
114
|
readonly entries: ReadonlyMap<string, MstarEngineStatusEntry>;
|
|
115
|
+
readonly selections: ReadonlyMap<string, MstarSelectionState>;
|
|
90
116
|
}
|
|
91
117
|
/**
|
|
92
118
|
* The panel's engine-status client: one `/api/mstar/engineStatus` request per
|
|
@@ -106,6 +132,19 @@ export declare class MstarEngineStatusClient {
|
|
|
106
132
|
private generationDisposer;
|
|
107
133
|
/** Connection generation: bumped by {@link invalidate}; a mismatched answer is dropped. */
|
|
108
134
|
private generation;
|
|
135
|
+
/**
|
|
136
|
+
* Per-session request generation: bumped by {@link invalidateSession} (a
|
|
137
|
+
* picker commit). A fetch captures the session's generation when it is
|
|
138
|
+
* issued, and its answer is dropped when that generation moved — the fence
|
|
139
|
+
* that keeps a late pre-pick answer from overwriting post-pick state.
|
|
140
|
+
*/
|
|
141
|
+
private readonly sessionGenerations;
|
|
142
|
+
/**
|
|
143
|
+
* Sessions whose cached entry no longer describes their durable binding: the
|
|
144
|
+
* next `ensure` for that entry's own anchor re-pulls it instead of serving it.
|
|
145
|
+
* Set by {@link invalidateSession}, cleared when the answer lands.
|
|
146
|
+
*/
|
|
147
|
+
private readonly stale;
|
|
109
148
|
private disposed;
|
|
110
149
|
/**
|
|
111
150
|
* @param connection - the client `connection` service, or undefined in a
|
|
@@ -135,6 +174,41 @@ export declare class MstarEngineStatusClient {
|
|
|
135
174
|
* repull this invalidation exists to force would be suppressed by them.
|
|
136
175
|
*/
|
|
137
176
|
invalidate(): void;
|
|
177
|
+
/**
|
|
178
|
+
* Mark ONE session's cached answer stale and fence off the requests already on
|
|
179
|
+
* the wire (a picker commit changed that session's durable binding).
|
|
180
|
+
*
|
|
181
|
+
* The entry is KEPT — the last emitted payload is still the last model
|
|
182
|
+
* emission, and spec §Picker contract 2 keeps plans / Event Log on it until
|
|
183
|
+
* the next real `agent/pre-step` replaces it. What must change is `binding`,
|
|
184
|
+
* the host's current control state, which the next {@link ensure} re-pulls for
|
|
185
|
+
* the same anchor ({@link stale}), because an entry that already answers the
|
|
186
|
+
* anchor would otherwise short-circuit the request and the panel would keep
|
|
187
|
+
* rendering the pre-pick selection.
|
|
188
|
+
*
|
|
189
|
+
* The fence is per session: a pre-pick answer issued before this call belongs
|
|
190
|
+
* to the superseded control state and is dropped on arrival, and no other
|
|
191
|
+
* session's cache is touched.
|
|
192
|
+
*/
|
|
193
|
+
invalidateSession(sessionId: string): void;
|
|
194
|
+
/**
|
|
195
|
+
* Commit this session's workflow pick over the host's shared gateway (the
|
|
196
|
+
* `selectWorkflow` UI control). Never optimistic: the returned state is
|
|
197
|
+
* `pending` until the host acknowledges, then either `selected` (with the
|
|
198
|
+
* acknowledged id) or `failed` (with the host's reason) — and a success
|
|
199
|
+
* invalidates THIS session only, so the next `ensure()` re-reads the
|
|
200
|
+
* acknowledged binding while every other session's cache is untouched.
|
|
201
|
+
* @param sessionId - the session the panel is showing.
|
|
202
|
+
* @param cwd - the session's workspace directory (the host cross-checks it).
|
|
203
|
+
* @param workflowId - the chosen ACTIVE workflow id.
|
|
204
|
+
*/
|
|
205
|
+
selectWorkflow(sessionId: string, cwd: string, workflowId: string): Promise<MstarSelectWorkflowFetch>;
|
|
206
|
+
/** One `selectWorkflow` round trip (never throws — every fault is a reason). */
|
|
207
|
+
private callSelect;
|
|
208
|
+
/** Publish one session's picker state (store write outside a render). */
|
|
209
|
+
private setSelection;
|
|
210
|
+
/** One session's current request generation. */
|
|
211
|
+
private sessionGen;
|
|
138
212
|
/** Stop accepting writes, abort in-flight requests and end the refresh interval (plugin teardown). */
|
|
139
213
|
dispose(): void;
|
|
140
214
|
/**
|
|
@@ -170,7 +244,11 @@ export declare class MstarEngineStatusClient {
|
|
|
170
244
|
* An answer issued under a superseded connection generation is DROPPED: it
|
|
171
245
|
* describes the connection that is gone, and publishing it would both render
|
|
172
246
|
* pre-reconnect data as `ok` and suppress the repull `invalidate()` forces
|
|
173
|
-
* (the stale answer would satisfy `ensure`'s anchor check).
|
|
247
|
+
* (the stale answer would satisfy `ensure`'s anchor check). An answer issued
|
|
248
|
+
* under a superseded SESSION generation is dropped for the same reason after a
|
|
249
|
+
* picker commit ({@link invalidateSession}): it describes the pre-pick control
|
|
250
|
+
* state and would otherwise repopulate the very entry the acknowledgement
|
|
251
|
+
* invalidated.
|
|
174
252
|
*
|
|
175
253
|
* An answer for a SUPERSEDED anchor is dropped for the same class of reason:
|
|
176
254
|
* a refresh issues its request for the anchor it saw, and a newer anchor row
|
|
@@ -100,15 +100,15 @@ export interface FlowEventView {
|
|
|
100
100
|
/** `${ts}-${kind}-${index}` — stable id (index = position in the projected window). */
|
|
101
101
|
id: string;
|
|
102
102
|
ts: number;
|
|
103
|
-
/** The ledger kind verbatim: dispatch | settle | the three workflow kinds | any unknown kind string (generic row). */
|
|
104
|
-
kind: 'dispatch' | 'settle' | 'workflow-run' | 'workflow-agent' | 'workflow-run-end' | (string & {});
|
|
103
|
+
/** The ledger kind verbatim: dispatch | settle | subagent-link | the three workflow kinds | any unknown kind string (generic row). */
|
|
104
|
+
kind: 'dispatch' | 'settle' | 'subagent-link' | 'workflow-run' | 'workflow-agent' | 'workflow-run-end' | (string & {});
|
|
105
105
|
/** `Execute as`; '' for settle rows without a paired identity and for workflow/unknown rows. */
|
|
106
106
|
role: string;
|
|
107
107
|
planId: string | null;
|
|
108
108
|
taskId: string | null;
|
|
109
109
|
taskCategory: string | null;
|
|
110
110
|
agent: string | null;
|
|
111
|
-
/** dispatch → dispatched|advisory|denied; settle → ok|error|denied; workflow/unknown → unknown (spec §2.4). */
|
|
111
|
+
/** dispatch → dispatched|advisory|denied; settle → ok|error|denied; link/workflow/unknown → unknown (spec §2.4). */
|
|
112
112
|
status: FlowEventStatus;
|
|
113
113
|
/** `role` ∈ the EXPECTED_ROLE_FLOW role union (spec §2.3 exact-string match). */
|
|
114
114
|
expected: boolean;
|
|
@@ -134,8 +134,19 @@ export interface FlowEventView {
|
|
|
134
134
|
readonly label?: string;
|
|
135
135
|
/** Run-member phase (workflow-agent rows only, when carried). */
|
|
136
136
|
readonly phase?: string;
|
|
137
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* Child session identity when the source supplied one: workflow-agent —
|
|
139
|
+
* the published member; settle — the foreground `runId` or a background
|
|
140
|
+
* catalog join; `subagent-link` — the required catalog child id. Omitted
|
|
141
|
+
* when the row carried none. Never a registry job id (that is `taskRef`).
|
|
142
|
+
*/
|
|
138
143
|
readonly childId?: string;
|
|
144
|
+
/**
|
|
145
|
+
* Settle + `subagent-link` rows: the registry background-job id, when
|
|
146
|
+
* carried. A jobs-registry key, never a child session id. Omitted when
|
|
147
|
+
* the row carried none.
|
|
148
|
+
*/
|
|
149
|
+
readonly taskRef?: string;
|
|
139
150
|
/** Terminal workflow run reason (workflow-run-end rows only). */
|
|
140
151
|
readonly stopReason?: string;
|
|
141
152
|
}
|
|
@@ -293,13 +304,15 @@ export type AgentEntityStatus = 'running' | 'settled' | 'error' | 'denied'
|
|
|
293
304
|
/**
|
|
294
305
|
* The canvas degradation-note classification (spec §8): the projection
|
|
295
306
|
* decides the note from the RAW ledger (never a UI-side heuristic on the
|
|
296
|
-
* entity list): `empty` = 0 events; `
|
|
297
|
-
*
|
|
298
|
-
* `
|
|
299
|
-
*
|
|
300
|
-
* `
|
|
307
|
+
* entity list): `empty` = 0 events; `link-only` = the readable window
|
|
308
|
+
* contains ONLY `subagent-link` rows (identity records — neither dispatch
|
|
309
|
+
* nor settlement evidence); `settle-only` = events present but NO dispatch
|
|
310
|
+
* and not link-only (settles / garbage / workflow — genuinely no dispatch
|
|
311
|
+
* evidence); `null` = dispatch evidence present (incl. anonymous dispatch
|
|
312
|
+
* rows — they are evidence, not settle-only). The unreadable-ledger case
|
|
313
|
+
* is the SEPARATE `degraded` flag, not a note value.
|
|
301
314
|
*/
|
|
302
|
-
export type AgentZoneNote = 'empty' | 'settle-only' | null;
|
|
315
|
+
export type AgentZoneNote = 'empty' | 'settle-only' | 'link-only' | null;
|
|
303
316
|
/**
|
|
304
317
|
* The projected agents zone (spec §4 + §6.2): the EXPECTED_ROLE_FLOW stage
|
|
305
318
|
* skeleton plus the dispatch-derived entity cards. Total function — NEVER
|
|
@@ -430,9 +443,9 @@ export declare function projectGraph(source: MstarEngineStatusPayload | null): Z
|
|
|
430
443
|
* collides.
|
|
431
444
|
*
|
|
432
445
|
* Canvas note: `note` classifies the readable ledger in
|
|
433
|
-
* the projection ('empty' / 'settle-only' / null — see
|
|
434
|
-
* UI consumes it directly and never infers
|
|
435
|
-
* (garbage rows would fake it).
|
|
446
|
+
* the projection ('empty' / 'link-only' / 'settle-only' / null — see
|
|
447
|
+
* `AgentZoneNote`); the UI consumes it directly and never infers
|
|
448
|
+
* settle-only from the entity list (garbage rows would fake it).
|
|
436
449
|
*
|
|
437
450
|
* Current-plan note: `activePlanId` / `activePlanCount` ride the
|
|
438
451
|
* `state.plans[]` InProgress rows (catalog order) — the Phase 2 group label
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* payload is a remote answer the panel never authored, so a malformed
|
|
11
11
|
* envelope degrades to `unavailable` — never to a half-parsed view.
|
|
12
12
|
*/
|
|
13
|
-
import type { MstarEngineStatusPayload } from '../../types.ts';
|
|
13
|
+
import type { MstarEngineStatusPayload, WorkflowSelectionView } from '../../types.ts';
|
|
14
14
|
/** String field: non-empty string, else null (missing → `unknown`). */
|
|
15
15
|
export declare function str(value: unknown): string | null;
|
|
16
16
|
/** Boolean field: real boolean, else null. */
|
|
@@ -33,10 +33,35 @@ export type MstarEngineStatusFetch = {
|
|
|
33
33
|
readonly at: string;
|
|
34
34
|
/** The agent turn the row was emitted for. */
|
|
35
35
|
readonly turn: number;
|
|
36
|
+
/**
|
|
37
|
+
* The session's CURRENT control-state selection, when the host served one
|
|
38
|
+
* (D4). It is deliberately separate from `payload.state.selection`, which
|
|
39
|
+
* keeps recording the LAST MODEL EMISSION — the picker's acknowledgement
|
|
40
|
+
* shows here immediately while plans / Event Log stay on the last snapshot.
|
|
41
|
+
* Null when the response carries none (an older host, or a malformed one).
|
|
42
|
+
*/
|
|
43
|
+
readonly binding: WorkflowSelectionView | null;
|
|
36
44
|
} | {
|
|
37
45
|
readonly status: 'unavailable';
|
|
38
46
|
readonly reason: string;
|
|
39
47
|
};
|
|
48
|
+
/** One workflow-pick acknowledgement (the `selectWorkflow` wire result). */
|
|
49
|
+
export type MstarSelectWorkflowFetch = {
|
|
50
|
+
readonly status: 'selected';
|
|
51
|
+
readonly sessionId: string;
|
|
52
|
+
readonly workflowId: string;
|
|
53
|
+
} | {
|
|
54
|
+
readonly status: 'unavailable';
|
|
55
|
+
readonly reason: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Narrow one untrusted workflow-selection view. Every arm must carry its
|
|
59
|
+
* discriminants as non-empty strings; the picker rows (`activeWorkflowIds`)
|
|
60
|
+
* survive only as a string array. Anything else is null — the caller then
|
|
61
|
+
* falls back to the emitted payload's own selection rather than rendering a
|
|
62
|
+
* guessed one.
|
|
63
|
+
*/
|
|
64
|
+
export declare function selectionView(value: unknown): WorkflowSelectionView | null;
|
|
40
65
|
/**
|
|
41
66
|
* Validate one `/api/mstar/engineStatus` response into the panel's state.
|
|
42
67
|
*
|
|
@@ -59,3 +84,18 @@ export type MstarEngineStatusFetch = {
|
|
|
59
84
|
* @returns the validated snapshot state, or the explicit unavailable state.
|
|
60
85
|
*/
|
|
61
86
|
export declare function parseEngineStatusResult(raw: unknown, sessionId: string, cwd?: string): MstarEngineStatusFetch;
|
|
87
|
+
/**
|
|
88
|
+
* Validate one `/api/mstar/selectWorkflow` response into the picker's state.
|
|
89
|
+
*
|
|
90
|
+
* Like {@link parseEngineStatusResult} the whole envelope is untrusted: the
|
|
91
|
+
* transport result, the endpoint result and the acknowledged identity are all
|
|
92
|
+
* checked. A success MUST name the session AND the workflow this client asked
|
|
93
|
+
* for — a foreign acknowledgement is refused rather than rendered as this
|
|
94
|
+
* session's pick.
|
|
95
|
+
*
|
|
96
|
+
* @param raw - the value returned by `connection.rpc.call` (untrusted).
|
|
97
|
+
* @param sessionId - the session this client ASKED for.
|
|
98
|
+
* @param workflowId - the workflow id this client asked to select.
|
|
99
|
+
* @returns the acknowledged pick, or the explicit unavailable state.
|
|
100
|
+
*/
|
|
101
|
+
export declare function parseSelectWorkflowResult(raw: unknown, sessionId: string, workflowId: string): MstarSelectWorkflowFetch;
|
|
@@ -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' | 'guide.description' | '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';
|
|
125
|
+
export type PanelKey = 'view.mstar-workflow' | 'guide.description' | '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.child-id' | '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.link-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.selection.unbound' | 'state.selection.pick' | 'state.selection.pending' | 'state.selection.failed' | '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;
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
*
|
|
41
41
|
* Shared iteration section: the page renders the SAME `IterationInfoSection`
|
|
42
42
|
* the tasks tab uses, from the SAME `view.iteration` data — 两个 tab 显示同一
|
|
43
|
-
* 迭代信息块. The degradation note (degraded / empty / settle-only) is
|
|
43
|
+
* 迭代信息块. The degradation note (degraded / empty / settle-only / link-only) is
|
|
44
44
|
* PROJECTED metadata, never inferred from the entity list, and the `Legend`
|
|
45
45
|
* (the 3 role-card status treatments) sits in flow BELOW the list.
|
|
46
46
|
*
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
import * as React from 'react';
|
|
15
15
|
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
16
16
|
import type { MstarEngineStatusPayload, MstarHarnessState } from '../../types.ts';
|
|
17
|
-
|
|
17
|
+
import { type MstarSelectionSeat } from './state-section.tsx';
|
|
18
|
+
export interface SidebarProps extends MstarSelectionSeat {
|
|
18
19
|
t: TranslateNS<'mstar-panel'>;
|
|
19
20
|
state: MstarHarnessState | null;
|
|
20
21
|
source: MstarEngineStatusPayload;
|
|
21
22
|
}
|
|
22
|
-
export declare function Sidebar({ t, state, source }: SidebarProps): React.JSX.Element;
|
|
23
|
+
export declare function Sidebar({ t, state, source, selection, pick, select }: SidebarProps): React.JSX.Element;
|
|
@@ -13,11 +13,33 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import * as React from 'react';
|
|
15
15
|
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
16
|
-
import type { MstarEngineStatusPayload, MstarHarnessState } from '../../types.ts';
|
|
17
|
-
|
|
16
|
+
import type { MstarEngineStatusPayload, MstarHarnessState, WorkflowSelectionView } from '../../types.ts';
|
|
17
|
+
import type { MstarSelectionState } from './engine-status-client.ts';
|
|
18
|
+
/**
|
|
19
|
+
* The picker seat (D4): the selection the panel SHOWS, this session's own
|
|
20
|
+
* commit state, and the commit seat itself. Handed down as one unit from the
|
|
21
|
+
* hook result to the section that renders it.
|
|
22
|
+
*/
|
|
23
|
+
export interface MstarSelectionSeat {
|
|
24
|
+
/**
|
|
25
|
+
* This session's CURRENT selection: the host's live control-state `binding`
|
|
26
|
+
* when the response carries one, else the last emission's own record
|
|
27
|
+
* (`state.selection`). `null` renders the unknown arm rather than throwing.
|
|
28
|
+
*/
|
|
29
|
+
readonly selection: WorkflowSelectionView | null;
|
|
30
|
+
/** This session's picker state (control feedback, never a selection source). */
|
|
31
|
+
readonly pick: MstarSelectionState;
|
|
32
|
+
/**
|
|
33
|
+
* Commit a workflow pick for this session, or null when the panel cannot
|
|
34
|
+
* (no client / no session / unknown cwd). Null renders an error selection
|
|
35
|
+
* WITHOUT a picker: a row that cannot be committed must not look clickable.
|
|
36
|
+
*/
|
|
37
|
+
readonly select: ((workflowId: string) => void) | null;
|
|
38
|
+
}
|
|
39
|
+
export interface StateSectionProps extends MstarSelectionSeat {
|
|
18
40
|
t: TranslateNS<'mstar-panel'>;
|
|
19
41
|
state: MstarHarnessState;
|
|
20
42
|
/** Top-level enforcement flag (spec §2.1) — NOT part of the state digest. */
|
|
21
43
|
enforcement: MstarEngineStatusPayload['enforcement'];
|
|
22
44
|
}
|
|
23
|
-
export declare function StateSection({ t, state, enforcement }: StateSectionProps): React.JSX.Element;
|
|
45
|
+
export declare function StateSection({ t, state, enforcement, selection, pick, select }: StateSectionProps): React.JSX.Element;
|
|
@@ -37,8 +37,8 @@ import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
|
37
37
|
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
|
|
38
38
|
import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
39
39
|
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
40
|
-
import type { MstarEngineStatusPayload } from '../../types.ts';
|
|
41
|
-
import type { MstarEngineStatusClient } from './engine-status-client.ts';
|
|
40
|
+
import type { MstarEngineStatusPayload, WorkflowSelectionView } from '../../types.ts';
|
|
41
|
+
import type { MstarEngineStatusClient, MstarSelectionState } from './engine-status-client.ts';
|
|
42
42
|
/** Selector hook over the Host session list (the `useSessions` standard seat). */
|
|
43
43
|
export type UseSessions = SnapshotSelectorHook<SessionListState>;
|
|
44
44
|
/** The panel's render state — a closed set: no shape can be both data and empty. */
|
|
@@ -66,6 +66,12 @@ export type MstarEngineStatusView =
|
|
|
66
66
|
* identity (`at` timestamp and the agent turn it was written for). Both are
|
|
67
67
|
* the host's records of the stored entry, so the panel can name which
|
|
68
68
|
* emission it is showing rather than implying it is the newest one.
|
|
69
|
+
*
|
|
70
|
+
* `binding` is the host's CURRENT control-state selection for this session
|
|
71
|
+
* (`null` when it served none), deliberately separate from
|
|
72
|
+
* `payload.state.selection` — which keeps recording the last MODEL EMISSION,
|
|
73
|
+
* so the picker's acknowledgement shows immediately while plans / Event Log
|
|
74
|
+
* stay on the last emitted snapshot.
|
|
69
75
|
*/
|
|
70
76
|
| {
|
|
71
77
|
readonly state: 'ok';
|
|
@@ -73,6 +79,7 @@ export type MstarEngineStatusView =
|
|
|
73
79
|
readonly payload: MstarEngineStatusPayload;
|
|
74
80
|
readonly at: string;
|
|
75
81
|
readonly turn: number;
|
|
82
|
+
readonly binding: WorkflowSelectionView | null;
|
|
76
83
|
readonly reason: null;
|
|
77
84
|
}
|
|
78
85
|
/** An explicit degraded answer — always WITH a reason, never silently empty. */
|
|
@@ -100,6 +107,21 @@ export interface MstarEngineStatusSeats {
|
|
|
100
107
|
/** The plugin's engine-status client (absent in a composition without one). */
|
|
101
108
|
engineStatus: MstarEngineStatusClient | undefined;
|
|
102
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The panel hook's result: the render state plus this session's picker seat.
|
|
112
|
+
* `selection` is the served binding (absent until an `ok` render); `pick` is the
|
|
113
|
+
* local commit state for THIS session only; `select` is null exactly when no
|
|
114
|
+
* commit can be made (no client, no session, or unknown cwd).
|
|
115
|
+
*/
|
|
116
|
+
export interface MstarEngineStatusHook {
|
|
117
|
+
readonly view: MstarEngineStatusView;
|
|
118
|
+
/** The served selection of the rendered payload (null unless `view.state === 'ok'`). */
|
|
119
|
+
readonly selection: WorkflowSelectionView | null;
|
|
120
|
+
/** This session's picker state, `idle` until a pick is committed. */
|
|
121
|
+
readonly pick: MstarSelectionState;
|
|
122
|
+
/** Commit a pick for this session; null when the panel cannot commit one. */
|
|
123
|
+
readonly select: ((workflowId: string) => void) | null;
|
|
124
|
+
}
|
|
103
125
|
/** Latest engine-status anchor row (either accepted identity) in snapshot order, or null. */
|
|
104
126
|
export declare function latestEngineStatusRow(nodes: readonly ConversationNode[]): ContextMessageNode | null;
|
|
105
127
|
/** Anchor row message time, or null when the log carries no anchor row. */
|
|
@@ -110,6 +132,8 @@ export declare function selectSessionCwd(sessionId: SessionId | undefined): (sta
|
|
|
110
132
|
* The panel's data hook (spec §5).
|
|
111
133
|
*
|
|
112
134
|
* @param seats - the session standard kit + the plugin's engine-status client.
|
|
113
|
-
* @returns the explicit render state (never a throw, never a half-parsed view)
|
|
135
|
+
* @returns the explicit render state (never a throw, never a half-parsed view)
|
|
136
|
+
* plus this session's picker triple: the served `selection`, the local commit
|
|
137
|
+
* `pick`, and `select` (null when no pick can be committed).
|
|
114
138
|
*/
|
|
115
|
-
export declare function useMstarEngineStatus(seats: MstarEngineStatusSeats):
|
|
139
|
+
export declare function useMstarEngineStatus(seats: MstarEngineStatusSeats): MstarEngineStatusHook;
|