@mstar-harness/dsh 3.6.3 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +4 -6
  2. package/README.zh.md +3 -3
  3. package/dist/client/panel/PanelView.d.ts +8 -11
  4. package/dist/client/panel/TabNav.d.ts +2 -2
  5. package/dist/client/panel/graph/event-log.d.ts +5 -9
  6. package/dist/client/panel/graph/project-graph.d.ts +53 -72
  7. package/dist/client/panel/graph/schema.d.ts +31 -37
  8. package/dist/client/panel/locale.d.ts +19 -19
  9. package/dist/client/panel/pages/AgentCanvasPage.d.ts +40 -58
  10. package/dist/client/panel/pages/EventLogPage.d.ts +6 -6
  11. package/dist/client/panel/pages/IterationInfoSection.d.ts +9 -11
  12. package/dist/client/panel/pages/IterationTaskPage.d.ts +3 -3
  13. package/dist/client/panel/plan-sort.d.ts +3 -6
  14. package/dist/client/panel/state-section.d.ts +1 -1
  15. package/dist/client/panel/zones/Legend.d.ts +2 -2
  16. package/dist/client/panel/zones/ProjectRollup.d.ts +1 -2
  17. package/dist/client/panel/zones/TaskBoard.d.ts +1 -2
  18. package/dist/gates/_shared.d.ts +7 -10
  19. package/dist/gates/adapter.d.ts +6 -9
  20. package/dist/gates/agent-flow.d.ts +49 -59
  21. package/dist/gates/agent-personas.d.ts +1 -2
  22. package/dist/gates/catalog.d.ts +2 -5
  23. package/dist/gates/dispatch.d.ts +9 -11
  24. package/dist/gates/fallbacks-advisory.d.ts +2 -3
  25. package/dist/gates/fallbacks-probe.d.ts +2 -2
  26. package/dist/gates/fallbacks-seeds.d.ts +1 -1
  27. package/dist/gates/fallbacks-structural.d.ts +1 -1
  28. package/dist/gates/goal-bridge.d.ts +6 -9
  29. package/dist/gates/role-persona.d.ts +2 -3
  30. package/dist/gates/skill-lint.d.ts +19 -2
  31. package/dist/gates/system-prompt.d.ts +7 -11
  32. package/dist/gates/tools.d.ts +1 -1
  33. package/dist/gates/workflow-ledger.d.ts +21 -28
  34. package/dist/gates/workflow-policy.d.ts +15 -19
  35. package/dist/gates/workflow-selection.d.ts +3 -3
  36. package/dist/index.js +215 -33
  37. package/dist/types.d.ts +4 -7
  38. package/harness-commands/iteration-drive.md +6 -6
  39. package/harness-commands/iteration-loop.md +7 -7
  40. package/harness-commands/iteration-start.md +8 -8
  41. package/harness-skills/mstar-coding-behavior/SKILL.md +3 -20
  42. package/harness-skills/mstar-dispatch-gates/SKILL.md +7 -13
  43. package/harness-skills/mstar-dispatch-gates/references/leaf-executor-checklist.md +1 -1
  44. package/harness-skills/mstar-harness-core/SKILL.md +9 -53
  45. package/harness-skills/mstar-host/references/zcode.md +1 -0
  46. package/harness-skills/mstar-iteration/SKILL.md +32 -318
  47. package/harness-skills/mstar-iteration/references/command-shared-invariants.md +1 -1
  48. package/harness-skills/mstar-iteration/references/phase-1-prepare.md +155 -0
  49. package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +113 -3
  50. package/harness-skills/mstar-iteration/references/phase5-helper-discovery.md +1 -1
  51. package/harness-skills/mstar-roles/SKILL.md +14 -12
  52. package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +5 -6
  53. package/harness-skills/mstar-roles/references/architect.md +1 -1
  54. package/harness-skills/mstar-roles/references/code-reviewer.md +11 -1
  55. package/harness-skills/mstar-roles/references/frontend-dev.md +1 -1
  56. package/harness-skills/mstar-roles/references/fullstack-dev-shared.md +1 -1
  57. package/harness-skills/mstar-roles/references/ops-engineer.md +1 -1
  58. package/harness-skills/mstar-roles/references/product-manager.md +1 -1
  59. package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +4 -0
  60. package/harness-skills/mstar-roles/references/project-manager.md +6 -4
  61. package/harness-skills/mstar-roles/references/prompt-engineer.md +1 -1
  62. package/harness-skills/mstar-roles/references/qa-engineer.md +1 -1
  63. package/harness-skills/mstar-roles/references/qc-specialist-shared.md +1 -1
  64. package/harness-skills/mstar-roles/references/writing-specialist.md +1 -1
  65. package/harness-skills/mstar-sdd/references/file-handoffs.md +40 -7
  66. package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +9 -0
  67. package/harness-skills/mstar-sdd/references/implementer-prompt.md +9 -0
  68. package/harness-skills/mstar-sdd/references/task-reviewer-prompt.md +7 -0
  69. package/package.json +1 -1
@@ -11,14 +11,13 @@ export declare const DISPATCH_LOGGER = "mstar/dispatch-gate";
11
11
  * default id + its fork sibling — roadmap §9 W-B1: fork dispatches carry the
12
12
  * same Assignment-shaped `{ description, prompt }` args and must be gated
13
13
  * like `subagent`). Exported SHARED with the agent-flow settle pairing
14
- * (`registerSettleListener` matches the same tool set — plan
15
- * `20260811-panel-f4-timeliness` Task 1) so the default cannot drift between
14
+ * (`registerSettleListener` matches the same tool set) so the default cannot drift between
16
15
  * the gate and the settle seam.
17
16
  */
18
17
  export declare const DEFAULT_DISPATCH_TOOLS: readonly ["subagent", "subagent_fork"];
19
18
  /**
20
19
  * The fixed workflow/ralph tool names the workflow gate matches (plan
21
- * `20260815-dsh-workflow-gate` — architect-verified): the workflow tool
20
+ * — architect-verified): the workflow tool
22
21
  * registers under Config-default name `'workflow'` and is RENAMEABLE per
23
22
  * instance (`toolName`, `tool-workflow/src/index.ts:41`); `ralph` is a
24
23
  * fixed name (`tool-ralph/src/index.ts:413`). A renamed instance is out
@@ -51,7 +50,7 @@ export interface DispatchGateAdvisory {
51
50
  * stay silent — no false-positive warnings. Callers MUST pass the engine
52
51
  * `assignmentHeaderRegion` slice: a `## Assignment` heading or
53
52
  * field line quoted in the task body must not shape a non-assignment prompt.
54
- * Exported for the agent-flow ledger's shape guard (qc2 F-2 — the shared
53
+ * Exported for the agent-flow ledger's shape guard — the shared
55
54
  * `DshHostAdapter.dispatchGate` core applies the SAME guard on both dispatch
56
55
  * surfaces, so the exec-less host-hook path records nothing for
57
56
  * non-Assignment text either).
@@ -65,7 +64,7 @@ export declare function isAssignmentShaped(assignmentText: string): boolean;
65
64
  * frontmatter, else warn-only.
66
65
  */
67
66
  export declare function resolveDispatchHard(harnessDir: string | null, config: Config, assignmentText: string): boolean;
68
- /** A header value that means "no value" (placeholder conventions). Type guard so callers narrow to `string`. Shared with the agent-flow ledger (qc1 F-003 — one grammar, no copy-paste drift). */
67
+ /** A header value that means "no value" (placeholder conventions). Type guard so callers narrow to `string`. Shared with the agent-flow ledger (one grammar, no copy-paste drift). */
69
68
  export declare function isNaValue(value: string | undefined): value is undefined;
70
69
  /**
71
70
  * Resolve the target plan id from the Assignment HEADER region: `Plan Path`
@@ -95,7 +94,7 @@ export declare function sessionIdOf(exec: ToolExecution): string | undefined;
95
94
  * whose plan row is `InProgress`.
96
95
  *
97
96
  * Contract (status-and-residuals.md § Pre-dispatch re-verify; v3
98
- * relocation — plan `20260819-workflow-dsh-viz` Task 3): before any
97
+ * relocation —): before any
99
98
  * writable implement dispatch, reread the ACTIVE workflow snapshot
100
99
  * (`workflows/<id>/snapshot.json` — the v1 root `plans[]` home is gone; the
101
100
  * root v2 `status.json` supplies the active `workflows[]`) and confirm
@@ -150,8 +149,7 @@ export declare function dispatchGateCore(config: Config, harnessDir: string | nu
150
149
  };
151
150
  /**
152
151
  * The workflow-gate input composed from one `workflow`/`ralph` tool call
153
- * (plan `20260815-dsh-workflow-gate` Task 1 — consumed by the Task 2 P-a /
154
- * P-c and Task 3 P-b policies): the tool name + the structural reads of
152
+ * : the tool name + the structural reads of
155
153
  * `meta` (workflow) / `objective` (ralph) + the in-flight call.
156
154
  */
157
155
  export interface WorkflowGateInput {
@@ -164,7 +162,7 @@ export interface WorkflowGateInput {
164
162
  /** The in-flight tool call — Task 3 P-b lease attribution reads the calling agent/session off it. */
165
163
  exec: ToolExecution;
166
164
  /**
167
- * P-b lease attribution (plan Task 3): the calling workspace's first
165
+ * P-b lease attribution: the calling workspace's first
168
166
  * `InProgress` plan lacking `execution_lease` coverage (computed by
169
167
  * {@link writableFanOutUncovered} from the status.json read through the
170
168
  * contained resolver path — `preExecuteListener` already resolved the
@@ -177,7 +175,7 @@ export interface WorkflowGateInput {
177
175
  /**
178
176
  * Compose the {@link WorkflowGateInput} from one workflow/ralph tool call's
179
177
  * arguments — structural reads, NEVER throws (plan
180
- * `20260815-dsh-workflow-gate` Task 1; args shapes architect-verified:
178
+ * Task 1; args shapes architect-verified:
181
179
  * workflow `{ script, meta: { name, description, whenToUse?, phases? },
182
180
  * args? }` (`tool-workflow/src/index.ts:152-161`); ralph
183
181
  * `{ objective, maxRounds?, maxHandoffChars? }`
@@ -187,7 +185,7 @@ export interface WorkflowGateInput {
187
185
  *
188
186
  * `meta.name` is NORMALIZED through {@link normalizeWorkflowName} (control
189
187
  * chars stripped) BEFORE the empty check — the P-c cache-key congruence
190
- * fold-in (plan Task 5): the run-start observation (workflow-ledger.ts)
188
+ * fold-in: the run-start observation (workflow-ledger.ts)
191
189
  * keys the ask cache with the SAME normalized name, so a control-char name
192
190
  * (`au\u0000dit`) asks once and observes under one key instead of re-asking
193
191
  * forever. The length is NEVER capped here (the gate's identity axis is
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Warn-only adoption advisory for the OPTIONAL `dsh-llm-fallbacks` plugin
3
- * (plan `20260815-dsh-fallbacks-personas` Task 4 + `20260816-dsh-b4-seeds`
4
- * Task 3): when the capability is mounted, ONE advisory pass per apply
3
+ * (plan Task 4 + when the capability is mounted, ONE advisory pass per apply
5
4
  * reports the deployment's fallbacks taxonomy state (bounded: ≤1 warn per
6
5
  * category, logger `mstar/fallbacks-advisory`):
7
6
  *
@@ -54,7 +53,7 @@ export declare function setAdvisoryLogger(sink: AdvisoryLogSink): AdvisoryLogSin
54
53
  /**
55
54
  * Warn id-list cap: an id-list warn line lists at most this many ids before
56
55
  * the `… and K more` suffix — a huge registry (thousands of rows) must not
57
- * produce a multi-KB log line (plan QC fix wave S-cap). Exported for the
56
+ * produce a multi-KB log line (cap). Exported for the
58
57
  * suite's cap assertions; module surface only — the entry's frozen 47-name
59
58
  * export surface deliberately does not re-export it.
60
59
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Capability probes for the OPTIONAL `dsh-llm-fallbacks` plugin (plan
3
- * `20260814-dsh-fallbacks-integration` Task 1 — probe foundation).
3
+ * Task 1 — probe foundation).
4
4
  *
5
5
  * The fallbacks plugin is an optional SEPARATE install (two-command
6
6
  * contract) and a dev-time-only dependency of this package: src carries
@@ -55,7 +55,7 @@ export declare function fallbacksService(ctx: Context): FallbacksServiceView | u
55
55
  * The fallbacks loader row when present and enabled (group rows skipped).
56
56
  * Unlike {@link fallbacksMounted}, NO live-fiber requirement: the entry is
57
57
  * declarative and `options.config` is set at entry creation, so the adoption
58
- * advisory (plan `20260815-dsh-fallbacks-personas` Task 4) can read the
58
+ * advisory can read the
59
59
  * deployment's row config even during HMR/fiber-swap windows — the advisory
60
60
  * caller gates on `fallbacksMounted` first.
61
61
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Zero-config seed declaration for the OPTIONAL `dsh-llm-fallbacks` plugin
3
- * (plan `20260816-dsh-b4-seeds` Task 2): when the `llm-fallbacks` service is
3
+ * : when the `llm-fallbacks` service is
4
4
  * applied, this module declares the 13 `mode: subagent` mstar roles into the
5
5
  * fallbacks seed registry — persona = mirror `description` (verbatim, the
6
6
  * SSOT stays `mstar-roles`) + one mandatory-load guide line.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Local structural mirrors of the consumed `dsh-llm-fallbacks` surface
3
- * (plan `20260831-dsh-alpha2-optional-fallbacks` Task 2). dsh natively
3
+ * . dsh natively
4
4
  * covers subagent customization, so the fallbacks
5
5
  * plugin is an OPTIONAL capability activated by the unchanged two-command
6
6
  * install contract — and a dev-time-only dependency of this package (type
@@ -4,7 +4,7 @@ import type { Config, HarnessResolver } from './_shared.ts';
4
4
  export declare const GOAL_BRIDGE_LOGGER = "mstar/goal-bridge";
5
5
  /**
6
6
  * Flat `maxGoalRounds` config fallback (architect decision — plan
7
- * `20260816-dsh-nb2-goal-bridge`): 256, aligned with the GoalService default
7
+ * ): 256, aligned with the GoalService default
8
8
  * (`goal/src/index.ts:187`) and ralph `maxRounds` (`tool-ralph/src/index.ts:37`).
9
9
  */
10
10
  export declare const DEFAULT_MAX_GOAL_ROUNDS = 256;
@@ -46,8 +46,7 @@ export interface GoalView extends GoalRefView {
46
46
  * index.ts:244-257`); `complete` is a CAS by `{ id, revision }`
47
47
  * (`GOAL_STALE_REVISION` on stale). The drift path uses complete+create
48
48
  * (never `edit`) so each new iteration gets a FRESH goal with a clean
49
- * round budget (plan QC fix wave — qc2 W-1 / qc3 F-001/F-008).
50
- */
49
+ * round budget. */
51
50
  export interface GoalsServiceView {
52
51
  get(agent: unknown): GoalView | undefined;
53
52
  create(agent: unknown, request: {
@@ -74,8 +73,7 @@ export declare function iterationGoalObjective(iterationId: string): string;
74
73
  * `status` is `active` or `locked` — the directory name IS the iteration id
75
74
  * (plan-conventions `{ITERATION_DIR}/<id>/`). Completed/status-less/archived
76
75
  * compasses do not steer. Silent on any read failure (advisory degrade).
77
- * Shared with the planMode bridge via explicit no-barrel import (Task 4b —
78
- * the same "is an active iteration steering" read).
76
+ * Shared with the planMode bridge via explicit no-barrel import (the same "is an active iteration steering" read).
79
77
  * @param harnessDir - the resolved `{HARNESS_DIR}`.
80
78
  */
81
79
  export declare function steeringCompass(harnessDir: string): {
@@ -115,13 +113,12 @@ export declare function mirrorIterationGoal(agent: unknown, input: MirrorIterati
115
113
  * first root-like ancestor. `undefined` when unresolvable (fork lineage,
116
114
  * non-in-process provider, registry gap, or a cycle) — the decision point
117
115
  * then silently skips. Cycle guard: a `seen` set over visited session ids
118
- * (the upstream `liveLineage` guard — plan QC fix wave qc2 W-2 / qc3
119
- * F-003) breaks on ANY revisited id — a 1-hop self-loop, a 2+ hop cycle
116
+ * (the upstream `liveLineage` guard) breaks on ANY revisited id — a 1-hop self-loop, a 2+ hop cycle
120
117
  * (A→B→A), or a longer malformed lineage — instead of spinning forever on
121
118
  * the synchronous `subagent/start` decision-point listeners (reachable via
122
119
  * HMR remounts, resumed/forked sessions with stale headers, or a future
123
120
  * host change). Shared with the planMode bridge via explicit no-barrel
124
- * import (Task 4b — the same `subagent/start` decision-point root walk).
121
+ * import (the same `subagent/start` decision-point root walk).
125
122
  */
126
123
  export declare function rootAgentOf(agent: unknown, agents: AgentsView): unknown | undefined;
127
124
  /**
@@ -131,7 +128,7 @@ export declare function rootAgentOf(agent: unknown, agents: AgentsView): unknown
131
128
  * decision point — index.ts advisory slot), resolving the delegating ROOT
132
129
  * via the `parentSession` walk — the two mirror edges are idempotent (get +
133
130
  * compare when the mirror is in place — no churn) — plus a THIRD, advisory
134
- * listener on the `session/event` firehose (Task 3): a `goal/change`
131
+ * listener on the `session/event` firehose : a `goal/change`
135
132
  * envelope whose goal is blocked logs ONE warn (code + objective summary +
136
133
  * project-register residual pointer) with ZERO harness writes
137
134
  * (the one-way mirror; see {@link warnBlockedGoal}). The goals service is an
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Native-first role-persona delivery (plan `20260831-dsh-alpha2-optional-fallbacks`
3
- * Task 3): a role-matched subagent start merges the persona into the request's
2
+ * Native-first role-persona delivery : a role-matched subagent start merges the persona into the request's
4
3
  * NATIVE `persona` slot (`@deepseek-ai/dsh-subagent`
5
4
  * `SubagentStartRequest.persona`) — the additive `mstar:role-persona`
6
5
  * system-prompt section is gone. Native semantics: the request persona
@@ -37,7 +36,7 @@
37
36
  * parsers the dispatch gate uses (`assignmentHeaderRegion` +
38
37
  * `parseAssignmentFields`) — over the start request's prompt text (the
39
38
  * `ContentBlock[]` the child receives as its first user message). Persona
40
- * lookup (plan `20260815-dsh-fallbacks-personas` Task 3) is the single
39
+ * lookup is the single
41
40
  * {@link personaFor} surface — `Config.rolePersonas[executeAs]` →
42
41
  * `harness-agents/` mirror default → skip (never gated on `roleMap` or on
43
42
  * the fallbacks mounted state: persona delivery is fallbacks-independent).
@@ -56,9 +56,21 @@ export declare class SkillLintVetoError extends Error {
56
56
  * CLI `mstar skill lint` combination plus the ephemeral-citation gate;
57
57
  * violation codes `lint.frontmatter.*` / `skill-authoring.five-question.*`
58
58
  * / `skill.ephemeral.*`). Pure: no enforcement, no I/O.
59
+ *
60
+ * Five-question profile (spec A4): the shared Engine classifier
61
+ * (`classifySkillLint`) selects the mode from `options.skillId` — the
62
+ * trusted resolved skill-target basename passed by the fs-intent path and
63
+ * `lintSkillWrite`. A doc-only call (no `skillId`) stays strict authoring —
64
+ * the greenfield default is never loosened by an unparented document. The
65
+ * frontmatter and ephemeral-citation checks run in every profile; `core`
66
+ * (exact `mstar-harness-core`) skips only the five-question check.
59
67
  * @param doc - the full SKILL.md text.
68
+ * @param options - `skillId`: the resolved skill-target directory basename
69
+ * (trusted boundary identity — never the doc's YAML `name` alone).
60
70
  */
61
- export declare function lintSkillDoc(doc: string): GateResult;
71
+ export declare function lintSkillDoc(doc: string, options?: {
72
+ skillId?: string;
73
+ }): GateResult;
62
74
  /**
63
75
  * Enforce the skill-authoring lints over a KNOWN document (the brief's
64
76
  * "incoming doc when available" branch): `Enforcement: hard` + violations →
@@ -68,8 +80,13 @@ export declare function lintSkillDoc(doc: string): GateResult;
68
80
  * needed on this branch. The content-blind listener path (where the
69
81
  * incoming doc is never visible) routes through {@link gateSkillIntent}
70
82
  * instead, which applies the status-gate repair-escape decision.
83
+ *
84
+ * The lint profile is classified from the trusted resolved skill-target
85
+ * basename (spec A4): `basename(dirname(resolve(options.target)))` — the
86
+ * write's own target, never the document's YAML `name`.
71
87
  * @param doc - the document about to be written (the write's content).
72
- * @param options - target display path (veto message) + resolved hard flag.
88
+ * @param options - target display path (veto message + profile identity) +
89
+ * resolved hard flag.
73
90
  */
74
91
  export declare function lintSkillWrite(doc: string, options: {
75
92
  target: string;
@@ -1,11 +1,8 @@
1
1
  /**
2
- * Harness-rules system-prompt injection (plan `20260816-dsh-nb1-systemprompt`
3
- * Task 2): the root session's ONE `mstar:harness-rules` pointer section plus
4
- * the `mstar:engine-status` runtime-context summary, both registered on the
5
- * GLOBAL prompt layer — visible to the root session AND every dispatched
2
+ * Harness-rules system-prompt injection (visible to the root session AND every dispatched
6
3
  * child — on their own names and layers (the child persona rides the NATIVE
7
4
  * subagent persona channel since plan
8
- * `20260831-dsh-alpha2-optional-fallbacks` Task 3 — no child-scoped
5
+ * Task 3 — no child-scoped
9
6
  * `mstar:role-persona` section exists anymore; duplicate-name throws remain
10
7
  * per name per layer, verified `scope/src/store.ts`).
11
8
  *
@@ -18,13 +15,13 @@
18
15
  * interpolation and throws on unknown/malformed/undefined references
19
16
  * (`interpolate` in `@deepseek-ai/dsh-system-prompt`), so every injected
20
17
  * string must carry no complete group. The mechanism is LIVE, not static
21
- * (plan QC fix wave W-1): every operator-controlled value embedded below
18
+ * : every operator-controlled value embedded below
22
19
  * (harness dir, plan ids, iteration id, lease fields, direction prose)
23
20
  * is passed through `stripInterpolationHazard` — complete `{{…}}` groups
24
21
  * are screened so a hostile value can never break prompt assembly, while
25
22
  * a lone `{{` stays literal prose.
26
23
  * - The harness dir is resolved PER ASSEMBLY from the assembly context's
27
- * agent (plan QC fix wave W-2 — the catalog pre-step precedent): the
24
+ * agent : the
28
25
  * session cwd of the agent whose prompt is being assembled, via
29
26
  * `resolver.forAgent`, with the boot value (`forWorkspace(undefined)`,
30
27
  * the explicit config or null) as the fallback when the assembly carries
@@ -39,13 +36,12 @@
39
36
  * re-registration, in zero-config and explicit-config deployments alike.
40
37
  * - The context provider reuses the catalog's unified machine-summary
41
38
  * source (`buildCatalogSources` — the SAME builder the engine-status
42
- * pre-step catalog row uses) and projects the SLIM digest (plan
43
- * `20260820-dsh-engine-status-slim` Task 2): the version watermark
39
+ * pre-step catalog row uses) and projects the SLIM digest: the version watermark
44
40
  * ALWAYS, plus ONE `workflow … | plans: …` line only when the active set
45
41
  * selects a lifecycle (`state.selection.kind === 'active'`). Harness dir
46
42
  * and enforcement live in `mstar:harness-rules`; residuals / leases /
47
43
  * direction / iteration-gate detail stay exclusive to the pre-step row.
48
- * v3 (plan `20260819-workflow-dsh-viz` Task 3): the
44
+ * v3 : the
49
45
  * digest reads ONLY the catalog row (`state` — itself aggregated from the
50
46
  * SELECTED workflow snapshot + project registers) — no direct
51
47
  * status.json / snapshot file reads to change. The build is TTL-memoized
@@ -64,7 +60,7 @@
64
60
  * - Registration is deferred through `ctx.inject(['systemPrompt'], …)`
65
61
  * (HMR-safe re-apply): the `section()`/`context()` calls run on the
66
62
  * inject child, and the exact disposers they return are collected on
67
- * that child via `systemPromptCtx.effect` (plan QC fix wave W-HMR) — the
63
+ * that child via `systemPromptCtx.effect` — the
68
64
  * registrations therefore unwind with THIS plugin's apply by explicit
69
65
  * ownership, so a re-apply disposes the old registrations before
70
66
  * registering fresh ones (no duplicate-name throw, no stale closure from
@@ -18,7 +18,7 @@ import { HarnessResolver } from './_shared.ts';
18
18
  export declare function registerSddIterationTools(ctx: Context, resolver: HarnessResolver): void;
19
19
  /**
20
20
  * Register the on-demand seam validation tools (
21
- * 20260808-dsh-seams-bundle): `mstar design-md validate` / `mstar compound
21
+ * : `mstar design-md validate` / `mstar compound
22
22
  * validate` CLI mirrors plus the audit / roles validators — thin wrappers
23
23
  * running the engine in-app. The registrations are deferred with
24
24
  * `ctx.inject(['tools'], …)` (same optional-unit pattern as the sdd tools),
@@ -1,7 +1,5 @@
1
1
  /**
2
- * Workflow-ledger session-event consumer (plan `20260815-dsh-workflow-ledger`
3
- * Task 3 — the W-B2 producer half).
4
- *
2
+ * Workflow-ledger session-event consumer. *
5
3
  * Source of record: the durable `tool-workflow/*` session events appended
6
4
  * into the CALLING PARENT session's log (top-level runs only — nested
7
5
  * transport calls record nothing upstream; Task 1 seam notes §4). The
@@ -19,9 +17,8 @@
19
17
  * forked conversation — `session/created` fires after the seed enters
20
18
  * the log, upstream `session/src/index.ts:961-995`) gets its snapshot
21
19
  * cold-scanned ONCE on the creation announcement, closing the
22
- * late-seeded-session gap (qc3 S-304 / qc2 W-1a).
23
- *
24
- * DEDUPE (qc2 W-1 / qc3 F-301 fix-wave): ONE DURABLE per-session watermark —
20
+ * late-seeded-session gap. *
21
+ * DEDUPE : ONE DURABLE per-session watermark —
25
22
  * the next expected envelope `seq` (session-log position) — persisted to
26
23
  * `{HARNESS_DIR}/workflows/<id>/workflow-ledger-cursors.json` (a small
27
24
  * bounded sidecar next to the workflow-dir `agent-flow.jsonl`, written
@@ -31,17 +28,16 @@
31
28
  * created-backfill / live): envelopes with `seq` below it were already
32
29
  * recorded — across cold+live overlap AND across plugin re-applies (a
33
30
  * re-registration no longer re-records the same live sessions). The
34
- * watermark advances only AFTER the ledger row appended successfully (qc3
35
- * R-401 — a failing append leaves the cursor behind, so the row is
36
- * re-attempted at the next scan, never permanently lost). The in-memory
31
+ * watermark advances only AFTER the ledger row appended successfully (a failing append leaves the cursor behind, so the
32
+ * row is re-attempted at the next scan, never permanently lost). The in-memory
37
33
  * Map is the durable file's mirror (module-level cache keyed by WORKFLOW
38
34
  * DIR, bounded by the session cap AND by a workflow-dir count cap — qc3
39
35
  * S-4 — so a long-lived process across many workflow ids never grows the
40
36
  * cache unbounded); a failed durable write keeps the in-memory mirror
41
- * advanced (in-process dedupe — qc3 S-6) with one warn — a ledger row is
37
+ * advanced (in-process dedupe —) with one warn — a ledger row is
42
38
  * never lost and the workflow run is never affected.
43
39
  *
44
- * INTER-PROCESS SERIALIZATION (qc3 W-1 fix-wave): the watermark
40
+ * INTER-PROCESS SERIALIZATION : the watermark
45
41
  * read-modify-write (load fresh → mutate → whole-map save) runs inside the
46
42
  * per-workflow write lock shared with the ledger append
47
43
  * (`withWorkflowDirLock` from agent-flow.ts — the same lockdir pattern as
@@ -52,16 +48,15 @@
52
48
  * process's just-advanced cursor (the duplicate-row regression mode). The
53
49
  * lock is held only around the bounded cursor update, never across scans.
54
50
  *
55
- * Mapping (Task 2 schema): `tool-workflow/run-start` → `workflow-run`
51
+ * Mapping: `tool-workflow/run-start` → `workflow-run`
56
52
  * (`agent` = the carrying parent session id), `tool-workflow/agent-start` →
57
53
  * `workflow-agent` (`childId` preserved), `tool-workflow/run-end` →
58
54
  * `workflow-run-end`. `tool-workflow/agent-end` is upstream MEMBER
59
- * bookkeeping with no ledger kind (Task 2 handoff + plan Interfaces — the
55
+ * bookkeeping with no ledger kind (the
60
56
  * member `outcome` is intentionally not persisted) and is filtered out.
61
57
  * `ts` takes the envelope's `time`.
62
58
  *
63
- * P-c answer observation (plan `20260815-dsh-workflow-gate` Task 4 fold-in —
64
- * the Task-2 Important handoff): the workflow GATE cannot observe the ask
59
+ * P-c answer observation : the workflow GATE cannot observe the ask
65
60
  * outcome — the tool registry's `serviceAsk` consumes the approval result
66
61
  * internally, and the gate invents no answerer. The run-start observation
67
62
  * IS the answer seam: when the approval waterfall ALLOWS a workflow call,
@@ -69,7 +64,7 @@
69
64
  * (name carried) lands in the parent session log — the consumer maps it to
70
65
  * the `workflow-run` row AND records `allow` for the run name into the
71
66
  * apply-scoped {@link WorkflowAskCache} (`registerWorkflowLedger`'s third
72
- * parameter — the host adapter's instance). W-1 (qc2 fix-wave): the record
67
+ * parameter — the host adapter's instance). the record
73
68
  * fires ONLY for names the policy marked asked in this apply
74
69
  * (`WorkflowAskCache.markAsked` on every ask verdict; the observation
75
70
  * promotes via `wasAsked`) — a run observed without a prior ask (P-b
@@ -107,8 +102,8 @@ import type { WorkflowAskCache } from './workflow-policy.ts';
107
102
  /** Logger label for the workflow-ledger consumer (dsh logger naming: `<scope>/<subject>`). */
108
103
  export declare const WORKFLOW_LEDGER_LOGGER = "mstar/workflow-ledger";
109
104
  /**
110
- * The durable watermark file name under the WORKFLOW dir (qc2 W-1 / qc3
111
- * F-301 fix-wave): `{ "v": 1, "cursors": { "<sessionId>": <nextSeq> } }` —
105
+ * The durable watermark file name under the WORKFLOW dir (/ qc3
106
+ * F-301 : `{ "v": 1, "cursors": { "<sessionId>": <nextSeq> } }` —
112
107
  * the next expected envelope seq per session id. Written atomically
113
108
  * (temp-file + rename) after every recorded workflow row; read lazily per
114
109
  * workflow dir (module-level cache). v3 layout: the sidecar lives in the
@@ -126,8 +121,7 @@ export declare const WORKFLOW_LEDGER_WATERMARK_FILE = "workflow-ledger-cursors.j
126
121
  */
127
122
  export declare const WORKFLOW_LEDGER_WATERMARK_MAX_SESSIONS = 256;
128
123
  /**
129
- * Workflow-dir count cap for the module-level watermark cache (qc3 S-4
130
- * fix-wave): a long-lived process can touch many workflow ids over its
124
+ * Workflow-dir count cap for the module-level watermark cache: a long-lived process can touch many workflow ids over its
131
125
  * lifetime (each iteration lifecycle creates a new workflow dir) — the
132
126
  * cache evicts the OLDEST cached dir when it exceeds this cap. The file is
133
127
  * the durable store; the cache is only a mirror, so an evicted dir is
@@ -144,12 +138,11 @@ export type WorkflowLedgerLogSink = (level: WorkflowLedgerLogLevel, message: str
144
138
  * can restore it (test pattern: agent-flow `setAgentFlowLogger`).
145
139
  */
146
140
  export declare function setWorkflowLedgerLogger(sink: WorkflowLedgerLogSink): WorkflowLedgerLogSink;
147
- /** The number of workflow dirs currently mirrored in the module-level watermark cache (qc3 S-4 observability). */
148
- export declare function workflowLedgerWatermarkCacheSize(): number;
141
+ /** The number of workflow dirs currently mirrored in the module-level watermark cache */ export declare function workflowLedgerWatermarkCacheSize(): number;
149
142
  /**
150
143
  * Advance one session's watermark entry to `nextSeq` and persist. Runs the
151
144
  * whole read-modify-write under the per-workflow inter-process lock
152
- * (qc3 W-1 fix-wave — same lock as the ledger append): the fresh load
145
+ * (same lock as the ledger append): the fresh load
153
146
  * starts from the latest durable cursors, so two processes sharing one
154
147
  * lifecycle never clobber each other's advances; the session entry is
155
148
  * monotonic (`Math.max` — a stale concurrent advance never regresses an
@@ -161,7 +154,7 @@ export declare function workflowLedgerWatermarkCacheSize(): number;
161
154
  * evicted session re-records) is bounded by the cap and documented in the
162
155
  * README.
163
156
  *
164
- * DEGRADED PATH (qc3 S-6 fix-wave): a lock timeout (another writer stuck
157
+ * DEGRADED PATH : a lock timeout (another writer stuck
165
158
  * for the full timeout — a crashed/stuck peer), a reentrancy error, or a
166
159
  * throwing critical section leaves the durable file untouched, but the
167
160
  * in-memory mirror is STILL advanced (the same monotonic `Math.max`;
@@ -189,7 +182,7 @@ export declare function advanceWatermark(workflowDir: string, sid: string, nextS
189
182
  }): void;
190
183
  /**
191
184
  * Register the workflow-ledger consumer: (1) a `session/created` backfill
192
- * listener (registered FIRST — qc3 S-305 — so no apply-time window exists
185
+ * listener (registered FIRST — — so no apply-time window exists
193
186
  * between the snapshot and the attach); (2) a bounded cold scan over
194
187
  * `ctx.sessions.list()` reading each session's `events` snapshot for
195
188
  * `tool-workflow/*` rows (covers pre-restart runs — constructor-seeded
@@ -199,10 +192,10 @@ export declare function advanceWatermark(workflowDir: string, sid: string, nextS
199
192
  * persisted to `{HARNESS_DIR}/workflows/<id>/workflow-ledger-cursors.json` —
200
193
  * the ACTIVE workflow dir, never the root) — re-applies
201
194
  * never duplicate; no other cache. The watermark advances only AFTER a
202
- * successful ledger append (qc3 R-401 — a failing append leaves the cursor
195
+ * successful ledger append (a failing append leaves the cursor
203
196
  * behind so the row is re-attempted at the next scan, never lost). Every
204
197
  * read/append is try/catch-contained — including `sessions.list()` itself
205
- * (qc2 S-7: one warn, the cold scan skipped, the consumer stays live); the
198
+ * (one warn, the cold scan skipped, the consumer stays live); the
206
199
  * `sessions` service absent → one debug log + consumer disabled (composition
207
200
  * without dsh-session). All appends go through `recordWorkflowEvent` (itself
208
201
  * fully contained — a failing ledger write never crashes or alters a
@@ -212,7 +205,7 @@ export declare function advanceWatermark(workflowDir: string, sid: string, nextS
212
205
  * @param resolver - the shared per-workspace `{HARNESS_DIR}` resolver
213
206
  * (harnessDir attribution from the carrying session's `header.cwd`).
214
207
  * @param workflowAskCache - the apply-scoped P-c ask cache (plan
215
- * `20260815-dsh-workflow-gate` Task 4 fold-in — the host adapter's
208
+ * Task 4 fold-in — the host adapter's
216
209
  * instance; see the module doc "P-c answer observation"). Absent → the
217
210
  * observation hook is disabled (W-B2 tests / compositions without the
218
211
  * workflow gate).
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * Workflow/ralph gate policy — the P-a name allowlist + P-b lease
3
- * attribution + P-c first-seen ask (plan `20260815-dsh-workflow-gate`
4
- * Tasks 2–3, W-B3). The policy is the SINGLE
3
+ * attribution + P-c first-seen ask . The policy is the SINGLE
5
4
  * decision point for the four-tier `workflowGate` mode semantics
6
5
  * (`off | warn | ask | hard`, default `warn`): it turns one composed
7
- * {@link WorkflowGateInput} (Task 1) into `allow | warn | ask | deny` + a
6
+ * {@link WorkflowGateInput} into `allow | warn | ask | deny` + a
8
7
  * reason. The dispatch-gate listener maps the verdict to the
9
8
  * `tools/pre-execute` refusal vocabulary (`PreToolDecision`) — this module
10
9
  * NEVER throws and NEVER builds an approval path: an `ask` verdict flows
@@ -21,7 +20,7 @@
21
20
  * | ralph (no `meta.name`), covered/read-only | any | allow — P-a/P-c NEVER apply to ralph (no allowlist identity); P-b applies |
22
21
  * | workflow, name ∈ `workflowNames` (non-empty list), covered | any | allow — the allowlist passes under every mode |
23
22
  * | workflow, unknown (empty/absent list ⇒ EVERY name unknown), covered | `off` | allow — the gate short-circuits `off` before the policy; kept here for a total policy |
24
- * | workflow, unknown, covered | `warn` | warn — advisory + one warn (Task 1 behavior, now centralized) |
23
+ * | workflow, unknown, covered | `warn` | warn — advisory + one warn (centralized) |
25
24
  * | workflow, unknown, covered | `hard` | deny — reason names the workflow name, veto before any child starts |
26
25
  * | workflow, unknown, covered, first-seen (no cached decision) | `ask` | ask — `{kind:'ask'}` through the approval waterfall + the name is marked asked (W-1 — the run-start observation promotes only asked names to allow) |
27
26
  * | workflow, unknown, covered, cached allow | `ask` | allow — cached decision, NO re-ask |
@@ -34,8 +33,7 @@
34
33
  * and a fresh apply starts with an empty cache. The cache records only
35
34
  * RESOLVED decisions (`allow` | `deny`) keyed by workflow name.
36
35
  *
37
- * Cache-key normalization (Task 5 fold-in — the Task-4 Important congruence
38
- * fix): every key — the gate's `metaName` (composed through
36
+ * Cache-key normalization (the congruence fix): every key — the gate's `metaName` (composed through
39
37
  * {@link normalizeWorkflowName} in dispatch.ts `workflowGateInputOf`), the
40
38
  * run-start observation's `runName` (workflow-ledger.ts), and the explicit
41
39
  * `record()` / `markAsked()` APIs (which normalize internally, F-302) — is
@@ -50,15 +48,14 @@
50
48
  * `serviceAsk` consumes the approval result internally (`deepseek-harness
51
49
  * packages/core/tools/src/index.ts`, `prepareExecution`/`serviceAsk`) — so
52
50
  * the ANSWER reaches the cache through the workflow-ledger consumer's
53
- * run-start observation (plan `20260815-dsh-workflow-gate` Task 4 fold-in —
54
- * the Task-2 Important handoff): an ALLOWED ask executes the call, the
51
+ * run-start observation : an ALLOWED ask executes the call, the
55
52
  * durable `tool-workflow/run-start` session event carries the run name, and
56
53
  * the consumer records `allow` for it (`workflow-ledger.ts`). The policy
57
54
  * marks every name that received an `ask` verdict in this apply
58
55
  * (`markAsked`, at the single ask point), and the observation promotes ONLY
59
56
  * marked names to `allow` — a run observed WITHOUT a prior ask (a P-b
60
57
  * advisory under `ask` mode, a `warn`/`off`-mode run) is NOT an approval
61
- * resolution and never pre-authorizes the name (qc2 W-1). A DENIED answer
58
+ * resolution and never pre-authorizes the name . A DENIED answer
62
59
  * produces no run → no observation → the next same-name call re-asks
63
60
  * (fail-closed — no grant evidence, never an invented allow). The explicit
64
61
  * `record()` API stays the general seam — an answerer integration or the
@@ -69,7 +66,7 @@
69
66
  * (`WorkflowGateInput` — erased at runtime, no cycle); dispatch.ts imports
70
67
  * the policy/cache values from here. The P-a vocabulary
71
68
  * (`workflowNameUnknown`, `WORKFLOW_NAME_UNKNOWN_CODE`) centralized HERE from
72
- * Task 1's dispatch.ts.
69
+ * 's dispatch.ts.
73
70
  */
74
71
  import type { Config } from './_shared.ts';
75
72
  import type { WorkflowGateInput } from './dispatch.ts';
@@ -81,16 +78,15 @@ import type { WorkflowGateInput } from './dispatch.ts';
81
78
  export declare const WORKFLOW_NAME_UNKNOWN_CODE = "workflow.name.unknown";
82
79
  /**
83
80
  * The workflow-gate advisory/deny violation code for P-b lease attribution
84
- * (Task 3): the calling workspace has an `InProgress` plan without
81
+ * : the calling workspace has an `InProgress` plan without
85
82
  * `execution_lease` coverage (warn-mode advisory / hard-mode veto reason —
86
83
  * the reason cites the uncovered plan id).
87
84
  */
88
85
  export declare const WORKFLOW_LEASE_UNCOVERED_CODE = "workflow.lease.uncovered";
89
86
  /**
90
87
  * Strip ASCII control characters (newlines / tabs / CR — the log-forging
91
- * surface, qc2 S-1) from one workflow name. THE shared P-c cache-key
92
- * normalization (plan `20260815-dsh-workflow-gate` Task 5 fold-in — the
93
- * Task-4 Important congruence fix): the gate's `metaName` (composed in
88
+ * surface( from one workflow name. THE shared P-c cache-key
89
+ * normalization : the gate's `metaName` (composed in
94
90
  * dispatch.ts `workflowGateInputOf`) and the run-start observation's
95
91
  * `runName` (workflow-ledger.ts) MUST key the ask cache through the SAME
96
92
  * function — a raw-vs-stripped mismatch (e.g. `au\u0000dit` gating under
@@ -108,7 +104,7 @@ export declare function normalizeWorkflowName(value: string): string;
108
104
  * `meta.name` — P-a never applies to them (callers guard on
109
105
  * `input.metaName !== undefined` first).
110
106
  *
111
- * Comparison boundary (qc1-S2): entries are normalized through
107
+ * Comparison boundary: entries are normalized through
112
108
  * {@link normalizeWorkflowName} BEFORE the comparison — the gate's
113
109
  * `metaName` is already stripped, so an operator-pasted control-char
114
110
  * variant (trailing newline, copied config value) matches the same
@@ -124,7 +120,7 @@ export type WorkflowAskCacheDecision = 'allow' | 'deny';
124
120
  * see the module doc for the lifecycle). Records ONLY resolved decisions; a
125
121
  * miss means first-seen (or an unanswered ask) → the policy asks again.
126
122
  *
127
- * W-1 (qc2 fix-wave): the cache ALSO tracks which names received an `ask`
123
+ * The cache ALSO tracks which names received an `ask`
128
124
  * verdict in this apply ({@link markAsked} — the gate marks EVERY ask
129
125
  * decision at the policy's single ask point). The run-start observation
130
126
  * (workflow-ledger.ts) records `allow` ONLY for names marked-asked — a run
@@ -132,7 +128,7 @@ export type WorkflowAskCacheDecision = 'allow' | 'deny';
132
128
  * `warn`/`off`-mode run) is NOT an approval resolution and must not
133
129
  * pre-authorize the name.
134
130
  *
135
- * F-302 (qc3 fix-wave): the WRITE seams ({@link record} / {@link markAsked})
131
+ * The WRITE seams ({@link record} / {@link markAsked})
136
132
  * normalize their keys internally — the "ONE shared normalization" contract
137
133
  * holds even for a caller that passes a raw spelling (today's production
138
134
  * callers already normalize before calling; this is defense-in-depth for the
@@ -163,7 +159,7 @@ export declare class WorkflowAskCache {
163
159
  /** Whether `name` received an `ask` verdict in this apply (the observation's promote gate). Normalizes internally. */
164
160
  wasAsked(name: string): boolean;
165
161
  }
166
- /** The four-tier policy decision vocabulary (plan W-B3, Task 2). */
162
+ /** The four-tier policy decision vocabulary (plan W-B3). */
167
163
  export type WorkflowPolicyDecision = 'allow' | 'warn' | 'ask' | 'deny';
168
164
  /**
169
165
  * One policy verdict: the decision + a human-readable reason + the violation
@@ -181,7 +177,7 @@ export type WorkflowPolicyVerdict = {
181
177
  };
182
178
  /**
183
179
  * The workflow/ralph gate policy — P-a name allowlist + P-c first-seen ask
184
- * (plan `20260815-dsh-workflow-gate` Task 2). `config` + cache + composed
180
+ * . `config` + cache + composed
185
181
  * input → verdict; the caller (dispatch gate) maps the verdict to the
186
182
  * `PreToolDecision` refusal vocabulary and owns the advisory emit/log
187
183
  * infrastructure. The ONE cache write is contained: an `ask` verdict marks
@@ -2,7 +2,7 @@ import type { WorkflowSelectionView } from '../types.ts';
2
2
  /** The active-set resolver result: the first active lifecycle or a clear error. */
3
3
  export type ActiveWorkflowSelection = WorkflowSelectionView;
4
4
  /**
5
- * Test-only observability hook (plan 20260822-gate-fixes Task 3 / f12):
5
+ * Test-only observability hook :
6
6
  * whether a snapshot path is still cached. Production code never calls
7
7
  * this — the eviction contract (delete → key gone) is asserted by the
8
8
  * workflow-selection spec.
@@ -15,8 +15,8 @@ export declare function _terminalStatusCacheHas(snapshotPath: string): boolean;
15
15
  * entry → a clear error, never a terminal snapshot and never the root v1
16
16
  * file.
17
17
  *
18
- * Active-set definition (explicit decision, plan `20260819-workflow-dsh-viz`
19
- * Task 2): membership in `workflows[]` — the engine lifecycle enum's
18
+ * Active-set definition (explicit decision,
19
+ * membership in `workflows[]` — the engine lifecycle enum's
20
20
  * non-terminal states are `running` AND `paused` (terminal lifecycles are
21
21
  * removed from the list at terminal). A PAUSED lifecycle therefore stays in
22
22
  * the active set and the agent-flow writer / ledger append to its workflow