@mstar-harness/dsh 3.8.1 → 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.
- package/README.i18n.yaml +2 -2
- package/README.md +16 -6
- package/README.zh.md +16 -6
- package/dist/client/panel/engine-status-client.d.ts +84 -6
- package/dist/client/panel/graph/project-graph.d.ts +26 -13
- package/dist/client/panel/guards.d.ts +41 -1
- package/dist/client/panel/locale.d.ts +1 -1
- package/dist/client/panel/pages/AgentListPage.d.ts +1 -1
- package/dist/client/panel/sidebar.d.ts +3 -2
- package/dist/client/panel/state-section.d.ts +25 -3
- package/dist/client/panel/use-mstar-engine-status.d.ts +28 -4
- package/dist/client.js +346 -48
- package/dist/engine-status-endpoint.d.ts +85 -8
- package/dist/engine-status-store.d.ts +91 -1
- package/dist/engine-status-wire.d.ts +9 -0
- package/dist/gates/_shared.d.ts +61 -9
- package/dist/gates/adapter.d.ts +32 -2
- package/dist/gates/agent-flow.d.ts +312 -60
- package/dist/gates/catalog.d.ts +58 -37
- package/dist/gates/dispatch.d.ts +11 -2
- package/dist/gates/goal-bridge.d.ts +10 -130
- package/dist/gates/plan-mode-bridge.d.ts +20 -11
- package/dist/gates/role-persona.d.ts +16 -0
- package/dist/gates/steering.d.ts +41 -0
- package/dist/gates/workflow-ledger.d.ts +31 -4
- package/dist/gates/workflow-selection.d.ts +41 -20
- package/dist/index.js +1206 -392
- package/dist/types.d.ts +36 -11
- package/harness-commands/amazing-pr-review.md +2 -0
- package/harness-commands/codebase-audit.md +2 -0
- package/harness-skills/mstar-host/SKILL.md +3 -1
- package/harness-skills/mstar-host/references/dsh-workflow-scripts.md +424 -0
- package/harness-skills/mstar-host/references/dsh.md +170 -43
- package/harness-skills/mstar-roles/references/project-manager.md +2 -0
- package/harness-skills/mstar-sdd/SKILL.md +2 -0
- package/package.json +2 -2
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
* HARD constraint — headless boot safety: this module is reachable from
|
|
21
21
|
* `apply`, and it must never make the host row statically inject `connection`
|
|
22
22
|
* or `webServer`. Everything web-only is inside the optional inject child; the
|
|
23
|
-
* endpoint's own reads (`ctx.get('sessions')`, `ctx.get('
|
|
24
|
-
* are structural and degrade when the service
|
|
23
|
+
* endpoint's own reads (`ctx.get('sessions')`, `ctx.get('agents')`,
|
|
24
|
+
* `ctx.get('sessionController')`) are structural and degrade when the service
|
|
25
|
+
* is absent.
|
|
25
26
|
*
|
|
26
27
|
* VALIDATION CHAIN — the endpoint serves ONE session's snapshot and answers
|
|
27
28
|
* otherwise. In order:
|
|
@@ -37,14 +38,33 @@
|
|
|
37
38
|
* another session's data, never a silently-close match, never a path built from
|
|
38
39
|
* unvalidated input.
|
|
39
40
|
*
|
|
41
|
+
* The response additionally carries the session's CURRENT control-state
|
|
42
|
+
* selection (`binding.selection`, D4) — server-resolved from the durable
|
|
43
|
+
* picker record + the verified live Agent — so the panel can show the chosen
|
|
44
|
+
* active id while `payload` / `at` / `turn` keep naming the LAST MODEL
|
|
45
|
+
* EMISSION. The `selectWorkflow` UI control (D4) is the write half: a LIVE
|
|
46
|
+
* session, an exact cwd, an ACTIVE workflow id, automatic-binding compatibility
|
|
47
|
+
* and a bounded session sequence are mandatory before the durable pick is
|
|
48
|
+
* committed.
|
|
49
|
+
*
|
|
40
50
|
* @module @mstar-harness/dsh/engine-status-endpoint
|
|
41
51
|
*/
|
|
42
52
|
import type { Context } from '@deepseek-ai/cordis';
|
|
43
53
|
import type { TypertContribution } from '@deepseek-ai/dsh-typert-registry';
|
|
44
54
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
45
|
-
import type {
|
|
46
|
-
import {
|
|
47
|
-
|
|
55
|
+
import type { WorkflowSelectionView } from './types.ts';
|
|
56
|
+
import { type HarnessResolver } from './gates/_shared.ts';
|
|
57
|
+
import { MSTAR_ENGINE_STATUS_METHOD, MSTAR_ENGINE_STATUS_NAMESPACE, MSTAR_SELECT_WORKFLOW_METHOD } from './engine-status-wire.ts';
|
|
58
|
+
export { MSTAR_ENGINE_STATUS_METHOD, MSTAR_ENGINE_STATUS_NAMESPACE, MSTAR_SELECT_WORKFLOW_METHOD };
|
|
59
|
+
/**
|
|
60
|
+
* The session's CURRENT control state (D4): the selection the server resolves
|
|
61
|
+
* for the session it just validated — the durable picker record folded with
|
|
62
|
+
* the verified live Agent's lease holder. Deliberately SEPARATE from
|
|
63
|
+
* `payload` / `at` / `turn`, which keep naming the last model emission.
|
|
64
|
+
*/
|
|
65
|
+
export interface MstarEngineStatusBinding {
|
|
66
|
+
readonly selection: WorkflowSelectionView;
|
|
67
|
+
}
|
|
48
68
|
/** The served snapshot (the stored emission, echoed back with its identity). */
|
|
49
69
|
export interface MstarEngineStatusOk {
|
|
50
70
|
readonly status: 'ok';
|
|
@@ -56,6 +76,8 @@ export interface MstarEngineStatusOk {
|
|
|
56
76
|
readonly turn: number;
|
|
57
77
|
/** The exact catalog payload emitted to that session's model. */
|
|
58
78
|
readonly payload: Record<string, unknown>;
|
|
79
|
+
/** Current control-state selection for this session (never the last emission's). */
|
|
80
|
+
readonly binding?: MstarEngineStatusBinding;
|
|
59
81
|
}
|
|
60
82
|
/**
|
|
61
83
|
* The explicit "no answer" result. `reason` is machine-readable and always
|
|
@@ -67,12 +89,27 @@ export interface MstarEngineStatusUnavailableResult {
|
|
|
67
89
|
}
|
|
68
90
|
/** The endpoint's wire result. */
|
|
69
91
|
export type MstarEngineStatusResult = MstarEngineStatusOk | MstarEngineStatusUnavailableResult;
|
|
92
|
+
/** The picker commit result: the durable preference was acknowledged. */
|
|
93
|
+
export interface MstarSelectWorkflowOk {
|
|
94
|
+
readonly status: 'selected';
|
|
95
|
+
readonly sessionId: string;
|
|
96
|
+
readonly workflowId: string;
|
|
97
|
+
}
|
|
98
|
+
/** The `selectWorkflow` UI control's wire result. */
|
|
99
|
+
export type MstarSelectWorkflowResult = MstarSelectWorkflowOk | MstarEngineStatusUnavailableResult;
|
|
70
100
|
/** Options the endpoint needs from the plugin's apply scope. */
|
|
71
101
|
export interface MstarEngineStatusEndpointOptions {
|
|
72
102
|
/** The per-workspace `{HARNESS_DIR}` resolver (the same one the gates use). */
|
|
73
103
|
readonly resolver: HarnessResolver;
|
|
74
104
|
/** The boot-resolved config root when an explicit `harnessDir` is configured. */
|
|
75
105
|
readonly bootHarnessDir: string | null;
|
|
106
|
+
/**
|
|
107
|
+
* A picker commit landed for `(harnessDir, sessionId)`: drop that session's
|
|
108
|
+
* cached catalog payload + re-emission digest so the next pre-step rebuilds
|
|
109
|
+
* from the acknowledged binding. Optional (a host without the catalog wiring
|
|
110
|
+
* still serves the control method); a throwing hook is contained.
|
|
111
|
+
*/
|
|
112
|
+
readonly invalidateSelection?: (harnessDir: string, sessionId: string) => void;
|
|
76
113
|
}
|
|
77
114
|
/**
|
|
78
115
|
* Host-side `mstar/engineStatus` service: `/api/mstar/engineStatus` serves the
|
|
@@ -81,9 +118,10 @@ export interface MstarEngineStatusEndpointOptions {
|
|
|
81
118
|
export declare class MstarEngineStatusGateway extends TypertRemoteService {
|
|
82
119
|
private readonly resolver;
|
|
83
120
|
private readonly bootHarnessDir;
|
|
121
|
+
private readonly invalidateSelection;
|
|
84
122
|
/**
|
|
85
123
|
* @param ctx - owning Cordis context.
|
|
86
|
-
* @param options - the apply-scoped resolver + boot root.
|
|
124
|
+
* @param options - the apply-scoped resolver + boot root (+ pick invalidation hook).
|
|
87
125
|
*/
|
|
88
126
|
constructor(ctx: Context, options: MstarEngineStatusEndpointOptions);
|
|
89
127
|
/**
|
|
@@ -91,11 +129,48 @@ export declare class MstarEngineStatusGateway extends TypertRemoteService {
|
|
|
91
129
|
* chain documented in the module header.
|
|
92
130
|
* @param sessionId - the session whose snapshot is requested (client-asserted).
|
|
93
131
|
* @param cwd - the session workspace the client believes it is reading (client-asserted).
|
|
94
|
-
* @returns the stored emission
|
|
132
|
+
* @returns the stored emission plus the session's current control-state
|
|
133
|
+
* selection, or the explicit unavailable state with a reason.
|
|
95
134
|
*/
|
|
96
135
|
engineStatus(sessionId: string, cwd: string): Promise<MstarEngineStatusResult>;
|
|
136
|
+
/**
|
|
137
|
+
* Commit one session's durable workflow selection (the panel's picker).
|
|
138
|
+
*
|
|
139
|
+
* Mandatory before the commit: the LIVE Session (a cold/persisted-only
|
|
140
|
+
* target answers `session-not-live`), an exact cwd match, a bounded integer
|
|
141
|
+
* session sequence, an ACTIVE workflow id from the freshly resolved
|
|
142
|
+
* registry, and no conflicting higher-priority automatic (lease/cwd)
|
|
143
|
+
* binding. The exclusion floor commits as `max(stored, seq)`. An identical
|
|
144
|
+
* already-stored active pick is acknowledged WITHOUT advancing the floor.
|
|
145
|
+
* No client-supplied directory, holder or sequence is accepted.
|
|
146
|
+
* @param sessionId - the session whose selection is committed (client-asserted).
|
|
147
|
+
* @param cwd - the session workspace the client asserts (must match the live session).
|
|
148
|
+
* @param workflowId - the chosen ACTIVE lifecycle id.
|
|
149
|
+
* @returns the acknowledgement, or the explicit unavailable state with a reason.
|
|
150
|
+
*/
|
|
151
|
+
selectWorkflow(sessionId: string, cwd: string, workflowId: string): Promise<MstarSelectWorkflowResult>;
|
|
97
152
|
/** The validation chain itself (contained by {@link engineStatus}). */
|
|
98
153
|
private serve;
|
|
154
|
+
/** The picker commit chain itself (contained by {@link selectWorkflow}). */
|
|
155
|
+
private pick;
|
|
156
|
+
/**
|
|
157
|
+
* The session's CURRENT selection: the durable picker record folded with the
|
|
158
|
+
* session's structural identity and — for a LIVE session — the verified live
|
|
159
|
+
* Agent's opaque id as the lease holder. An unreadable binding record keeps
|
|
160
|
+
* the structural hint only (the pick is unknown, never invented), and the
|
|
161
|
+
* request's `sessionId` is NEVER substituted for the holder.
|
|
162
|
+
*/
|
|
163
|
+
private currentSelection;
|
|
164
|
+
/**
|
|
165
|
+
* The opaque lease-holder `Agent.id` of the session's live Agent, when the
|
|
166
|
+
* public agents service resolves one whose own session header identifies the
|
|
167
|
+
* resolved Session (id AND cwd). Absent/mismatching Agent ⇒ undefined — the
|
|
168
|
+
* request's `sessionId` is never used as a holder shortcut. The verification
|
|
169
|
+
* itself is SHARED ({@link verifiedLeaseHolderOf}) with the other
|
|
170
|
+
* session-level hint builders (the workflow ledger), so a lease-bound
|
|
171
|
+
* session resolves the same lifecycle on every path.
|
|
172
|
+
*/
|
|
173
|
+
private leaseHolderOf;
|
|
99
174
|
/**
|
|
100
175
|
* Resolve the authoritative cwd of one session: the LIVE session first
|
|
101
176
|
* (`ctx.sessions.get(id)`), then the session controller's persisted
|
|
@@ -106,7 +181,9 @@ export declare class MstarEngineStatusGateway extends TypertRemoteService {
|
|
|
106
181
|
private resolveSessionCwd;
|
|
107
182
|
}
|
|
108
183
|
/**
|
|
109
|
-
* The generated-style invocation
|
|
184
|
+
* The generated-style invocation descriptors for the shared `/api` gateway:
|
|
185
|
+
* `/api/mstar/engineStatus` (the stored snapshot + current binding) and
|
|
186
|
+
* `/api/mstar/selectWorkflow` (the panel's durable pick).
|
|
110
187
|
*
|
|
111
188
|
* Registered EXPLICITLY (not through `@Remote` SRC markers): the host gateway
|
|
112
189
|
* checks its own `ctx.typert.local` table FIRST, while SRC discovery reads a
|
|
@@ -16,10 +16,18 @@
|
|
|
16
16
|
* ```json
|
|
17
17
|
* {
|
|
18
18
|
* "sv": 1,
|
|
19
|
-
* "entries": { "<session id>": [ { "rv": 1, "cwd": "/proj", "at": "…", "turn": 3, "payload": { … } } ] }
|
|
19
|
+
* "entries": { "<session id>": [ { "rv": 1, "cwd": "/proj", "at": "…", "turn": 3, "payload": { … } } ] },
|
|
20
|
+
* "bindings": { "<session id>": { "cwd": "/proj", "selectedWorkflowId": "wf-2", "excludedBeforeSeq": 12 } }
|
|
20
21
|
* }
|
|
21
22
|
* ```
|
|
22
23
|
*
|
|
24
|
+
* `entries` is the emission history (what the model saw); `bindings` is the
|
|
25
|
+
* session-scoped workflow-selection CONTROL state (D4: the picked active
|
|
26
|
+
* workflow + the durable no-backfill floor). The control map is additive and
|
|
27
|
+
* optional — a missing map means "no pick / floor 0" — and is never part of an
|
|
28
|
+
* emitted payload: each writer preserves the other's field verbatim, and the
|
|
29
|
+
* binding writer never touches `payload` / `at` / `turn`.
|
|
30
|
+
*
|
|
23
31
|
* `sv` is the envelope schema version and `rv` the per-entry record version:
|
|
24
32
|
* a reader that does not recognize EITHER must answer "unavailable" rather
|
|
25
33
|
* than parse a shape it does not understand — and (write rule below) a writer
|
|
@@ -156,6 +164,52 @@ export interface EngineStatusSnapshotWriteInput {
|
|
|
156
164
|
/** Global byte ceiling override (test seam; production uses the constant). */
|
|
157
165
|
readonly maxBytes?: number;
|
|
158
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* One session's durable workflow-selection CONTROL record (D4): the active
|
|
169
|
+
* workflow this session picked plus the durable no-backfill floor. It lives in
|
|
170
|
+
* the envelope's optional top-level `bindings` map — never inside an emitted
|
|
171
|
+
* payload — and is keyed by the durable `session.header.id`.
|
|
172
|
+
*/
|
|
173
|
+
export interface WorkflowSessionBinding {
|
|
174
|
+
/** The authoritative session cwd the record was written for (exact-match anchor). */
|
|
175
|
+
readonly cwd: string;
|
|
176
|
+
/** The session's chosen ACTIVE workflow id; absent = no explicit pick yet. */
|
|
177
|
+
readonly selectedWorkflowId?: string;
|
|
178
|
+
/**
|
|
179
|
+
* Durable exclusion floor: ledger rows at or below this sequence were
|
|
180
|
+
* intentionally skipped while the session was unbound and must never be
|
|
181
|
+
* backfilled. An absent record means floor 0 (no exclusion history).
|
|
182
|
+
*/
|
|
183
|
+
readonly excludedBeforeSeq: number;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Binding read outcome: the stored record (or its absence as `ok` WITHOUT a
|
|
187
|
+
* `binding`), or why attribution is unavailable — absent and corrupt are
|
|
188
|
+
* distinct answers, never a silent empty record.
|
|
189
|
+
*/
|
|
190
|
+
export type WorkflowSessionBindingRead = {
|
|
191
|
+
readonly kind: 'ok';
|
|
192
|
+
readonly binding?: WorkflowSessionBinding;
|
|
193
|
+
} | {
|
|
194
|
+
readonly kind: 'unavailable';
|
|
195
|
+
readonly reason: string;
|
|
196
|
+
};
|
|
197
|
+
/** One binding read-modify-write request (a picker commit or a floor advance). */
|
|
198
|
+
export interface WorkflowSessionBindingUpdate {
|
|
199
|
+
/** The chosen active workflow id; omitted preserves the stored preference. */
|
|
200
|
+
readonly selectedWorkflowId?: string;
|
|
201
|
+
/** The exclusion floor to merge (by max) into the stored record. */
|
|
202
|
+
readonly excludedBeforeSeq: number;
|
|
203
|
+
/** Global byte ceiling override (test seam; production uses the constant). */
|
|
204
|
+
readonly maxBytes?: number;
|
|
205
|
+
}
|
|
206
|
+
/** Binding write outcome: written, or the degraded reason (never throws for I/O faults). */
|
|
207
|
+
export type WorkflowSessionBindingWrite = {
|
|
208
|
+
readonly kind: 'written';
|
|
209
|
+
} | {
|
|
210
|
+
readonly kind: 'degraded';
|
|
211
|
+
readonly reason: string;
|
|
212
|
+
};
|
|
159
213
|
/** Absolute snapshot file path for one `{HARNESS_DIR}`. */
|
|
160
214
|
export declare function engineStatusSnapshotPath(harnessDir: string): string;
|
|
161
215
|
/** The explicit unavailable result (single constructor — one shape everywhere). */
|
|
@@ -188,3 +242,39 @@ export declare function readEngineStatusSnapshot(harnessDir: string | null, sess
|
|
|
188
242
|
* per store — the oversize warning) or the degraded reason.
|
|
189
243
|
*/
|
|
190
244
|
export declare function writeEngineStatusSnapshot(harnessDir: string | null, input: EngineStatusSnapshotWriteInput): EngineStatusSnapshotWrite;
|
|
245
|
+
/**
|
|
246
|
+
* Read one session's durable workflow-selection binding.
|
|
247
|
+
*
|
|
248
|
+
* The answers are deliberately distinct: `{kind:'ok'}` WITHOUT a `binding`
|
|
249
|
+
* means there is nothing recorded for this session (no store yet, an sv=1
|
|
250
|
+
* envelope without the control map, no key for the session) — the caller
|
|
251
|
+
* proceeds unbound. `{kind:'unavailable', reason}` means the record cannot be
|
|
252
|
+
* trusted (`store-unreadable`, `store-invalid-json`, `store-envelope-schema`,
|
|
253
|
+
* `store-bindings-schema`, `cwd-mismatch`) — the caller must NOT treat that as
|
|
254
|
+
* "no pick" and attribute the session anywhere.
|
|
255
|
+
*
|
|
256
|
+
* The file read + parse is memoized by the file's identity (see
|
|
257
|
+
* {@link readBindingStoreSnapshot}); only this session's key is re-checked per
|
|
258
|
+
* call, so the per-tool-call / per-step cost does not scale with the store.
|
|
259
|
+
* @param harnessDir - the resolved `{HARNESS_DIR}`.
|
|
260
|
+
* @param sessionId - the durable `session.header.id` (the picker key).
|
|
261
|
+
* @param cwd - the authoritative session cwd (exact match against the record).
|
|
262
|
+
*/
|
|
263
|
+
export declare function readWorkflowSessionBinding(harnessDir: string, sessionId: string, cwd: string): WorkflowSessionBindingRead;
|
|
264
|
+
/**
|
|
265
|
+
* Durably record one session's workflow-selection binding (the D4 picker
|
|
266
|
+
* commit / exclusion-floor advance) — the same read-modify-write discipline as
|
|
267
|
+
* {@link writeEngineStatusSnapshot}: the snapshot-dir lock, a writer-unique
|
|
268
|
+
* temp file, an atomic rename, and the refusal rule for a store this build
|
|
269
|
+
* cannot understand. The emission records (`payload` / `at` / `turn` /
|
|
270
|
+
* `rv` / `cwd`) are preserved EXACTLY: this write only sets
|
|
271
|
+
* `bindings[sessionId]`, merges the floor by max, and keeps the stored
|
|
272
|
+
* preference when the update omits one. A binding that cannot fit the ceiling
|
|
273
|
+
* is refused rather than paid for by dropping another session's record.
|
|
274
|
+
* @param harnessDir - the resolved `{HARNESS_DIR}`.
|
|
275
|
+
* @param sessionId - the durable `session.header.id`.
|
|
276
|
+
* @param cwd - the authoritative session cwd (must match any stored record).
|
|
277
|
+
* @param update - the preference (optional) and the exclusion floor.
|
|
278
|
+
* @returns written, or the degraded reason (never throws for I/O faults).
|
|
279
|
+
*/
|
|
280
|
+
export declare function updateWorkflowSessionBinding(harnessDir: string, sessionId: string, cwd: string, update: WorkflowSessionBindingUpdate): WorkflowSessionBindingWrite;
|
|
@@ -27,3 +27,12 @@ export declare const ENGINE_STATUS_ENDPOINT = "mstar/engineStatus";
|
|
|
27
27
|
export declare const MSTAR_ENGINE_STATUS_NAMESPACE = "mstar";
|
|
28
28
|
/** Wire method of the invocation → `/api/mstar/engineStatus`. */
|
|
29
29
|
export declare const MSTAR_ENGINE_STATUS_METHOD = "engineStatus";
|
|
30
|
+
/**
|
|
31
|
+
* Wire method of the panel's workflow-selection control → `/api/mstar/selectWorkflow`.
|
|
32
|
+
* A session-scoped UI control (never a model workflow-execution tool): the
|
|
33
|
+
* host acknowledges the pick durably and the next `ensure()` reads the
|
|
34
|
+
* current binding back.
|
|
35
|
+
*/
|
|
36
|
+
export declare const MSTAR_SELECT_WORKFLOW_METHOD = "selectWorkflow";
|
|
37
|
+
/** The endpoint path the client calls for a workflow pick. */
|
|
38
|
+
export declare const SELECT_WORKFLOW_ENDPOINT = "mstar/selectWorkflow";
|
package/dist/gates/_shared.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import z from 'schemastery';
|
|
|
2
2
|
import type { GateResult, ValidationResult } from '@mstar-harness/engine';
|
|
3
3
|
import type { Config as SkillLocalConfig } from '@deepseek-ai/dsh-skill-filesystem';
|
|
4
4
|
import type { IterationGateListView, IterationGateViolationView } from '../types.ts';
|
|
5
|
+
import type { SessionHint } from './workflow-selection.ts';
|
|
5
6
|
/** Canonical harness status file name (mstar-artifacts status.json). */
|
|
6
7
|
export declare const STATUS_FILE = "status.json";
|
|
7
8
|
/** Plugin configuration. */
|
|
@@ -128,15 +129,6 @@ export interface Config {
|
|
|
128
129
|
* so P-a never applies to them.
|
|
129
130
|
*/
|
|
130
131
|
workflowNames?: string[];
|
|
131
|
-
/**
|
|
132
|
-
* Goal-bridge round cap : the
|
|
133
|
-
* flat `maxGoalRounds` the goal bridge passes to the goals service when it
|
|
134
|
-
* mirrors the active iteration objective (bounds autonomous Phase 2
|
|
135
|
-
* loops — the service itself throws on resume past the cap). Absent →
|
|
136
|
-
* 256 (aligned with the GoalService default and ralph `maxRounds` —
|
|
137
|
-
* architect decision; see the plan).
|
|
138
|
-
*/
|
|
139
|
-
maxGoalRounds?: number;
|
|
140
132
|
}
|
|
141
133
|
/**
|
|
142
134
|
* dsh system-prompt strict `{{variable}}` interpolation hazard: the renderer
|
|
@@ -314,6 +306,66 @@ export declare function sessionCwdOf(agent: unknown): string | undefined;
|
|
|
314
306
|
* skips the persist instead of inventing a key.
|
|
315
307
|
*/
|
|
316
308
|
export declare function sessionHeaderIdOf(agent: unknown): string | undefined;
|
|
309
|
+
/**
|
|
310
|
+
* The opaque id of one agent — the LEASE-holder identity (`Agent.id`,
|
|
311
|
+
* structural read). Deliberately distinct from {@link sessionHeaderIdOf}:
|
|
312
|
+
* the durable picker key is `session.header.id` while a lease's `holder` is
|
|
313
|
+
* the dispatching agent's own id, and the two are never substituted for one
|
|
314
|
+
* another (no host-prefix coercion — the resolver compares them opaquely).
|
|
315
|
+
*/
|
|
316
|
+
export declare function agentIdOf(agent: unknown): string | undefined;
|
|
317
|
+
/**
|
|
318
|
+
* The VERIFIED live lease-holder identity of one session's Agent — the id the
|
|
319
|
+
* dispatch gate forwards to the shared resolvers for the SAME dispatch
|
|
320
|
+
* (`sessionHintOf(exec.agent)` → `agentIdOf`). Every consumer of a
|
|
321
|
+
* session-level hint (the host endpoint's control-state read, the workflow
|
|
322
|
+
* ledger's attribution) must forward the SAME identity, or a session whose
|
|
323
|
+
* lifecycle is only decidable by its lease (two active lifecycles sharing one
|
|
324
|
+
* `control_worktree_path`) resolves differently per call site.
|
|
325
|
+
*
|
|
326
|
+
* The handle must BE that session's agent — its own `session.header.id` names
|
|
327
|
+
* the session, and (when the caller has an authoritative cwd) its workspace
|
|
328
|
+
* must equal it. Anything else answers `undefined`: the session id is never
|
|
329
|
+
* substituted for a holder (they are opaque and distinct).
|
|
330
|
+
* @param agent - the live agent the host resolves for the session (structural read).
|
|
331
|
+
* @param sessionId - the session the hint is built for.
|
|
332
|
+
* @param cwd - the session's workspace; `undefined` skips the workspace check
|
|
333
|
+
* (a caller with no authoritative cwd cannot verify one).
|
|
334
|
+
*/
|
|
335
|
+
export declare function verifiedLeaseHolderOf(agent: unknown, sessionId: string, cwd: string | undefined): string | undefined;
|
|
336
|
+
/**
|
|
337
|
+
* The structural session hint one event's agent supplies to the workflow
|
|
338
|
+
* resolvers (no dsh-session import — cold/raw Session consumers read the same
|
|
339
|
+
* `header.cwd` / `header.id` directly). `selectedWorkflowId` is deliberately
|
|
340
|
+
* ABSENT: it is the session's durable binding record, loaded by the
|
|
341
|
+
* composition edge that owns the store (adapter / catalog / workflow-ledger /
|
|
342
|
+
* plan-mode bridge) — the pure structural read never fabricates it.
|
|
343
|
+
* @param agent - the agent an event carries (structural read).
|
|
344
|
+
* @returns the hint, or `undefined` when the agent carries no session
|
|
345
|
+
* identity and no id at all (an exec-less hook) — an OMITTED hint, never a
|
|
346
|
+
* fabricated empty one.
|
|
347
|
+
*/
|
|
348
|
+
export declare function sessionHintOf(agent: unknown): SessionHint | undefined;
|
|
349
|
+
/**
|
|
350
|
+
* One carrying session's selection-hint read: the hint the resolvers consume,
|
|
351
|
+
* plus whether the session's DURABLE binding could be trusted.
|
|
352
|
+
*
|
|
353
|
+
* `ok` without a `hint` = the event carries no session (an exec-less hook) —
|
|
354
|
+
* the automatic rungs miss and the registry's unique-active case still
|
|
355
|
+
* resolves. `unavailable` = the binding store could not be read
|
|
356
|
+
* (corrupt/unreadable/cwd-mismatch), so the caller must NOT attribute a
|
|
357
|
+
* durable write to this session — an unverifiable record is NOT "no pick",
|
|
358
|
+
* and must never be replaced by an empty hint that would silently attribute
|
|
359
|
+
* the write to whichever lifecycle happens to resolve.
|
|
360
|
+
*/
|
|
361
|
+
export type SessionHintRead = {
|
|
362
|
+
readonly kind: 'ok';
|
|
363
|
+
readonly hint?: SessionHint;
|
|
364
|
+
} | {
|
|
365
|
+
readonly kind: 'unavailable';
|
|
366
|
+
readonly reason: string;
|
|
367
|
+
readonly hint?: SessionHint;
|
|
368
|
+
};
|
|
317
369
|
/** The tool-execution actor of one fs-intent event, when it carries an agent. */
|
|
318
370
|
export declare function actorAgentOf(actor: object | undefined): unknown;
|
|
319
371
|
/**
|
package/dist/gates/adapter.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Service, type Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { AssignmentFields, GateResult, HostAdapter, IntegrationMergeLease, ValidationResult } from '@mstar-harness/engine';
|
|
3
3
|
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
4
|
-
import type { HarnessResolver, Config } from './_shared.ts';
|
|
4
|
+
import type { HarnessResolver, Config, SessionHintRead } from './_shared.ts';
|
|
5
5
|
import { type HarnessDocKind } from './status.ts';
|
|
6
6
|
import type { AgentFlowPairing, WorkflowVerdictInput } from './agent-flow.ts';
|
|
7
7
|
import { WorkflowAskCache } from './workflow-policy.ts';
|
|
@@ -109,6 +109,33 @@ export declare class DshHostAdapter extends Service implements HostAdapter {
|
|
|
109
109
|
* cleanup extension needs it to locate the project registers).
|
|
110
110
|
*/
|
|
111
111
|
statusGate(path: string, kind: HarnessDocKind, harnessDir: string | null): GateResult;
|
|
112
|
+
/**
|
|
113
|
+
* Derive the carrying session's workflow-selection hint for one event
|
|
114
|
+
* (D4): the structural identity read off the agent (`session.header.cwd` /
|
|
115
|
+
* `session.header.id` plus the agent's own opaque id as the lease holder)
|
|
116
|
+
* folded with this session's DURABLE binding preference from the
|
|
117
|
+
* engine-status store. Both gate reads and ledger writes route through
|
|
118
|
+
* this ONE derivation, so a session is attributed consistently within a
|
|
119
|
+
* single decision.
|
|
120
|
+
*
|
|
121
|
+
* The store is the plugin's only durable picker state, and it is read at
|
|
122
|
+
* THIS composition edge: `dispatch.ts` (and the writers in `agent-flow.ts`)
|
|
123
|
+
* receive plain hints and never touch the store — no circular
|
|
124
|
+
* `agent-flow → store → agent-flow` import.
|
|
125
|
+
*
|
|
126
|
+
* Degrades honestly, never with a fabricated hint:
|
|
127
|
+
* - no session at all (exec-less hook / agent stub) → `ok` without a hint,
|
|
128
|
+
* so the automatic rungs miss and only a unique active lifecycle
|
|
129
|
+
* resolves;
|
|
130
|
+
* - a session without both id AND cwd → `ok` with what IS known (the
|
|
131
|
+
* lease/cwd rungs and the unique-active case still work — only the
|
|
132
|
+
* durable pick needs the session key);
|
|
133
|
+
* - an unreadable/refused/cwd-mismatched binding record → `unavailable`
|
|
134
|
+
* (reported once through the adapter's log), so the callers keep the
|
|
135
|
+
* structural evidence for GATE validation but write no ledger row.
|
|
136
|
+
* @param agent - the event's agent (`exec.agent`), structural read.
|
|
137
|
+
*/
|
|
138
|
+
sessionHintFor(agent: unknown): SessionHintRead;
|
|
112
139
|
/**
|
|
113
140
|
* Shared dispatch-gate core (plugin-internal): the `tools/pre-execute`
|
|
114
141
|
* listener and `beforeDispatch` route through this method — ONE
|
|
@@ -122,8 +149,11 @@ export declare class DshHostAdapter extends Service implements HostAdapter {
|
|
|
122
149
|
* @param hard - the caller's ONE `resolveDispatchHard` resolution): passed in so the record block and
|
|
123
150
|
* the caller's enforcement decision share a single compass resolution;
|
|
124
151
|
* when omitted (external callers) the adapter resolves it itself.
|
|
152
|
+
* @param hintRead - the caller's already-derived hint read (the
|
|
153
|
+
* `tools/pre-execute` listener derives it once and shares it with the
|
|
154
|
+
* workflow branch); omitted → derived here from `exec.agent`.
|
|
125
155
|
*/
|
|
126
|
-
dispatchGate(prompt: string, exec?: ToolExecution, hard?: boolean): GateResult;
|
|
156
|
+
dispatchGate(prompt: string, exec?: ToolExecution, hard?: boolean, hintRead?: SessionHintRead): GateResult;
|
|
127
157
|
/**
|
|
128
158
|
* Record one workflow/ralph gate verdict row (plan
|
|
129
159
|
* Task 4 — the durable ledger row for every
|