@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.
- package/README.md +4 -6
- package/README.zh.md +3 -3
- package/dist/client/panel/PanelView.d.ts +8 -11
- package/dist/client/panel/TabNav.d.ts +2 -2
- package/dist/client/panel/graph/event-log.d.ts +5 -9
- package/dist/client/panel/graph/project-graph.d.ts +53 -72
- package/dist/client/panel/graph/schema.d.ts +31 -37
- package/dist/client/panel/locale.d.ts +19 -19
- package/dist/client/panel/pages/AgentCanvasPage.d.ts +40 -58
- package/dist/client/panel/pages/EventLogPage.d.ts +6 -6
- package/dist/client/panel/pages/IterationInfoSection.d.ts +9 -11
- package/dist/client/panel/pages/IterationTaskPage.d.ts +3 -3
- package/dist/client/panel/plan-sort.d.ts +3 -6
- package/dist/client/panel/state-section.d.ts +1 -1
- package/dist/client/panel/zones/Legend.d.ts +2 -2
- package/dist/client/panel/zones/ProjectRollup.d.ts +1 -2
- package/dist/client/panel/zones/TaskBoard.d.ts +1 -2
- package/dist/gates/_shared.d.ts +7 -10
- package/dist/gates/adapter.d.ts +6 -9
- package/dist/gates/agent-flow.d.ts +49 -59
- package/dist/gates/agent-personas.d.ts +1 -2
- package/dist/gates/catalog.d.ts +2 -5
- package/dist/gates/dispatch.d.ts +9 -11
- package/dist/gates/fallbacks-advisory.d.ts +2 -3
- package/dist/gates/fallbacks-probe.d.ts +2 -2
- package/dist/gates/fallbacks-seeds.d.ts +1 -1
- package/dist/gates/fallbacks-structural.d.ts +1 -1
- package/dist/gates/goal-bridge.d.ts +6 -9
- package/dist/gates/role-persona.d.ts +2 -3
- package/dist/gates/skill-lint.d.ts +19 -2
- package/dist/gates/system-prompt.d.ts +7 -11
- package/dist/gates/tools.d.ts +1 -1
- package/dist/gates/workflow-ledger.d.ts +21 -28
- package/dist/gates/workflow-policy.d.ts +15 -19
- package/dist/gates/workflow-selection.d.ts +3 -3
- package/dist/index.js +215 -33
- package/dist/types.d.ts +4 -7
- package/harness-commands/iteration-drive.md +6 -6
- package/harness-commands/iteration-loop.md +7 -7
- package/harness-commands/iteration-start.md +8 -8
- package/harness-skills/mstar-coding-behavior/SKILL.md +3 -20
- package/harness-skills/mstar-dispatch-gates/SKILL.md +7 -13
- package/harness-skills/mstar-dispatch-gates/references/leaf-executor-checklist.md +1 -1
- package/harness-skills/mstar-harness-core/SKILL.md +9 -53
- package/harness-skills/mstar-host/references/zcode.md +1 -0
- package/harness-skills/mstar-iteration/SKILL.md +32 -318
- package/harness-skills/mstar-iteration/references/command-shared-invariants.md +1 -1
- package/harness-skills/mstar-iteration/references/phase-1-prepare.md +155 -0
- package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +113 -3
- package/harness-skills/mstar-iteration/references/phase5-helper-discovery.md +1 -1
- package/harness-skills/mstar-roles/SKILL.md +14 -12
- package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +5 -6
- package/harness-skills/mstar-roles/references/architect.md +1 -1
- package/harness-skills/mstar-roles/references/code-reviewer.md +11 -1
- package/harness-skills/mstar-roles/references/frontend-dev.md +1 -1
- package/harness-skills/mstar-roles/references/fullstack-dev-shared.md +1 -1
- package/harness-skills/mstar-roles/references/ops-engineer.md +1 -1
- package/harness-skills/mstar-roles/references/product-manager.md +1 -1
- package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +4 -0
- package/harness-skills/mstar-roles/references/project-manager.md +6 -4
- package/harness-skills/mstar-roles/references/prompt-engineer.md +1 -1
- package/harness-skills/mstar-roles/references/qa-engineer.md +1 -1
- package/harness-skills/mstar-roles/references/qc-specialist-shared.md +1 -1
- package/harness-skills/mstar-roles/references/writing-specialist.md +1 -1
- package/harness-skills/mstar-sdd/references/file-handoffs.md +40 -7
- package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +9 -0
- package/harness-skills/mstar-sdd/references/implementer-prompt.md +9 -0
- package/harness-skills/mstar-sdd/references/task-reviewer-prompt.md +7 -0
- package/package.json +1 -1
package/dist/gates/dispatch.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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 —
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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 (
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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 (
|
|
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
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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`
|
|
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
|
package/dist/gates/tools.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
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
|
|
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 (
|
|
35
|
-
*
|
|
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 —
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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).
|
|
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 (
|
|
111
|
-
* F-301
|
|
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
|
|
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
|
|
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
|
-
* (
|
|
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
|
|
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 —
|
|
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 (
|
|
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
|
-
* (
|
|
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
|
-
*
|
|
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
|
|
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}
|
|
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 (
|
|
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 (
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
92
|
-
* normalization
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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,
|
|
19
|
-
*
|
|
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
|