@mstar-harness/dsh 3.8.0 → 3.8.2

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.
Files changed (51) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +142 -194
  3. package/README.zh.md +29 -17
  4. package/bundle/README.md +83 -171
  5. package/dist/client/index.d.ts +17 -8
  6. package/dist/client/panel/MstarPanelTitle.d.ts +13 -0
  7. package/dist/client/panel/PanelView.d.ts +56 -52
  8. package/dist/client/panel/TabNav.d.ts +17 -14
  9. package/dist/client/panel/definition.d.ts +23 -0
  10. package/dist/client/panel/engine-status-client.d.ts +84 -6
  11. package/dist/client/panel/graph/project-graph.d.ts +35 -64
  12. package/dist/client/panel/graph/schema.d.ts +1 -2
  13. package/dist/client/panel/guards.d.ts +41 -1
  14. package/dist/client/panel/locale.d.ts +1 -1
  15. package/dist/client/panel/mstar-glyph.d.ts +22 -0
  16. package/dist/client/panel/pages/AgentListPage.d.ts +71 -0
  17. package/dist/client/panel/pages/EventLogPage.d.ts +7 -4
  18. package/dist/client/panel/pages/IterationInfoSection.d.ts +16 -13
  19. package/dist/client/panel/pages/IterationTaskPage.d.ts +13 -14
  20. package/dist/client/panel/panel-store.d.ts +28 -0
  21. package/dist/client/panel/sidebar.d.ts +13 -7
  22. package/dist/client/panel/state-section.d.ts +25 -3
  23. package/dist/client/panel/use-mstar-engine-status.d.ts +39 -14
  24. package/dist/client/panel/zones/Legend.d.ts +5 -3
  25. package/dist/client/panel/zones/TaskBoard.d.ts +13 -9
  26. package/dist/client.js +1038 -1242
  27. package/dist/engine-status-endpoint.d.ts +85 -8
  28. package/dist/engine-status-store.d.ts +91 -1
  29. package/dist/engine-status-wire.d.ts +9 -0
  30. package/dist/gates/_shared.d.ts +61 -9
  31. package/dist/gates/adapter.d.ts +32 -2
  32. package/dist/gates/agent-flow.d.ts +312 -60
  33. package/dist/gates/catalog.d.ts +59 -38
  34. package/dist/gates/dispatch.d.ts +11 -2
  35. package/dist/gates/goal-bridge.d.ts +10 -130
  36. package/dist/gates/plan-mode-bridge.d.ts +20 -11
  37. package/dist/gates/role-persona.d.ts +16 -0
  38. package/dist/gates/steering.d.ts +41 -0
  39. package/dist/gates/workflow-ledger.d.ts +31 -4
  40. package/dist/gates/workflow-selection.d.ts +41 -20
  41. package/dist/index.js +1208 -394
  42. package/dist/types.d.ts +50 -18
  43. package/harness-commands/amazing-pr-review.md +2 -0
  44. package/harness-commands/codebase-audit.md +2 -0
  45. package/harness-skills/mstar-host/SKILL.md +3 -1
  46. package/harness-skills/mstar-host/references/dsh-workflow-scripts.md +424 -0
  47. package/harness-skills/mstar-host/references/dsh.md +259 -266
  48. package/harness-skills/mstar-roles/references/project-manager.md +2 -0
  49. package/harness-skills/mstar-sdd/SKILL.md +2 -0
  50. package/package.json +66 -64
  51. package/dist/client/panel/pages/AgentCanvasPage.d.ts +0 -345
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The panel's own inline glyph (plan sidebar §L1.3): the icon the guide
3
+ * capsule draws before its title, and the chip title seat draws before the
4
+ * captured tab title. Deliberately NOT imported from
5
+ * `@deepseek-ai/dsh-client-ui-primitives` — dynamic client plugins may not
6
+ * import runtime values from other client plugins (types only), and the
7
+ * client bundle's purity gate rejects `@deepseek-ai/*` value imports — so the
8
+ * glyph is our own `<svg>` on `currentColor`, `IconProps`-shaped like the
9
+ * shipped `CompassGlyph`/`CubeGlyph`.
10
+ */
11
+ import type { IconProps } from '@deepseek-ai/dsh-client-ui-primitives';
12
+ /**
13
+ * The brand star on `currentColor` — the plugin's mark at guide and chip
14
+ * sizes (14–16px). `size` defaults to 16 (the guide-capsule size — the
15
+ * definition registers this component with no props); the chip title seat
16
+ * passes 14 explicitly. The geometry is the brand mark from the repo's
17
+ * `assets/` logos (`logo.svg` / `logo-dark.svg`): the star path reused
18
+ * verbatim (viewBox 512), the assets' colored rounded tile dropped — no
19
+ * tile, no hardcoded colors — `fill='currentColor'` so the host's chip/guide
20
+ * styling themes the mark.
21
+ */
22
+ export declare function MstarGlyph({ size, className }: IconProps): import("react").JSX.Element;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * AgentListPage (plan sidebar §L3) — the 代理执行 tab: a VERTICAL GROUPED
3
+ * LIST. Replaces the deleted absolutely-positioned agent canvas: every
4
+ * geometry concept (the coordinate-space content layer, the pointer pan, the
5
+ * stage columns, the card boxes, the SVG edge layer, the card ports) is
6
+ * gone — the flow itself is carried by the group/stage/sub-bucket headings
7
+ * in constant order, exactly as the column order did before.
8
+ *
9
+ * Grouping (plan sidebar §L3.2 — locked, PROJECTION-driven, never a render
10
+ * guess): two levels. The OUTER group is the phase of the entity's stage
11
+ * (`entity.stage.phase`, or `entity.zone` when `stage === null`), in the
12
+ * `EXPECTED_ROLE_FLOW`/`view.stages` constant order — Phase 1
13
+ * (iteration-start: the sequential review-edit-chain) then Phase 2
14
+ * (autonomous-execute: the iterative plan loop, annotated with the current
15
+ * `activePlanId`). The INNER group is the stage with the implementor stage
16
+ * split by the PROJECTED `entity.bucket`: the implementor partition above
17
+ * (flow roles in `SDD_BUCKET_ROLES.implementor` order, then the on-demand
18
+ * roles, carrying the on-demand badge) and the reviewer partition below —
19
+ * plus the「unknown / 未匹配角色」sub-bucket at the bottom of the LAST stage
20
+ * group for `zone: 'general'` entities, rendered only when it has members
21
+ * (the canvas's placement rule, unchanged). Every stage group always
22
+ * renders, because the projection always yields the full 14-role roster as
23
+ * cards (idle at minimum). The implementor-partition host stage is DERIVED
24
+ * from the projected skeleton (the stage whose expected roles intersect
25
+ * `SDD_BUCKET_ROLES.implementor`), so a phase/stage rename can never
26
+ * silently orphan the sub-buckets; absent that stage the LAST stage group is
27
+ * the total-function sink (never a throw).
28
+ *
29
+ * Card anatomy (plan sidebar §L3.3): each entity is a FULL-WIDTH FLOW ROW —
30
+ * no inline box style, no absolute positioning, no ports. The status point,
31
+ * done-✓ restriction (`status === 'settled' && emphasis !== 'off'`), the
32
+ * title rule, the ×N count, the role chip, the record line and the on-demand
33
+ * badge are all carried over unchanged.
34
+ *
35
+ * Emphasis tiers (design doc §3): the projected `data-agent-emphasis` tier
36
+ * fades the card CHROME only (chrome colors mix toward the layer background
37
+ * by tier — current 100% / next 75% / off 45%, theme-independent per
38
+ * `DESIGN.md` §3.5) — NEVER a whole-card opacity, so the status point and
39
+ * the ✓ never fade.
40
+ *
41
+ * Shared iteration section: the page renders the SAME `IterationInfoSection`
42
+ * the tasks tab uses, from the SAME `view.iteration` data — 两个 tab 显示同一
43
+ * 迭代信息块. The degradation note (degraded / empty / settle-only / link-only) is
44
+ * PROJECTED metadata, never inferred from the entity list, and the `Legend`
45
+ * (the 3 role-card status treatments) sits in flow BELOW the list.
46
+ *
47
+ * Scrolling (plan sidebar §L2.2): the page owns NO scroller — the rows grow
48
+ * the panel's single scroll body (`[data-mstar-scroll]`). The phase groups
49
+ * ride the shell's shared `.groupGrid` class (one column below the 720px
50
+ * container breakpoint, the two-column spread above it is that rule's).
51
+ */
52
+ import * as React from 'react';
53
+ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
54
+ import type { ZoneView } from '../graph/project-graph.ts';
55
+ export interface AgentListPageProps {
56
+ /** The projected agents zone (spec §6.2 — `ZoneView['agents']`). */
57
+ view: ZoneView['agents'];
58
+ /** The projected iteration zone (spec §3) — the SHARED iteration info
59
+ * block: BOTH the tasks tab and this page render the SAME
60
+ * `IterationInfoSection` from the SAME `view.iteration` data. */
61
+ iteration: ZoneView['iteration'];
62
+ t: TranslateNS<'mstar-panel'>;
63
+ }
64
+ /**
65
+ * The unknown sub-bucket id : `zone: 'general'` entities render in the
66
+ * 「unknown / 未匹配角色」sub-bucket at the bottom of the LAST stage group,
67
+ * marked `data-sub-bucket="unknown"`. The constant survives the canvas
68
+ * deletion — it names the sub-bucket VALUE, not a column.
69
+ */
70
+ export declare const UNKNOWN_COLUMN = "unknown";
71
+ export declare function AgentListPage({ view, iteration, t }: AgentListPageProps): React.JSX.Element;
@@ -10,10 +10,13 @@
10
10
  * keyboard-accessible, SSR-stable) whose body shows the FULL catalog fields;
11
11
  * a missing field renders「—」— never a guessed value (spec §5/§8).
12
12
  *
13
- * Layout (user feedback「左右
14
- * 排两列 + 锁定一个高内部滚动」): the two partitions render side by side in a
15
- * locked-height two-column grid; the page never scrolls as a whole — each
16
- * partition pins its title and scrolls internally (`event-log.module.css`).
13
+ * Layout (plan sidebar §L2.5/§L4.1): the two partitions are FLOW ROWS in
14
+ * the panel's single scroll body (`[data-mstar-scroll]`) — the old
15
+ * locked-height two-column grid and both per-partition internal scrollers
16
+ * are retired; rows grow the scroll body instead of owning a scrollbar.
17
+ * The grid rides the shell's shared `.groupGrid` class, so the ≥720px
18
+ * container spread is the shell's one rule. The iteration head is NOT
19
+ * rendered in this section.
17
20
  *
18
21
  * Dock migration decision (spec §5 — 无双份日志): the AgentEventDock is
19
22
  * REMOVED, not degraded. The dock's content (row layout + status chips)
@@ -2,9 +2,10 @@
2
2
  * IterationInfoSection (spec panel-tabs §3
3
3
  * — the SHARED iteration info block): the
4
4
  * Content Head — iteration summary (the collapsible toggle row) + the 5
5
- * horizontal iteration steps + the branches panel — rendered by BOTH tabs
5
+ * iteration steps stacked VERTICALLY + the branches panel — rendered by BOTH
6
+ * tabs
6
7
  * from the SAME `view.iteration` data (the tasks tab inside IterationTaskPage
7
- * above the kanban, the agents tab inside AgentCanvasPage above the canvas).
8
+ * above the board, the agents tab inside AgentListPage above the list).
8
9
  * One implementation, two mounts — 任务迭代与代理执行共用同一迭代信息块.
9
10
  *
10
11
  * The component is extracted VERBATIM from the former inline head of
@@ -13,18 +14,20 @@
13
14
  * - Content Head (spec §3): the iteration info (iterationId / gate verdict /
14
15
  * status note) rides the summary row, which IS the toggle (a native button
15
16
  * with aria-expanded + aria-controls pointing at the body). The
16
- * expanded body renders the Steps HORIZONTALLY as 5 EQUAL full-width unit
17
- * blocks (badge/phase/chip
18
- * centered, --mstar-space-* gap; no connector bars) with the current step
19
- * highlighted on the block itself (the same honesty as the zone stepper:
20
- * no "completed" checkmarks) plus the branch panel (rendered ONLY while the
21
- * iteration is active, spec §3). Plan (spec panel-f4 §2.3 R8/R9): the expanded body is a LEFT-RIGHT
22
- * SPLIT — branches (small half, DOM-first) + steps (large half), with the
23
- * `data-iteration-head-split` container present only while branches render;
17
+ * expanded body renders the Steps as a VERTICAL 5-item stacked stepper
18
+ * (one row per step: badge · phase · chip · verdict seat; plan sidebar
19
+ * §L4.2 — the horizontal row cannot fit the 300px column) with the current
20
+ * step highlighted on the block itself (the same honesty as the zone
21
+ * stepper: no "completed" checkmarks) plus the branch panel (rendered ONLY
22
+ * while the iteration is active, spec §3). Plan (spec panel-f4 §2.3
23
+ * R8/R9, re-shaped by plan sidebar §L4.2): the expanded body STACKS —
24
+ * branches (DOM-first) above the steps; the `data-iteration-head-split`
25
+ * container is present only while branches render;
24
26
  * each step reserves the fixed-height verdict seat (`data-step-verdict-seat`)
25
27
  * and the PASS/FAIL badge renders only for a current step with a real gate
26
28
  * verdict (`state === 'current' && verdict !== 'unknown'` — Phase 1 renders
27
- * no badge), so the centered content groups align across steps.
29
+ * no badge), so every step row has the SAME children (badge/phase/chip/seat)
30
+ * and the rows align across steps.
28
31
  *
29
32
  * Collapse/expand (spec §3): a local `useState` defaulted to
30
33
  * the iteration state — `active === false` → collapsed to a one-line summary
@@ -68,9 +71,9 @@ export declare function nextExpandedOnActivation(prev: boolean, prevActive: bool
68
71
  * — exported pure for the render tests, the `nextExpandedOnActivation`
69
72
  * precedent): the `data-iteration-head-split` container renders ONLY while
70
73
  * the branch panel renders (`active && branches !== null`); otherwise the
71
- * expanded body renders the steps row ALONE — the expanded-inactive fallback
74
+ * expanded body renders the steps stack ALONE — the expanded-inactive fallback
72
75
  * (a user manually expands an inactive head → the 5-step idle skeleton
73
- * without the split). The `active + branches null` arm is projection-
76
+ * without the wrapper). The `active + branches null` arm is projection-
74
77
  * unreachable (branches are always projected non-null while active), but the
75
78
  * predicate keeps the decision a single, testable source of truth.
76
79
  */
@@ -1,31 +1,30 @@
1
1
  /**
2
2
  * IterationTaskPage (spec panel-tabs §3
3
3
  * — the 任务迭代 tab: the SHARED IterationInfoSection (iteration
4
- * summary + the 5 horizontal iteration steps + branches — the same block the
4
+ * summary + the vertical 5-step stepper + branches — the same block the
5
5
  * agents tab renders, user
6
- * 2026-08-12 feedback #4) above the full-width standard kanban. Replaces the
6
+ * 2026-08-12 feedback #4) above the stacked plan board. Replaces the
7
7
  * WorkflowCanvas zone dashboard on the tasks tab (WorkflowCanvas is removed
8
8
  * by the plan close; its zone-level components stay untouched here).
9
9
  *
10
- * The head (collapse/expand, steps row, branches, verdict seats) lives in
11
- * `IterationInfoSection.tsx` — extracted from this page by Task 8 so BOTH
10
+ * The head (collapse/expand, vertical steps, branches, verdict seats) lives
11
+ * in `IterationInfoSection.tsx` — extracted from this page by Task 8 so BOTH
12
12
  * tabs render the SAME iteration info block from the SAME `view.iteration`
13
13
  * data (one implementation, two mounts; the anchor family `data-iteration-*`
14
14
  * is unchanged).
15
15
  *
16
- * Task area (spec §3/D2): the standard 5-column kanban (Todo / InProgress /
17
- * InReview / Done / blocked-unknown — Blocked + unknown merged) via the
18
- * REUSED TaskBoard
19
- * (`view.tasks`) — the Done overflow stays the projection's PLAN_CAP
20
- * handling (TaskBoard only surfaces the `+N more` hint). The page fills the
21
- * content region as a flex column: the head is flex:none (fixed), the tasks
22
- * area (`data-mstar-tasks-scroll`) is the page's independent vertical scroll
23
- * body (flex:1, min-height:0, overflow-y:auto) — the kanban spreads
24
- * full-width and is never compressed into a small box by a canvas height.
16
+ * Task area (plan sidebar §L4.2): the standard 5-group board (Todo /
17
+ * InProgress / InReview / Done / blocked-unknown — Blocked + unknown merged)
18
+ * via the REUSED TaskBoard (`view.tasks`) — the Done overflow stays the
19
+ * projection's PLAN_CAP handling (TaskBoard only surfaces the `+N more`
20
+ * hint). The page is FLOW CONTENT inside the panel's single scroll body
21
+ * (`[data-mstar-scroll]`, plan sidebar §L2.2 — the page-owned scroll body is
22
+ * retired): the board stacks as five groups, then the project rollup, then
23
+ * the in-flow digest.
25
24
  *
26
25
  * Degradation (spec §8): the projection never throws — an inactive/missing
27
26
  * iteration renders the collapsed muted summary; state/plans missing render
28
- * the muted 5-column kanban skeleton (TaskBoard) — never an orange warn box.
27
+ * the muted 5-group kanban skeleton (TaskBoard) — never an orange warn box.
29
28
  */
30
29
  import * as React from 'react';
31
30
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The workflow panel's entry store (plan sidebar §L2.4): the selected
3
+ * internal section, keyed by the sidebar tab record's id.
4
+ *
5
+ * Why a slot store and not `useState`: a docked sidebar body is UNMOUNTED
6
+ * whenever another tab in the pane becomes active (and the sidebar layout is
7
+ * memory-only), so component state would silently reset the section on every
8
+ * glance at the file tree. The store instance is framework-cached per
9
+ * (entry, session) and survives the unmount by construction; keying inside
10
+ * the state by `tab.id` keeps two panes showing the panel independent. The
11
+ * registration passes the handle as the seat's `store` option, so the body
12
+ * receives `useStore` + the baked `select` action through its props share.
13
+ */
14
+ /** The panel's three internal sections (one sidebar tab, three sections). */
15
+ export type PanelSection = 'tasks' | 'agents' | 'events';
16
+ /** The entry-store state: the selected section per sidebar tab record. */
17
+ export interface PanelStoreState {
18
+ byTab: Record<string, PanelSection | undefined>;
19
+ }
20
+ /**
21
+ * The panel entry store handle. `undefined` reads as the `'tasks'` default —
22
+ * the body applies `?? 'tasks'` at the read site, so nothing writes the
23
+ * default into the state.
24
+ */
25
+ export declare function createPanelStore(): import("@deepseek-ai/dsh-client-store").EngineStoreHandle<PanelStoreState, {
26
+ select(d: PanelStoreState, tabId: string, section: PanelSection): void;
27
+ }>;
28
+ export type PanelStore = ReturnType<typeof createPanelStore>;
@@ -1,17 +1,23 @@
1
1
  /**
2
- * Panel right sidebar (spec panel-zones §5): fixed 300px column, full height,
3
- * flex column — the workspace-state digest scrolls in its own region
4
- * (`flex: 1; min-height: 0; overflow-y: auto`), while the bottom meta dock
5
- * (version + harness dir) stays pinned and does NOT scroll with the digest.
2
+ * Workspace-state digest (plan sidebar §L2.1): the former 300px sidebar
3
+ * column, now IN FLOW at the end of the panel's scroll body — the digest is
4
+ * not a column any more, and its own nested scroller
5
+ * (`data-mstar-sidebar-scroll`) is retired: `[data-mstar-scroll]` is the
6
+ * panel's single scroller and this block is flow content inside it. The
7
+ * bottom meta dock moved to the shell's third zone (PanelView renders it
8
+ * directly), so this component renders ONLY the digest.
9
+ *
10
+ * `data-mstar-sidebar` stays on the digest block (anchor lineage).
6
11
  * Degradation: `state === null` renders the no-state note instead of the
7
- * digest (never a crash); the meta dock still renders from the source.
12
+ * digest (never a crash).
8
13
  */
9
14
  import * as React from 'react';
10
15
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
11
16
  import type { MstarEngineStatusPayload, MstarHarnessState } from '../../types.ts';
12
- export interface SidebarProps {
17
+ import { type MstarSelectionSeat } from './state-section.tsx';
18
+ export interface SidebarProps extends MstarSelectionSeat {
13
19
  t: TranslateNS<'mstar-panel'>;
14
20
  state: MstarHarnessState | null;
15
21
  source: MstarEngineStatusPayload;
16
22
  }
17
- 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
- export interface StateSectionProps {
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;
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * Data hook for the workflow panel (spec §5): the panel's ONE data path.
3
3
  *
4
- * The persisted catalog row is an ANCHOR, not a data source: since the source
5
- * reduction the row carries exactly `{ kind: 'plugin', plugin:
6
- * 'mstar-engine-status', form: 'catalog' }`, and the structured payload lives
7
- * in the host's per-session snapshot store. So the hook
4
+ * The persisted catalog row is an ANCHOR, not a data source: rows are emitted
5
+ * as `{ kind: 'plugin', plugin: 'mstar-engine', form: 'catalog' }`, and the
6
+ * structured payload lives in the host's per-session snapshot store. So the
7
+ * hook
8
8
  *
9
9
  * 1. finds the LATEST anchor row in the active session's conversation log
10
10
  * (`kind === 'context'` + `form === 'catalog'` + the first-party `plugin`
11
- * arm with this plugin's identity) and takes its message time as the
12
- * refresh key — a re-emission appends a new row, the snapshot bump re-runs
13
- * this selection, and the newest anchor asks for the newest snapshot;
11
+ * arm with one of this plugin's anchor identities) and takes its message
12
+ * time as the refresh key — a re-emission appends a new row, the snapshot
13
+ * bump re-runs this selection, and the newest anchor asks for the newest
14
+ * snapshot;
14
15
  * 2. reads the session's workspace directory from the session standard kit's
15
16
  * session feed (the host cross-checks the asserted `cwd` against the
16
17
  * session AND the stored snapshot, so it must be the real one);
@@ -36,8 +37,8 @@ import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
36
37
  import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
37
38
  import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
38
39
  import type { SessionId } from '@deepseek-ai/dsh-session';
39
- import type { MstarEngineStatusPayload } from '../../types.ts';
40
- 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';
41
42
  /** Selector hook over the Host session list (the `useSessions` standard seat). */
42
43
  export type UseSessions = SnapshotSelectorHook<SessionListState>;
43
44
  /** The panel's render state — a closed set: no shape can be both data and empty. */
@@ -65,6 +66,12 @@ export type MstarEngineStatusView =
65
66
  * identity (`at` timestamp and the agent turn it was written for). Both are
66
67
  * the host's records of the stored entry, so the panel can name which
67
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.
68
75
  */
69
76
  | {
70
77
  readonly state: 'ok';
@@ -72,6 +79,7 @@ export type MstarEngineStatusView =
72
79
  readonly payload: MstarEngineStatusPayload;
73
80
  readonly at: string;
74
81
  readonly turn: number;
82
+ readonly binding: WorkflowSelectionView | null;
75
83
  readonly reason: null;
76
84
  }
77
85
  /** An explicit degraded answer — always WITH a reason, never silently empty. */
@@ -85,11 +93,11 @@ export type MstarEngineStatusView =
85
93
  };
86
94
  /** The seats the hook needs: the session standard kit + the plugin's client. */
87
95
  export interface MstarEngineStatusSeats {
88
- /** Selector hook over the chat target snapshot (the `conversation.view` kit). */
96
+ /** Selector hook over the chat target snapshot (the session standard kit's chat face). */
89
97
  useChat: SnapshotSelectorHook<ChatSnapshot>;
90
98
  /**
91
99
  * Selector hook over the Host session list (the global standard seat). The
92
- * view ring always hands it to a `conversation.view` entry; it stays
100
+ * session-scope slot dispatch always hands it to the panel; it stays
93
101
  * optional here because a program without the ui-session adapter does not
94
102
  * see the declaration merge (the panel then reports `session-cwd-unknown`).
95
103
  */
@@ -99,7 +107,22 @@ export interface MstarEngineStatusSeats {
99
107
  /** The plugin's engine-status client (absent in a composition without one). */
100
108
  engineStatus: MstarEngineStatusClient | undefined;
101
109
  }
102
- /** Latest `mstar-engine-status` anchor row in snapshot order, or null. */
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
+ }
125
+ /** Latest engine-status anchor row (either accepted identity) in snapshot order, or null. */
103
126
  export declare function latestEngineStatusRow(nodes: readonly ConversationNode[]): ContextMessageNode | null;
104
127
  /** Anchor row message time, or null when the log carries no anchor row. */
105
128
  export declare function selectAnchorTime(snapshot: ChatSnapshot): number | null;
@@ -109,6 +132,8 @@ export declare function selectSessionCwd(sessionId: SessionId | undefined): (sta
109
132
  * The panel's data hook (spec §5).
110
133
  *
111
134
  * @param seats - the session standard kit + the plugin's engine-status client.
112
- * @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).
113
138
  */
114
- export declare function useMstarEngineStatus(seats: MstarEngineStatusSeats): MstarEngineStatusView;
139
+ export declare function useMstarEngineStatus(seats: MstarEngineStatusSeats): MstarEngineStatusHook;
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * Legend (spec panel-tabs §4/§6.2):
3
- * mounted on the AgentCanvasPage (the zone-dashboard footer legend is gone
4
- * with the WorkflowCanvas — spec §6.1). Describes ONLY the role-card status
5
- * treatments of the agent canvas — plan
3
+ * mounted on the AgentListPage, IN FLOW below the grouped list (the
4
+ * zone-dashboard footer legend is gone with the WorkflowCanvas — spec §6.1;
5
+ * the list page keeps the legend placement the canvas page established,
6
+ * after the content). Describes ONLY the role-card status
7
+ * treatments of the agent rows — plan
6
8
  * Task 1 (图例精简): the 7
7
9
  * collaboration-edge / layout entries (flow-actual / port / group /
8
10
  * sub-bucket / supervise / on-demand / unknown) are REMOVED — the legend is
@@ -1,13 +1,17 @@
1
1
  /**
2
2
  * TaskBoard — the tasks-zone kanban: the 5
3
- * PLAN_STATE_IDS columns (Todo / InProgress / InReview / Done /
4
- * blocked-unknown, in the projection's constant order), each with a localized
5
- * state-name header + count badge, plan cards (mono ellipsized id + status
6
- * chip — the `data-plan-id` / `data-plan-status` anchors shared with the
7
- * sidebar plan board), the dim inter-column flow arrows (spec §2.4:
8
- * Todo→InProgress→InReview→Done plus the InProgress↔Blocked back-edge, now
9
- * docking at the merged blocked-unknown column), the per-column 「更多」
10
- * expand affordance, and the muted "no plans" empty state.
3
+ * PLAN_STATE_IDS groups (Todo / InProgress / InReview / Done /
4
+ * blocked-unknown, in the projection's constant order) STACKED in flow (plan
5
+ * sidebar §L4.2 — the horizontal 5-column row cannot fit the 300px column),
6
+ * each with a header row carrying the flow glyph (the
7
+ * `data-kanban-arrow` labels + the `⇄` back-edge glyph: Todo→InProgress→
8
+ * InReview→Done plus the InProgress↔Blocked back-edge, docking at the merged
9
+ * blocked-unknown group), the localized state-name + count badge, plan cards
10
+ * (mono ellipsized id + status chip — the `data-plan-id` /
11
+ * `data-plan-status` anchors shared with the sidebar plan board), and the
12
+ * per-group 「更多」 expand affordance. The board rides the shell's shared
13
+ * `.groupGrid` class, so the ≥720px container spread reaches the groups
14
+ * (plan sidebar §L4.3 — one wide rule, not a second layout).
11
15
  *
12
16
  * The projection KEEPS every row (`column.plans` = the full column) and
13
17
  * reports `column.capped` (PLAN_CAP) when a column overflows. This render
@@ -19,7 +23,7 @@
19
23
  * keeps input order.
20
24
  *
21
25
  * Degradation (spec §8): state null / plans missing project to the same
22
- * 5-column skeleton with count 0 — the board renders it with a muted
26
+ * 5-group skeleton with count 0 — the board renders it with a muted
23
27
  * "no plans" note (`data-zone-empty="no-plans"`), NEVER an orange warn box.
24
28
  */
25
29
  import * as React from 'react';