@linxin666/dsh-client-ui-task-board 0.4.4 → 0.4.6
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 +59 -20
- package/README.zh.md +59 -20
- package/lib/client.js +6208 -624
- package/lib/client.js.map +1 -1
- package/lib/index.js +4774 -493
- package/lib/types/client/PluginSettingsCard.d.ts +7 -0
- package/lib/types/client/TaskBoardSettingsCard.d.ts +31 -3
- package/lib/types/client/board/ClampedMarkdown.d.ts +3 -0
- package/lib/types/client/board/ConfirmDialog.d.ts +4 -1
- package/lib/types/client/board/EditTaskModal.d.ts +5 -2
- package/lib/types/client/board/LinkSubtaskModal.d.ts +5 -2
- package/lib/types/client/board/NewTaskModal.d.ts +4 -1
- package/lib/types/client/board/TagManagerModal.d.ts +26 -0
- package/lib/types/client/board/TaskBoard.d.ts +10 -1
- package/lib/types/client/board/TaskCard.d.ts +14 -1
- package/lib/types/client/board/TaskDetail.d.ts +3 -1
- package/lib/types/client/board/TaskForm.d.ts +4 -1
- package/lib/types/client/board/VerificationReport.d.ts +23 -0
- package/lib/types/client/board/card-view.d.ts +113 -0
- package/lib/types/client/board/icons.d.ts +32 -0
- package/lib/types/client/board/overlay.d.ts +69 -0
- package/lib/types/client/board/status-key.d.ts +15 -0
- package/lib/types/client/board/task-markdown.d.ts +19 -0
- package/lib/types/client/index.d.ts +23 -5
- package/lib/types/client/locales.d.ts +168 -1
- package/lib/types/client/native-panel.d.ts +6 -20
- package/lib/types/client/plugin-card-seat.d.ts +5 -0
- package/lib/types/client/schedule-zone.d.ts +50 -0
- package/lib/types/client/seats.d.ts +18 -0
- package/lib/types/client/service.d.ts +32 -0
- package/lib/types/client/settings-form.d.ts +16 -0
- package/lib/types/core/controller.d.ts +46 -11
- package/lib/types/core/extension.d.ts +283 -0
- package/lib/types/core/handover.d.ts +13 -1
- package/lib/types/core/issue-form.d.ts +16 -0
- package/lib/types/core/poll-cadence.d.ts +31 -0
- package/lib/types/core/tasks.d.ts +228 -17
- package/lib/types/core/use-cases/task-schedule.d.ts +68 -10
- package/lib/types/core/use-cases/task-tag.d.ts +48 -0
- package/lib/types/core/use-cases/task-update.d.ts +5 -3
- package/lib/types/core/verification-budget.d.ts +52 -0
- package/lib/types/core/verification.d.ts +753 -0
- package/lib/types/core/workspace-target.d.ts +41 -0
- package/lib/types/host/agent-tools.d.ts +1 -1
- package/lib/types/host/extension-registry.d.ts +111 -0
- package/lib/types/host/llm-dispatch.d.ts +63 -0
- package/lib/types/host/verification-gate.d.ts +95 -0
- package/lib/types/host/verification-runner.d.ts +139 -0
- package/lib/types/host/workspace-evidence.d.ts +53 -0
- package/lib/types/host-ledger.d.ts +133 -14
- package/lib/types/host-runner.d.ts +55 -10
- package/lib/types/host-service.d.ts +205 -11
- package/lib/types/index.d.ts +134 -26
- package/lib/types/protocol.d.ts +92 -10
- package/lib/types/tool-surface.d.ts +71 -0
- package/package.json +28 -31
- package/src/client/PluginSettingsCard.tsx +9 -0
- package/src/client/TaskBoardSettingsCard.tsx +378 -66
- package/src/client/board/ClampedMarkdown.tsx +69 -0
- package/src/client/board/ConfirmDialog.tsx +7 -3
- package/src/client/board/EditTaskModal.tsx +5 -2
- package/src/client/board/LinkSubtaskModal.tsx +12 -7
- package/src/client/board/NewTaskModal.tsx +168 -21
- package/src/client/board/TagManagerModal.tsx +235 -0
- package/src/client/board/TaskBoard.tsx +259 -103
- package/src/client/board/TaskCard.tsx +214 -81
- package/src/client/board/TaskDetail.tsx +289 -43
- package/src/client/board/TaskForm.tsx +13 -3
- package/src/client/board/VerificationReport.tsx +322 -0
- package/src/client/board/card-view.ts +220 -0
- package/src/client/board/icons.tsx +89 -0
- package/src/client/board/overlay.tsx +189 -0
- package/src/client/board/status-key.ts +30 -0
- package/src/client/board/task-markdown.module.css +137 -0
- package/src/client/board/task-markdown.tsx +106 -0
- package/src/client/board-settings.module.css +66 -0
- package/src/client/board.module.css +488 -63
- package/src/client/index.ts +82 -51
- package/src/client/locales.ts +343 -6
- package/src/client/native-panel.tsx +18 -2
- package/src/client/plugin-card-seat.ts +7 -0
- package/src/client/schedule-zone.ts +100 -2
- package/src/client/seats.tsx +58 -0
- package/src/client/service.ts +94 -0
- package/src/client/settings-card.module.css +31 -5
- package/src/client/settings-form.ts +27 -1
- package/src/core/controller.ts +105 -10
- package/src/core/extension.ts +376 -0
- package/src/core/freeze-snapshot.ts +2 -2
- package/src/core/handover.ts +16 -1
- package/src/core/issue-form.ts +19 -0
- package/src/core/poll-cadence.ts +41 -0
- package/src/core/store.ts +80 -15
- package/src/core/tasks.ts +293 -45
- package/src/core/use-cases/task-create.ts +30 -9
- package/src/core/use-cases/task-parent.ts +3 -2
- package/src/core/use-cases/task-schedule.ts +190 -25
- package/src/core/use-cases/task-tag.ts +110 -0
- package/src/core/use-cases/task-update.ts +13 -7
- package/src/core/verification-budget.ts +115 -0
- package/src/core/verification.ts +1594 -0
- package/src/core/workspace-target.ts +59 -0
- package/src/host/agent-tools.ts +125 -38
- package/src/host/extension-registry.ts +509 -0
- package/src/host/llm-dispatch.ts +87 -0
- package/src/host/verification-gate.ts +487 -0
- package/src/host/verification-runner.ts +702 -0
- package/src/host/workspace-evidence.ts +176 -0
- package/src/host-ai.ts +15 -9
- package/src/host-ledger.ts +468 -71
- package/src/host-routes.ts +15 -2
- package/src/host-runner.ts +106 -24
- package/src/host-service.ts +546 -40
- package/src/index.ts +305 -21
- package/src/protocol.ts +226 -28
- package/src/tool-surface.ts +95 -0
- package/lib/invariant.js +0 -6
- package/lib/types/invariant.d.ts +0 -3
- package/src/invariant.ts +0 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type ExecutionOutcome, type ExecutionRecord, type TaskRecord } from './core/tasks.ts';
|
|
1
|
+
import { type ExecutionOutcome, type ExecutionRecord, type ScheduleMode, type TaskRecord } from './core/tasks.ts';
|
|
2
2
|
import { type TaskBoardAction, type TaskBoardSchedulerSnapshot } from './protocol.ts';
|
|
3
|
+
import { type ExecutionVerification } from './core/verification.ts';
|
|
3
4
|
import { type TaskPermission } from './core/handover.ts';
|
|
4
5
|
export interface LedgerState {
|
|
5
6
|
revision: number;
|
|
@@ -34,7 +35,10 @@ export interface OpenExecutionReference {
|
|
|
34
35
|
/** Minimal value copy used by the Host scheduler. */
|
|
35
36
|
export interface DueScheduleReference {
|
|
36
37
|
readonly taskId: string;
|
|
37
|
-
|
|
38
|
+
/** Whether this due rule is a recurring cron rule or a single planned instant. */
|
|
39
|
+
readonly mode: ScheduleMode;
|
|
40
|
+
/** Cron expression of a recurring rule; absent on a one-shot. */
|
|
41
|
+
readonly cron?: string;
|
|
38
42
|
/** Zone this rule's wall clock is read in. */
|
|
39
43
|
readonly timeZone: string;
|
|
40
44
|
readonly nextRunAt: number;
|
|
@@ -43,6 +47,24 @@ export interface DueScheduleReference {
|
|
|
43
47
|
export interface LedgerRuntimeView {
|
|
44
48
|
readonly armedSchedules: number;
|
|
45
49
|
readonly openExecutions: readonly OpenExecutionReference[];
|
|
50
|
+
/**
|
|
51
|
+
* Session ids of every open execution, including the ones
|
|
52
|
+
* {@link openExecutions} skips because their own outcome is already
|
|
53
|
+
* recorded. A caller that asks whether the board still observes any session
|
|
54
|
+
* must use this list: a deferred cascade parent is settled by its members,
|
|
55
|
+
* but it is still an open execution.
|
|
56
|
+
*/
|
|
57
|
+
readonly openSessionIds: readonly string[];
|
|
58
|
+
/**
|
|
59
|
+
* Whether this document holds anything the session roster can still decide:
|
|
60
|
+
* an open execution that needs inspecting, or a card in the running column
|
|
61
|
+
* whose verdict may arrive from a settle this process never saw.
|
|
62
|
+
*
|
|
63
|
+
* A board with no running card, no open execution and no armed schedule has
|
|
64
|
+
* no use for the roster at all, which is what lets the Host poll stand down
|
|
65
|
+
* instead of re-reading every persisted session forever.
|
|
66
|
+
*/
|
|
67
|
+
readonly needsSessionState: boolean;
|
|
46
68
|
}
|
|
47
69
|
/**
|
|
48
70
|
* Best-effort single-letter process state ('R','S','D','Z',...) or undefined
|
|
@@ -89,8 +111,14 @@ export declare class HostTaskLedger {
|
|
|
89
111
|
readonly lockFile: string;
|
|
90
112
|
/** Small sidecar for the 30 s scheduler heartbeat (lastTickAt only). */
|
|
91
113
|
readonly schedulerFile: string;
|
|
92
|
-
/**
|
|
93
|
-
readonly
|
|
114
|
+
/** Resolves the baseline the confirmation gate compares a binding against. */
|
|
115
|
+
private readonly sessionDefault;
|
|
116
|
+
/**
|
|
117
|
+
* Session-default permission the confirmation gate compares against. Read
|
|
118
|
+
* through the resolver on every use, so a baseline that follows the Host's
|
|
119
|
+
* own default preset tracks a Settings change made while the board runs.
|
|
120
|
+
*/
|
|
121
|
+
get sessionDefaultPermission(): TaskPermission;
|
|
94
122
|
/**
|
|
95
123
|
* Deployment subtask depth limit (1..3): the lineage gate every write obeys.
|
|
96
124
|
* The settings card edits it live, so {@link setMaxSubtaskDepth} mutates it
|
|
@@ -98,7 +126,7 @@ export declare class HostTaskLedger {
|
|
|
98
126
|
*/
|
|
99
127
|
private depthLimit;
|
|
100
128
|
constructor(dir?: string, now?: () => number, options?: {
|
|
101
|
-
sessionDefaultPermission?: TaskPermission;
|
|
129
|
+
sessionDefaultPermission?: TaskPermission | (() => TaskPermission);
|
|
102
130
|
maxSubtaskDepth?: number;
|
|
103
131
|
});
|
|
104
132
|
/** Current subtask depth limit (1..3). */
|
|
@@ -118,7 +146,7 @@ export declare class HostTaskLedger {
|
|
|
118
146
|
};
|
|
119
147
|
state(): LedgerState;
|
|
120
148
|
/**
|
|
121
|
-
* Runtime-only projection for the
|
|
149
|
+
* Runtime-only projection for the Host poll. It copies just primitive
|
|
122
150
|
* identifiers and timestamps, never the complete task/execution history or
|
|
123
151
|
* an authoritative mutable object from the ledger.
|
|
124
152
|
*/
|
|
@@ -145,9 +173,45 @@ export declare class HostTaskLedger {
|
|
|
145
173
|
/**
|
|
146
174
|
* Open the cascade one due schedule triggers: an empty array means nothing
|
|
147
175
|
* ran (already running, or a participant whose elevated permission is still
|
|
148
|
-
* unconfirmed
|
|
176
|
+
* unconfirmed, a one-shot whose instant was missed, or an exhausted budget),
|
|
177
|
+
* and the rule's own state says which.
|
|
178
|
+
*
|
|
179
|
+
* The run budget is enforced HERE, inside the single ledger writer: a rule
|
|
180
|
+
* whose counter already reached its cap is stopped instead of opened, so no
|
|
181
|
+
* restart, repeated timer fire or re-arm can overrun it.
|
|
182
|
+
* @param taskId - the task whose rule came due.
|
|
183
|
+
* @param triggeredAt - the instant the occurrence came due.
|
|
184
|
+
* @returns the executions this occurrence opened.
|
|
185
|
+
*/
|
|
186
|
+
openScheduled(taskId: string, triggeredAt: number): OpenedRun[];
|
|
187
|
+
/**
|
|
188
|
+
* Record a due occurrence that opened no execution: roll a recurring rule to
|
|
189
|
+
* its next occurrence (budget untouched), or stop it when there is none. A
|
|
190
|
+
* one-shot has no second occurrence, so it always stops here with the reason.
|
|
191
|
+
*/
|
|
192
|
+
private skipOccurrence;
|
|
193
|
+
/** Apply a schedule-occurrence transition and persist it atomically. */
|
|
194
|
+
private progressSchedule;
|
|
195
|
+
/**
|
|
196
|
+
* Refund the one scheduled run an occurrence consumed before its launch
|
|
197
|
+
* failed without creating a session (see
|
|
198
|
+
* {@link applyScheduleRefund}). Called by the service on the failed-launch
|
|
199
|
+
* path only; a manual run and a launch that did reach a session are never
|
|
200
|
+
* refunded. A no-op for a task with no rule, so a failed cascade member does
|
|
201
|
+
* not touch anything.
|
|
202
|
+
* @param taskId - the task whose occurrence is being refunded.
|
|
203
|
+
* @param now - clock instant (ms epoch).
|
|
204
|
+
*/
|
|
205
|
+
refundScheduledOccurrence(taskId: string, now: number): void;
|
|
206
|
+
/**
|
|
207
|
+
* Boot / resume recovery: skip every occurrence that came due while the board
|
|
208
|
+
* was not running through it. A recurring rule rolls to its next future
|
|
209
|
+
* target; a one-shot whose instant has passed is stopped as missed, because
|
|
210
|
+
* there is no later occurrence left to run. Rendering the missed occurrence
|
|
211
|
+
* is deliberately not attempted: the ACL of a card that fired hours ago is
|
|
212
|
+
* stale, and the board's own recovery contract is "missed triggers are
|
|
213
|
+
* skipped, never replayed".
|
|
149
214
|
*/
|
|
150
|
-
openScheduled(taskId: string, nextRunAt: number | undefined, triggeredAt: number): OpenedRun[];
|
|
151
215
|
skipMissed(now: number): void;
|
|
152
216
|
setScheduler(patch: Partial<TaskBoardSchedulerSnapshot>): void;
|
|
153
217
|
/**
|
|
@@ -158,16 +222,29 @@ export declare class HostTaskLedger {
|
|
|
158
222
|
*/
|
|
159
223
|
settle(taskId: string, executionId: string, outcome: ExecutionOutcome, error?: string): void;
|
|
160
224
|
attachSession(taskId: string, executionId: string, sessionId: string): void;
|
|
225
|
+
allTasks(): readonly TaskRecord[];
|
|
226
|
+
getTask(id: string): TaskRecord | undefined;
|
|
227
|
+
saveTaskRecord(task: TaskRecord): void;
|
|
161
228
|
private apply;
|
|
229
|
+
/**
|
|
230
|
+
* Whether a creation-time schedule request is usable. A one-shot must carry
|
|
231
|
+
* a whole-millisecond instant in the future; a recurring rule must carry a
|
|
232
|
+
* valid expression with a reachable occurrence and, when capped, a positive
|
|
233
|
+
* whole run budget. An unusable zone is refused rather than reinterpreted as
|
|
234
|
+
* the Host zone.
|
|
235
|
+
*/
|
|
236
|
+
private validScheduleRequest;
|
|
162
237
|
/**
|
|
163
238
|
* The binding that makes a run illegal, if any.
|
|
164
239
|
*
|
|
165
240
|
* A plain cascade launches one session per participant, so every participant
|
|
166
241
|
* carries its own resolved binding and each one gates the run. A team run
|
|
167
|
-
* launches only the Lead session: the Lead's binding gates it,
|
|
168
|
-
*
|
|
169
|
-
* refused
|
|
170
|
-
*
|
|
242
|
+
* launches only the Lead session: the Lead's binding gates it, and a
|
|
243
|
+
* teammate inherits that session's permission, so a subtask's OWN pin is
|
|
244
|
+
* refused exactly when the Lead session does not already carry it — the
|
|
245
|
+
* teammate could never be given that authority, and dropping the pin
|
|
246
|
+
* silently would misreport the work (an inherited binding is the Lead's own
|
|
247
|
+
* and stays allowed once the Lead is confirmed).
|
|
171
248
|
* @param root - the task being run.
|
|
172
249
|
* @returns the first refusal, or undefined when the run may start.
|
|
173
250
|
*/
|
|
@@ -190,7 +267,9 @@ export declare class HostTaskLedger {
|
|
|
190
267
|
* @param now - clock instant (ms epoch).
|
|
191
268
|
* @param initiator - the DSH session that asked for the run (audit only).
|
|
192
269
|
* @param rerun - true to reset the root to 'todo' before starting it.
|
|
193
|
-
* @param
|
|
270
|
+
* @param progress - when set, this run was a due occurrence and the root's
|
|
271
|
+
* rule is advanced (counter, next target, stop/skip record) in the same
|
|
272
|
+
* atomic commit that opened the executions.
|
|
194
273
|
*/
|
|
195
274
|
private startCascade;
|
|
196
275
|
/**
|
|
@@ -236,10 +315,18 @@ export declare class HostTaskLedger {
|
|
|
236
315
|
* @returns whether the document changed.
|
|
237
316
|
*/
|
|
238
317
|
private closeTeamMembers;
|
|
318
|
+
/**
|
|
319
|
+
* Re-align every armed rule at load/import. A recurring rule is recomputed
|
|
320
|
+
* from the current instant; a one-shot is armed at its planned instant when
|
|
321
|
+
* that is still in the future, and stopped as missed once it has passed
|
|
322
|
+
* (there is no later occurrence to run). A recurring rule recomputed past an
|
|
323
|
+
* occurrence records the skip, so the board can show that a fire was passed
|
|
324
|
+
* over rather than silently rewinding.
|
|
325
|
+
*/
|
|
239
326
|
private repairSchedules;
|
|
240
327
|
private reconcileInterruptedStarts;
|
|
241
328
|
/**
|
|
242
|
-
* Field-preserving migration of
|
|
329
|
+
* Field-preserving migration of an older document. It first proves every task
|
|
243
330
|
* row is structurally valid, so a document that would silently drop or coerce
|
|
244
331
|
* rows fails loudly instead (no quarantined-empty restart), and then reuses
|
|
245
332
|
* the current normalization.
|
|
@@ -250,8 +337,40 @@ export declare class HostTaskLedger {
|
|
|
250
337
|
* (the stored `nextRunAt` already encodes the old zone), but the rule stops
|
|
251
338
|
* following a later `TZ` change, which is what made an existing schedule
|
|
252
339
|
* silently move when the Host's zone changed.
|
|
340
|
+
*
|
|
341
|
+
* v5 adds the per-execution acceptance block. The migration deliberately does
|
|
342
|
+
* NOT stamp one: an execution opened before v5 keeps no contract, so it
|
|
343
|
+
* settles on its own historical verdict and no in-flight run is retroactively
|
|
344
|
+
* judged by a gate that was never armed for it.
|
|
253
345
|
*/
|
|
254
346
|
private migrateLegacyDocument;
|
|
347
|
+
/**
|
|
348
|
+
* Find the still-open execution that ran in one session, with its task.
|
|
349
|
+
*
|
|
350
|
+
* The completion gate keys on the session id its tool call arrives from: the
|
|
351
|
+
* execution record is the only object binding a session to a card, and an
|
|
352
|
+
* already-settled execution is deliberately not returned (a session the board
|
|
353
|
+
* no longer owns must not be gated).
|
|
354
|
+
* @param sessionId - the DSH session the tool call runs in.
|
|
355
|
+
* @returns the open execution and its task, or undefined.
|
|
356
|
+
*/
|
|
357
|
+
findOpenExecutionBySession(sessionId: string): {
|
|
358
|
+
task: TaskRecord;
|
|
359
|
+
execution: ExecutionRecord;
|
|
360
|
+
} | undefined;
|
|
361
|
+
/**
|
|
362
|
+
* Replace one execution's acceptance block (creating it when absent).
|
|
363
|
+
*
|
|
364
|
+
* A no-op when the serialized value is unchanged, so a coarse caller that
|
|
365
|
+
* re-writes the same state never bumps the ledger revision. A settled
|
|
366
|
+
* execution keeps its record: the report of a finished cycle must survive,
|
|
367
|
+
* and only the board's own settlement moves the card.
|
|
368
|
+
* @param taskId - the task owning the execution.
|
|
369
|
+
* @param executionId - the execution to update.
|
|
370
|
+
* @param verification - the new block.
|
|
371
|
+
* @returns true when the ledger changed.
|
|
372
|
+
*/
|
|
373
|
+
setVerification(taskId: string, executionId: string, verification: ExecutionVerification): boolean;
|
|
255
374
|
private load;
|
|
256
375
|
private normalizeDocument;
|
|
257
376
|
/** Quarantine an unreadable document and start from an empty ledger. */
|
|
@@ -3,7 +3,10 @@ import type { SessionSummary } from '@deepseek-ai/dsh-api-session-controller/typ
|
|
|
3
3
|
import type { CommandResult } from '@deepseek-ai/dsh-commands/types';
|
|
4
4
|
import type { Workspace } from '@deepseek-ai/dsh-workspace/types';
|
|
5
5
|
import type { TaskRecord } from './core/tasks.ts';
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Host services needed to validate a task's workspace before creating a
|
|
8
|
+
* session, and to resolve the workspace an unpinned card runs in.
|
|
9
|
+
*/
|
|
7
10
|
export interface TaskBoardWorkspaceRegistry {
|
|
8
11
|
list(): readonly Workspace[];
|
|
9
12
|
}
|
|
@@ -75,15 +78,16 @@ export interface PromptContext {
|
|
|
75
78
|
/** True when those members run as teammates inside this session (Team Lead). */
|
|
76
79
|
team?: boolean;
|
|
77
80
|
/**
|
|
78
|
-
* Scheduled-run provenance: the instant the
|
|
79
|
-
* IANA zone its wall clock was read in. Present only for a
|
|
80
|
-
* run, so the model can resolve an unqualified date in the
|
|
81
|
-
* instead of guessing from the Host clock (issue #1722).
|
|
81
|
+
* Scheduled-run provenance: the instant the rule actually fired, its kind,
|
|
82
|
+
* and the IANA zone its wall clock was read in. Present only for a
|
|
83
|
+
* timer-triggered run, so the model can resolve an unqualified date in the
|
|
84
|
+
* run's own terms instead of guessing from the Host clock (issue #1722).
|
|
82
85
|
*/
|
|
83
86
|
schedule?: {
|
|
84
87
|
triggeredAt: number;
|
|
85
88
|
timeZone: string;
|
|
86
|
-
|
|
89
|
+
mode: 'cron' | 'once';
|
|
90
|
+
cron?: string;
|
|
87
91
|
};
|
|
88
92
|
}
|
|
89
93
|
/**
|
|
@@ -118,6 +122,14 @@ export declare class HostExecutionRunner {
|
|
|
118
122
|
});
|
|
119
123
|
private invoke;
|
|
120
124
|
private stream;
|
|
125
|
+
/**
|
|
126
|
+
* The workspace an unpinned run lands in: the deployment's most recently used
|
|
127
|
+
* one. Undefined when the deployment serves no workspace registry or has
|
|
128
|
+
* registered none yet; the launch then keeps the "let the Host decide" shape,
|
|
129
|
+
* which is the only remaining path to the Host's own working directory.
|
|
130
|
+
* @returns the workspace id to create the session in, when one is known.
|
|
131
|
+
*/
|
|
132
|
+
private recentWorkspaceId;
|
|
121
133
|
/**
|
|
122
134
|
* Launch one execution. Without `options.reuseSessionId` a fresh session is
|
|
123
135
|
* created, renamed, pinned, and prompted (the historical contract). With it,
|
|
@@ -131,6 +143,20 @@ export declare class HostExecutionRunner {
|
|
|
131
143
|
launch(task: TaskRecord, options?: {
|
|
132
144
|
reuseSessionId?: string;
|
|
133
145
|
promptContext?: PromptContext;
|
|
146
|
+
onSession?: (sessionId: string) => void;
|
|
147
|
+
onGoalArmed?: (armed: boolean) => void;
|
|
148
|
+
/**
|
|
149
|
+
* GLOBAL native /goal switch, resolved by the caller ONCE per execution and
|
|
150
|
+
* carried here so the decision is frozen for this launch.
|
|
151
|
+
*
|
|
152
|
+
* Frozen deliberately: a settings edit made while the run is in flight must
|
|
153
|
+
* not arm, disarm or otherwise change the goal/acceptance contract of a run
|
|
154
|
+
* already running. Absent means off — the default for every deployment that
|
|
155
|
+
* never touched the switch, including cards written before the option
|
|
156
|
+
* existed. A plain single turn is what an off switch produces; the task-level
|
|
157
|
+
* `goalRun` still applies on top of it (both must ASK for a goal).
|
|
158
|
+
*/
|
|
159
|
+
goalEnabled?: boolean;
|
|
134
160
|
}): Promise<string>;
|
|
135
161
|
/**
|
|
136
162
|
* Fail closed when a reused session records a different Agent preset than
|
|
@@ -153,6 +179,15 @@ export declare class HostExecutionRunner {
|
|
|
153
179
|
* the same permission/model pins before the prompt.
|
|
154
180
|
*/
|
|
155
181
|
private pinAndPrompt;
|
|
182
|
+
/**
|
|
183
|
+
* Read the host's model catalog: the default route an unconfigured session
|
|
184
|
+
* starts at, and each provider's models with the reasoning metadata its
|
|
185
|
+
* adapter exposes. The acceptance settings card and the frozen contract both
|
|
186
|
+
* resolve against it, so "inherit host" means the host's own configuration
|
|
187
|
+
* rather than a session's or a card's pinned model.
|
|
188
|
+
* @returns the raw catalog value, or undefined when this cohort serves none.
|
|
189
|
+
*/
|
|
190
|
+
modelCatalog(): Promise<unknown>;
|
|
156
191
|
/**
|
|
157
192
|
* Arm dsh's built-in goal on the session. The task prompt is queued FIRST, so
|
|
158
193
|
* the session's first turn carries the instruction verbatim; `/goal
|
|
@@ -160,11 +195,21 @@ export declare class HostExecutionRunner {
|
|
|
160
195
|
* dsh's goal-round driver keeps starting continuation rounds until the agent
|
|
161
196
|
* marks it complete (see {@link goalVerdict} for how the run settles).
|
|
162
197
|
*
|
|
163
|
-
*
|
|
198
|
+
* Two switches gate the arming, and BOTH must ask for it:
|
|
199
|
+
* - the GLOBAL native-/goal switch (`goalEnabled`, default OFF), frozen when
|
|
200
|
+
* this execution started; and
|
|
201
|
+
* - the task's own `goalRun` (absent means off, only an explicit true opts
|
|
202
|
+
* the card into a goal run).
|
|
203
|
+
*
|
|
164
204
|
* A refusal (no command dispatcher, no `/goal` command in this cohort, an
|
|
165
|
-
* objective the command rejects) is reported and the run continues as
|
|
166
|
-
*
|
|
167
|
-
*
|
|
205
|
+
* objective the command rejects) is reported and the run continues as a plain
|
|
206
|
+
* turn: the task was asked to run, and a missing goal mode must not lose the
|
|
207
|
+
* work.
|
|
208
|
+
* @param sessionId - the session to arm in.
|
|
209
|
+
* @param task - the task being run.
|
|
210
|
+
* @param context - the run's prompt context.
|
|
211
|
+
* @param goalEnabled - the GLOBAL switch, frozen for this execution.
|
|
212
|
+
* @returns whether `/goal` was really armed.
|
|
168
213
|
*/
|
|
169
214
|
private armGoal;
|
|
170
215
|
/**
|
|
@@ -3,6 +3,10 @@ import { HostTaskLedger } from './host-ledger.ts';
|
|
|
3
3
|
import { HostExecutionRunner, type SessionCommandDispatcher, type TaskBoardWorkspaceRegistry } from './host-runner.ts';
|
|
4
4
|
import { PowerInhibitor } from './power-inhibitor.ts';
|
|
5
5
|
import { type TaskBoardAction, type TaskBoardEventPayload, type TaskBoardSnapshot } from './protocol.ts';
|
|
6
|
+
import { TaskBoardExtensionRegistry } from './host/extension-registry.ts';
|
|
7
|
+
import type { TaskBoardExtension } from './core/extension.ts';
|
|
8
|
+
import type { ScheduleMode } from './core/tasks.ts';
|
|
9
|
+
import { type ModelCatalogView, type VerificationContract, type VerificationSettings } from './core/verification.ts';
|
|
6
10
|
import type { TaskPermission } from './core/handover.ts';
|
|
7
11
|
/** One teammate the Host asks the Agent Teams service to spawn for a team run. */
|
|
8
12
|
export interface TeamSpawnInput {
|
|
@@ -31,6 +35,30 @@ export interface TeamSpawnResult {
|
|
|
31
35
|
export interface TaskBoardTeamDispatcher {
|
|
32
36
|
spawn(input: TeamSpawnInput): Promise<TeamSpawnResult>;
|
|
33
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Why an enforced goal execution settled failed while its acceptance DID run:
|
|
40
|
+
* attempts were recorded and none of them passed. The judge answered about the
|
|
41
|
+
* work and the work did not pass.
|
|
42
|
+
*/
|
|
43
|
+
export declare const NO_MATCHING_PASS_VERIFICATION_REASON = "goal \u9A8C\u6536\uFF1A\u672C\u6B21\u6267\u884C\u6CA1\u6709\u5339\u914D\u7684\u9A8C\u6536\u901A\u8FC7\u8BB0\u5F55\uFF08\u9A8C\u6536\u672A\u8FD0\u884C\u3001\u672A\u901A\u8FC7\u6216\u62A5\u544A\u6765\u81EA\u5176\u4ED6\u6267\u884C\uFF09\uFF0C\u6309\u672A\u9A8C\u6536\u5224\u5931\u8D25\u3002";
|
|
44
|
+
/**
|
|
45
|
+
* Why an enforced goal execution settled failed with ZERO acceptance records:
|
|
46
|
+
* the gate was never opened, so the judge never ran and nothing was ever judged
|
|
47
|
+
* (issue #1837). The root cause is a session that declared completion in prose
|
|
48
|
+
* instead of calling `update_goal(action: complete)` — a tool-adherence problem,
|
|
49
|
+
* NOT a quality verdict on the delivery — so this reason says so and keeps the
|
|
50
|
+
* two investigation directions apart.
|
|
51
|
+
*/
|
|
52
|
+
export declare const NEVER_INVOKED_VERIFICATION_REASON = "goal \u9A8C\u6536\u672A\u89E6\u53D1\uFF1A\u672C\u6B21\u6267\u884C\u6CA1\u6709\u4EFB\u4F55\u9A8C\u6536\u8BB0\u5F55\uFF0C\u9A8C\u6536\u95E8\u4ECE\u672A\u6253\u5F00\u2014\u2014\u6267\u884C\u4F1A\u8BDD\u6CA1\u6709\u8C03\u7528 update_goal(action: complete) \u6765\u5B8C\u6210\u76EE\u6807\uFF08\u5E38\u89C1\u4E8E\u53EA\u5728\u56DE\u590D\u91CC\u5BA3\u544A\u5B8C\u6210\uFF09\u3002\u8FD9\u4E0D\u662F\u8D28\u91CF\u5224\u8D1F\uFF1A\u4EA4\u4ED8\u4ECE\u672A\u88AB\u88C1\u5224\u8BC4\u4F30\u3002";
|
|
53
|
+
/**
|
|
54
|
+
* Why an enforced goal execution settled failed while its ONLY acceptance
|
|
55
|
+
* records are INVALID: the judge answered but could not locate its own
|
|
56
|
+
* rejection, so the board stopped calling it. This is NOT an evidence-backed
|
|
57
|
+
* quality veto — the requirement is explicit that such a run must not be
|
|
58
|
+
* described as one — but the execution still has no matching pass, so it ends
|
|
59
|
+
* for lack of one, and the reason names that precisely.
|
|
60
|
+
*/
|
|
61
|
+
export declare const INVALID_ONLY_VERIFICATION_REASON = "goal \u9A8C\u6536\u65E0\u6548\uFF1A\u672C\u6B21\u6267\u884C\u53EA\u8BB0\u5F55\u4E86\u65E0\u6548\u9A8C\u6536\uFF08\u88C1\u5224\u672A\u80FD\u7ED9\u51FA\u4E0E\u4EFB\u52A1\u8981\u6C42\u5BF9\u5E94\u3001\u4E14\u53EF\u5B9A\u4F4D\u5230\u672C\u6B21\u8BC1\u636E\u7684\u5426\u51B3\u4F9D\u636E\uFF09\uFF0C\u770B\u677F\u5DF2\u505C\u6B62\u8C03\u7528\u88C1\u5224\u3002\u8FD9**\u4E0D\u662F**\u6709\u8BC1\u636E\u7684\u8D28\u91CF\u5224\u8D1F\uFF1A\u9A8C\u6536\u672C\u8EAB\u4E0D\u53EF\u7528\uFF0C\u672C\u6B21\u8FD0\u884C\u56E0\u6CA1\u6709\u5339\u914D\u7684\u901A\u8FC7\u8BB0\u5F55\u800C\u7ED3\u675F\u3002\u8BF7\u68C0\u67E5\u9A8C\u6536\u73AF\u5883\u4E0E\u8BC1\u636E\u53EF\u89C1\u6027\uFF0C\u6216\u7528 task_board_manage(action=reset-verification) \u6E05\u9664\u8BB0\u5F55\u7684\u65E0\u6548\u9A8C\u6536\u540E\u91CD\u65B0\u5B8C\u6210\u76EE\u6807\u3002";
|
|
34
62
|
/**
|
|
35
63
|
* Provenance of one cron-triggered cascade: when the rule fired and the zone
|
|
36
64
|
* its wall clock was read in. Passed into every launched prompt of that run so
|
|
@@ -39,7 +67,10 @@ export interface TaskBoardTeamDispatcher {
|
|
|
39
67
|
export interface ScheduledRunContext {
|
|
40
68
|
triggeredAt: number;
|
|
41
69
|
timeZone: string;
|
|
42
|
-
|
|
70
|
+
/** Whether this fire came from a recurring rule or a single planned instant. */
|
|
71
|
+
mode: ScheduleMode;
|
|
72
|
+
/** Cron expression of a recurring rule; absent on a one-shot. */
|
|
73
|
+
cron?: string;
|
|
43
74
|
}
|
|
44
75
|
/**
|
|
45
76
|
* The native timer face the Host arms through. The cordis `timer` service
|
|
@@ -59,6 +90,12 @@ export declare class TaskBoardHostService {
|
|
|
59
90
|
private readonly listeners;
|
|
60
91
|
/** The one recurring timer: the session-roster poll. */
|
|
61
92
|
private pollTimer;
|
|
93
|
+
/** Cadence of the roster poll, in seconds (a settings field; see the config schema). */
|
|
94
|
+
private sessionPollSeconds;
|
|
95
|
+
/** Pending delay that follows a failed poll pass, if one is armed. */
|
|
96
|
+
private pollBackoffTimer;
|
|
97
|
+
/** Consecutive failed poll passes; doubles the next retry delay. */
|
|
98
|
+
private consecutivePollFailures;
|
|
62
99
|
/** The armed schedule timer, if a trigger is pending. */
|
|
63
100
|
private scheduleTimer;
|
|
64
101
|
/** The instant the armed schedule timer targets (ms epoch), for resume detection. */
|
|
@@ -66,13 +103,6 @@ export declare class TaskBoardHostService {
|
|
|
66
103
|
private disposed;
|
|
67
104
|
private pollInFlight;
|
|
68
105
|
private active;
|
|
69
|
-
/**
|
|
70
|
-
* Ids the last roster poll saw as present and idle; undefined while the
|
|
71
|
-
* roster is unknown. Session reuse (issue #1419) requires this positive
|
|
72
|
-
* evidence, so a launch before the first successful poll mints a fresh
|
|
73
|
-
* conversation instead of prompting into a session it cannot see.
|
|
74
|
-
*/
|
|
75
|
-
private idleSessionIds;
|
|
76
106
|
/**
|
|
77
107
|
* Consecutive unreadable-history polls per open execution (see
|
|
78
108
|
* {@link noteUnreadableInspection}). Cleared as soon as an inspection
|
|
@@ -80,28 +110,124 @@ export declare class TaskBoardHostService {
|
|
|
80
110
|
*/
|
|
81
111
|
private readonly unreadablePolls;
|
|
82
112
|
private preventIdleSleep;
|
|
113
|
+
private readonly verificationSettings;
|
|
114
|
+
private readonly verificationCatalog;
|
|
83
115
|
private readonly team;
|
|
84
116
|
private readonly timers;
|
|
117
|
+
/** Live reader of the global native-/goal switch; frozen per execution. */
|
|
118
|
+
private readonly goalRunEnabled;
|
|
85
119
|
private lastPowerJson;
|
|
86
120
|
private readonly now;
|
|
121
|
+
/** The deployment's workspaces, consulted to resolve a card that pins none. */
|
|
122
|
+
private readonly workspaceRegistry;
|
|
123
|
+
/**
|
|
124
|
+
* External provider extensions. The board owns task lifecycle and execution;
|
|
125
|
+
* a provider observes them through the registry's capability face and never
|
|
126
|
+
* reaches into the ledger itself.
|
|
127
|
+
*/
|
|
128
|
+
readonly extensions: TaskBoardExtensionRegistry;
|
|
87
129
|
constructor(gateway: TypertGateway, options?: {
|
|
88
130
|
ledger?: HostTaskLedger;
|
|
89
131
|
power?: PowerInhibitor;
|
|
90
132
|
now?: () => number;
|
|
91
133
|
commandDispatcher?: SessionCommandDispatcher;
|
|
92
134
|
workspaceRegistry?: TaskBoardWorkspaceRegistry;
|
|
93
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Permission baseline of the confirmation gate: a fixed value, or a live
|
|
137
|
+
* resolver the board re-reads so a Host Settings change needs no remount.
|
|
138
|
+
*/
|
|
139
|
+
sessionDefaultPermission?: TaskPermission | (() => TaskPermission);
|
|
94
140
|
maxSubtaskDepth?: number;
|
|
95
141
|
team?: TaskBoardTeamDispatcher;
|
|
96
142
|
timers?: HostTimerFace;
|
|
143
|
+
/**
|
|
144
|
+
* Live GLOBAL native /goal switch (a volatile config read). Read ONCE per
|
|
145
|
+
* execution, at launch, and carried by value from then on: a settings edit
|
|
146
|
+
* made while a run is in flight must not arm, disarm or otherwise change the
|
|
147
|
+
* goal/acceptance contract of that run. Absent means OFF, which is the
|
|
148
|
+
* default for every deployment that never configured it.
|
|
149
|
+
*/
|
|
150
|
+
goalRunEnabled?: () => boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Live acceptance settings (volatile config reads). Absent keeps goal
|
|
153
|
+
* acceptance OFF for every execution this service opens, which is what a
|
|
154
|
+
* programmatic mount without the settings domain gets.
|
|
155
|
+
*/
|
|
156
|
+
verificationSettings?: () => VerificationSettings;
|
|
157
|
+
/** The host model catalog the acceptance contract resolves its route from. */
|
|
158
|
+
verificationCatalog?: () => Promise<ModelCatalogView | undefined>;
|
|
97
159
|
});
|
|
98
160
|
start(): void;
|
|
99
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Apply the live configuration. The roster cadence is re-read on every
|
|
163
|
+
* commit, so a settings edit takes effect without a restart; the poll is
|
|
164
|
+
* scheduled at the new cadence immediately rather than waiting out the old
|
|
165
|
+
* interval.
|
|
166
|
+
* @param active - the board's master switch.
|
|
167
|
+
* @param preventIdleSleep - whether the board holds an idle-sleep assertion.
|
|
168
|
+
* @param sessionPollSeconds - roster-poll cadence in seconds (clamped).
|
|
169
|
+
*/
|
|
170
|
+
setConfiguration(active: boolean, preventIdleSleep: boolean, sessionPollSeconds?: number): void;
|
|
100
171
|
snapshot(): TaskBoardSnapshot;
|
|
172
|
+
/**
|
|
173
|
+
* Admit one external provider. Idempotent by extension id; the returned
|
|
174
|
+
* disposer releases it (its stored data stays).
|
|
175
|
+
*/
|
|
176
|
+
registerExtension(extension: TaskBoardExtension): () => void;
|
|
177
|
+
/**
|
|
178
|
+
* The acceptance configuration the settings card displays: the live settings,
|
|
179
|
+
* the contract they resolve to, and the host catalog the choices come from.
|
|
180
|
+
*
|
|
181
|
+
* The card shows the RESOLVED route, not the raw configuration, so "inherit
|
|
182
|
+
* host" reads as the concrete model and reasoning level the next execution
|
|
183
|
+
* will actually freeze, including any recorded effort fallback.
|
|
184
|
+
* @returns the resolved acceptance options.
|
|
185
|
+
*/
|
|
186
|
+
verificationOptions(): Promise<{
|
|
187
|
+
settings: VerificationSettings;
|
|
188
|
+
contract: VerificationContract;
|
|
189
|
+
catalog: ModelCatalogView;
|
|
190
|
+
}>;
|
|
101
191
|
/** SSE frame payload; deliberately skips the tasks deep-clone of {@link snapshot}. */
|
|
102
192
|
eventPayload(): TaskBoardEventPayload;
|
|
103
193
|
subscribe(listener: () => void): () => void;
|
|
104
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Give a root card created without a workspace pin the workspace its creator
|
|
196
|
+
* is in.
|
|
197
|
+
*
|
|
198
|
+
* An agent's `task_board_create` arrives with the calling session, and the
|
|
199
|
+
* GUI submits the session the main view shows, so the card lands where the
|
|
200
|
+
* work was asked for instead of where the Host process happens to run. A card
|
|
201
|
+
* that names a workspace keeps it, and a subtask keeps inheriting its lineage
|
|
202
|
+
* (the runner walks the ancestor chain for that).
|
|
203
|
+
*
|
|
204
|
+
* The initiator is client-asserted, so it only chooses among workspaces the
|
|
205
|
+
* deployment already knows: it can neither register one nor reach outside the
|
|
206
|
+
* list the user sees.
|
|
207
|
+
* @param action - the action about to be applied.
|
|
208
|
+
* @param initiator - the session that issued the action, when one was asserted.
|
|
209
|
+
* @returns the action, with an inherited workspace on a root creation.
|
|
210
|
+
*/
|
|
211
|
+
private withInheritedWorkspace;
|
|
212
|
+
apply(requestId: string, action: Extract<TaskBoardAction, {
|
|
213
|
+
kind: 'extension-action';
|
|
214
|
+
}>, initiator?: string): Promise<TaskBoardSnapshot>;
|
|
215
|
+
apply(requestId: string, action: Exclude<TaskBoardAction, {
|
|
216
|
+
kind: 'extension-action';
|
|
217
|
+
}>, initiator?: string): TaskBoardSnapshot;
|
|
218
|
+
apply(requestId: string, action: TaskBoardAction, initiator?: string): TaskBoardSnapshot | Promise<TaskBoardSnapshot>;
|
|
219
|
+
/**
|
|
220
|
+
* Apply one board-owned action with every gate intact. Provider capability
|
|
221
|
+
* calls and the same-origin wire both land here, so the two surfaces can
|
|
222
|
+
* never disagree about a card.
|
|
223
|
+
*/
|
|
224
|
+
private applyBoardAction;
|
|
225
|
+
/** Route one provider action and answer the resulting board snapshot. */
|
|
226
|
+
private handleExtensionAction;
|
|
227
|
+
/** Current task id -> status map, for change detection around a mutation. */
|
|
228
|
+
private statusMap;
|
|
229
|
+
/** Emit a status change for every task whose column moved, isolated per callback. */
|
|
230
|
+
private emitStatusChanges;
|
|
105
231
|
dispose(): void;
|
|
106
232
|
private launch;
|
|
107
233
|
private scheduleTeammate;
|
|
@@ -113,7 +239,32 @@ export declare class TaskBoardHostService {
|
|
|
113
239
|
* Lead's cascade verdict.
|
|
114
240
|
*/
|
|
115
241
|
private spawnTeammate;
|
|
242
|
+
/**
|
|
243
|
+
* One roster pass, and whether it could read the session tree.
|
|
244
|
+
*
|
|
245
|
+
* The board reads the DSH session roster only while it has something the
|
|
246
|
+
* roster can decide: an execution to inspect, or a card parked in the running
|
|
247
|
+
* column whose verdict may arrive from a settle this process never saw. That
|
|
248
|
+
* gate is what removes the cost the reporter measured — `session/list`
|
|
249
|
+
* rebuilds every persisted session row (string conversion, object allocation,
|
|
250
|
+
* a stat per record), and an idle board with no tasks was paying it every few
|
|
251
|
+
* seconds forever.
|
|
252
|
+
* @returns whether the roster was readable (an idle pass counts as readable).
|
|
253
|
+
*/
|
|
116
254
|
private pollSessions;
|
|
255
|
+
/**
|
|
256
|
+
* The session a run may continue in, for a card that opted into reuse
|
|
257
|
+
* (issue #1419). Reuse requires positive evidence that the previous session
|
|
258
|
+
* is present and idle, and that evidence must be read for THIS launch: an
|
|
259
|
+
* idle board no longer polls, so a roster cached from an earlier pass could
|
|
260
|
+
* be hours old — either refusing a session that has been idle all along, or
|
|
261
|
+
* prompting into one that started running since. A card that did not opt in
|
|
262
|
+
* reads no roster at all, and a read that fails mints a fresh conversation
|
|
263
|
+
* exactly as an unknown roster always did.
|
|
264
|
+
* @param task - the task about to run.
|
|
265
|
+
* @returns the session id to continue in, or undefined for a fresh session.
|
|
266
|
+
*/
|
|
267
|
+
private reuseSessionFor;
|
|
117
268
|
/** Reuse the session list this poll already fetched: one list RPC per tick, not 1 + E. */
|
|
118
269
|
private reconcileExecutions;
|
|
119
270
|
/**
|
|
@@ -125,6 +276,31 @@ export declare class TaskBoardHostService {
|
|
|
125
276
|
* ancestor of it — in the running column with no way out. The first poll of
|
|
126
277
|
* each streak is logged, so the Host log names the session.
|
|
127
278
|
*/
|
|
279
|
+
private settleAndNotify;
|
|
280
|
+
/**
|
|
281
|
+
* Remove one execution's acceptance-only detail after it PASSED and settled.
|
|
282
|
+
*
|
|
283
|
+
* Deliberately narrow: only the acceptance mechanism's own per-attempt
|
|
284
|
+
* material (findings, invalid diagnostics, the bulky judge side) is removed,
|
|
285
|
+
* and only for THIS execution, keyed by its own id in the ledger it belongs
|
|
286
|
+
* to. No user file, task artifact, raw session history or other execution's
|
|
287
|
+
* record is read or written. Idempotent by the record's own state, and it
|
|
288
|
+
* clearly never touches a run that did not pass (the caller's guard) — a
|
|
289
|
+
* failed or invalid execution keeps everything a repair or a review needs.
|
|
290
|
+
* @param taskId - the task whose execution settled.
|
|
291
|
+
* @param executionId - the settled execution.
|
|
292
|
+
*/
|
|
293
|
+
private cleanupAcceptanceDetail;
|
|
294
|
+
/**
|
|
295
|
+
* Catch-up pass: clean the acceptance detail of every execution that PASSED
|
|
296
|
+
* and settled but whose cleanup did not finish (a crash, a failed write, a
|
|
297
|
+
* Host killed mid-cleanup).
|
|
298
|
+
*
|
|
299
|
+
* The same bounds as any other cleanup apply — only a real pass record on a
|
|
300
|
+
* settled execution is touched — so this can never delete material belonging
|
|
301
|
+
* to an execution that did not pass, and never a user file.
|
|
302
|
+
*/
|
|
303
|
+
private cleanupPendingAcceptanceDetail;
|
|
128
304
|
private noteUnreadableInspection;
|
|
129
305
|
/** Drop the armed schedule timer and forget its target. */
|
|
130
306
|
private clearScheduleTimer;
|
|
@@ -161,8 +337,26 @@ export declare class TaskBoardHostService {
|
|
|
161
337
|
* session instead, once that session exists.
|
|
162
338
|
*/
|
|
163
339
|
private dispatchRuns;
|
|
340
|
+
/**
|
|
341
|
+
* Move one execution's applicability without touching its frozen contract or
|
|
342
|
+
* its recorded attempts (used when the run's goal form becomes known).
|
|
343
|
+
*/
|
|
344
|
+
private setApplicability;
|
|
164
345
|
private scheduleLaunch;
|
|
165
346
|
private schedulePoll;
|
|
347
|
+
/**
|
|
348
|
+
* Count one failed pass and arm the retry that follows it.
|
|
349
|
+
*
|
|
350
|
+
* A session tree that is down is retried on a doubling delay instead of
|
|
351
|
+
* hammering it on the fixed cadence: the heartbeat would otherwise repeat
|
|
352
|
+
* every failure — and every retry inside {@link HostExecutionRunner.listRunning}
|
|
353
|
+
* — at exactly the interval the reporter measured.
|
|
354
|
+
*/
|
|
355
|
+
private notePollFailure;
|
|
356
|
+
/** Arm the retry that follows a failed pass, doubling up to the ceiling. */
|
|
357
|
+
private armPollBackoff;
|
|
358
|
+
/** Drop a pending retry; the next regular tick takes over. */
|
|
359
|
+
private clearPollBackoff;
|
|
166
360
|
/**
|
|
167
361
|
* Re-arm from the ledger's current targets. Callers that just changed a
|
|
168
362
|
* schedule (the host routes, the agent tools) invoke this after the write
|