@adhdev/daemon-core 0.9.82-rc.209 → 0.9.82-rc.210
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/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +2 -0
- package/dist/commands/router.d.ts +6 -0
- package/dist/git/git-commands.d.ts +2 -0
- package/dist/git/git-diff.d.ts +6 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.js +5699 -3486
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5679 -3483
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +6 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +5 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +151 -0
- package/dist/mesh/mesh-events-pending.d.ts +33 -0
- package/dist/mesh/mesh-events-stale.d.ts +40 -0
- package/dist/mesh/mesh-events-utils.d.ts +14 -0
- package/dist/mesh/mesh-events.d.ts +5 -198
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
- package/dist/mesh/mesh-ledger.d.ts +19 -0
- package/dist/mesh/mesh-missions.d.ts +58 -0
- package/dist/mesh/mesh-review-inbox.d.ts +90 -0
- package/dist/mesh/mesh-runtime-store.d.ts +175 -0
- package/dist/mesh/mesh-task-stats.d.ts +49 -0
- package/dist/mesh/mesh-work-queue.d.ts +82 -0
- package/dist/mesh/refine-config.d.ts +24 -2
- package/dist/mesh/worktree-bootstrap-config.d.ts +22 -0
- package/dist/providers/acp-provider-instance.d.ts +2 -0
- package/dist/providers/spec/driver.d.ts +8 -0
- package/dist/providers/spec/evaluator.d.ts +4 -5
- package/dist/providers/spec/loader.d.ts +1 -0
- package/dist/providers/spec/schema.gen.d.ts +1409 -6
- package/dist/providers/spec/types.d.ts +188 -175
- package/dist/repo-mesh-types.d.ts +1 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +3 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +20 -7
- package/src/commands/router.ts +594 -66
- package/src/git/git-commands.ts +5 -5
- package/src/git/git-diff.ts +53 -0
- package/src/index.ts +11 -5
- package/src/mesh/coordinator-prompt.ts +14 -1
- package/src/mesh/mesh-delivery-policy.ts +17 -0
- package/src/mesh/mesh-events-coordinator.ts +1404 -0
- package/src/mesh/mesh-events-pending.ts +371 -0
- package/src/mesh/mesh-events-stale.ts +283 -0
- package/src/mesh/mesh-events-utils.ts +161 -0
- package/src/mesh/mesh-events.ts +27 -2143
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
- package/src/mesh/mesh-ledger.ts +134 -2
- package/src/mesh/mesh-missions.ts +151 -0
- package/src/mesh/mesh-review-inbox.ts +307 -0
- package/src/mesh/mesh-runtime-store.ts +539 -3
- package/src/mesh/mesh-task-stats.ts +154 -0
- package/src/mesh/mesh-work-queue.ts +233 -17
- package/src/mesh/refine-config.ts +42 -5
- package/src/mesh/worktree-bootstrap-config.ts +79 -0
- package/src/providers/acp-provider-instance.ts +15 -1
- package/src/providers/cli-provider-instance.ts +34 -13
- package/src/providers/spec/driver.ts +57 -29
- package/src/providers/spec/evaluator.ts +302 -112
- package/src/providers/spec/loader.ts +226 -37
- package/src/providers/spec/schema.gen.ts +450 -334
- package/src/providers/spec/schema.json +162 -75
- package/src/providers/spec/types.ts +234 -183
- package/src/repo-mesh-types.ts +1 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M4.0: Review inbox — derive review items from existing truth.
|
|
3
|
+
*
|
|
4
|
+
* No new store: review items are a query-time projection of
|
|
5
|
+
* - mesh_status node statuses (daemon-owned branchConvergence), and
|
|
6
|
+
* - the task ledger (completion evidence envelopes + refine job results).
|
|
7
|
+
*
|
|
8
|
+
* Scope (M4.0): host-daemon-local nodes only. Remote nodes are excluded and
|
|
9
|
+
* surfaced via remoteNodesExcluded/excludedRemoteNodeIds until the
|
|
10
|
+
* daemon↔daemon P2P relay path is live-verified (M4.2).
|
|
11
|
+
*/
|
|
12
|
+
import type { MeshLedgerEntry } from './mesh-ledger.js';
|
|
13
|
+
export type MeshReviewInboxReason = 'merge_candidate' | 'refine_blocked_review';
|
|
14
|
+
export interface MeshReviewInboxConvergence {
|
|
15
|
+
status: string;
|
|
16
|
+
reason: string | null;
|
|
17
|
+
nextStep: string | null;
|
|
18
|
+
needsConvergence: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface MeshReviewInboxEvidence {
|
|
21
|
+
available: boolean;
|
|
22
|
+
/** Ledger kind of the entry the evidence came from. */
|
|
23
|
+
kind?: 'task_completed' | 'task_failed';
|
|
24
|
+
/** 'task_completion' = ordinary worker completion envelope; 'refine_job' = Refinery result. */
|
|
25
|
+
source?: 'task_completion' | 'refine_job';
|
|
26
|
+
timestamp?: string;
|
|
27
|
+
taskId?: string;
|
|
28
|
+
sessionId?: string;
|
|
29
|
+
/** M2-3 bootstrap stage from the refine validation gate: cached|ran|failed|skipped|legacy|not_configured. */
|
|
30
|
+
bootstrap?: Record<string, unknown> | null;
|
|
31
|
+
validation?: Record<string, unknown> | null;
|
|
32
|
+
checkpoint?: Record<string, unknown> | null;
|
|
33
|
+
worker?: {
|
|
34
|
+
status: string;
|
|
35
|
+
classification?: string;
|
|
36
|
+
changedFiles: string[];
|
|
37
|
+
changedFilesTruncated?: true;
|
|
38
|
+
validationResults: Array<Record<string, unknown>>;
|
|
39
|
+
errors: string[];
|
|
40
|
+
requiresUserAction: boolean;
|
|
41
|
+
} | null;
|
|
42
|
+
finalBranchConvergenceState?: Record<string, unknown>;
|
|
43
|
+
refineJob?: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
export interface MeshReviewInboxDiffFile {
|
|
46
|
+
path: string;
|
|
47
|
+
status?: string;
|
|
48
|
+
insertions?: number;
|
|
49
|
+
deletions?: number;
|
|
50
|
+
binary?: boolean;
|
|
51
|
+
oldPath?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface MeshReviewInboxDiffSummary {
|
|
54
|
+
baseRef: string;
|
|
55
|
+
files: MeshReviewInboxDiffFile[];
|
|
56
|
+
totalFiles: number;
|
|
57
|
+
totalInsertions: number;
|
|
58
|
+
totalDeletions: number;
|
|
59
|
+
truncated: boolean;
|
|
60
|
+
error?: string;
|
|
61
|
+
}
|
|
62
|
+
export interface MeshReviewInboxItem {
|
|
63
|
+
nodeId: string;
|
|
64
|
+
workspace: string | null;
|
|
65
|
+
branch: string | null;
|
|
66
|
+
defaultBranch: string | null;
|
|
67
|
+
isLocalWorktree: boolean;
|
|
68
|
+
reviewReason: MeshReviewInboxReason;
|
|
69
|
+
convergence: MeshReviewInboxConvergence;
|
|
70
|
+
evidence: MeshReviewInboxEvidence;
|
|
71
|
+
transcriptHandle: Record<string, unknown> | null;
|
|
72
|
+
/** Latest non-terminal Refinery job for this node (accepted/running), if any. */
|
|
73
|
+
activeRefineJob: Record<string, unknown> | null;
|
|
74
|
+
lastActivityAt: string | null;
|
|
75
|
+
/** Filled by the daemon command with a bounded base-branch diff probe; null when the workspace is not locally readable. */
|
|
76
|
+
diffSummary?: MeshReviewInboxDiffSummary | null;
|
|
77
|
+
}
|
|
78
|
+
export interface MeshReviewInboxDerivation {
|
|
79
|
+
items: MeshReviewInboxItem[];
|
|
80
|
+
remoteNodesExcluded: boolean;
|
|
81
|
+
excludedRemoteNodeIds: string[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Derive review inbox items from mesh_status node statuses and a bounded
|
|
85
|
+
* ledger tail. Pure and read-only; the caller attaches diffSummary separately.
|
|
86
|
+
*/
|
|
87
|
+
export declare function deriveMeshReviewInboxItems(args: {
|
|
88
|
+
nodes: Array<Record<string, unknown>>;
|
|
89
|
+
ledgerEntries: MeshLedgerEntry[];
|
|
90
|
+
}): MeshReviewInboxDerivation;
|
|
@@ -146,4 +146,179 @@ export declare class MeshRuntimeStore {
|
|
|
146
146
|
event: string;
|
|
147
147
|
createdAt: string;
|
|
148
148
|
}>;
|
|
149
|
+
/**
|
|
150
|
+
* Record a mesh tool call and check whether this mesh+tool combination is
|
|
151
|
+
* being called too rapidly (sliding window rate guard).
|
|
152
|
+
*
|
|
153
|
+
* Returns a rate-limit advisory string when the call rate is too high, null otherwise.
|
|
154
|
+
* windowMs: sliding window size in ms (default 10s)
|
|
155
|
+
* maxCalls: max allowed calls within the window (default 5)
|
|
156
|
+
*/
|
|
157
|
+
recordMeshToolCall(opts: {
|
|
158
|
+
meshId: string;
|
|
159
|
+
tool: string;
|
|
160
|
+
sessionId?: string | null;
|
|
161
|
+
windowMs?: number;
|
|
162
|
+
maxCalls?: number;
|
|
163
|
+
}): {
|
|
164
|
+
rateLimitExceeded: boolean;
|
|
165
|
+
callsInWindow: number;
|
|
166
|
+
advisory: string | null;
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Prune tool call log entries older than the given age in ms.
|
|
170
|
+
* Exposed for testing.
|
|
171
|
+
*/
|
|
172
|
+
pruneToolCallLog(olderThanMs: number): void;
|
|
173
|
+
appendLedgerEntry(entry: {
|
|
174
|
+
id: string;
|
|
175
|
+
meshId: string;
|
|
176
|
+
timestamp: string;
|
|
177
|
+
kind: string;
|
|
178
|
+
nodeId?: string | null;
|
|
179
|
+
sessionId?: string | null;
|
|
180
|
+
providerType?: string | null;
|
|
181
|
+
payload?: unknown;
|
|
182
|
+
}): void;
|
|
183
|
+
readLedgerEntries(meshId: string, opts?: {
|
|
184
|
+
tail?: number;
|
|
185
|
+
since?: string;
|
|
186
|
+
kind?: string;
|
|
187
|
+
limit?: number;
|
|
188
|
+
}): Array<{
|
|
189
|
+
id: string;
|
|
190
|
+
meshId: string;
|
|
191
|
+
timestamp: string;
|
|
192
|
+
kind: string;
|
|
193
|
+
nodeId: string | null;
|
|
194
|
+
sessionId: string | null;
|
|
195
|
+
providerType: string | null;
|
|
196
|
+
payload: unknown;
|
|
197
|
+
}>;
|
|
198
|
+
/**
|
|
199
|
+
* G2 read cutover: read ledger entries in append order (oldest first),
|
|
200
|
+
* matching legacy JSONL file-order semantics. Ties on the same timestamp
|
|
201
|
+
* are broken by rowid (insertion order), preserving the positional
|
|
202
|
+
* guarantee that mesh-events relies on for same-millisecond entries.
|
|
203
|
+
*/
|
|
204
|
+
readLedgerEntriesOrdered(meshId: string, opts?: {
|
|
205
|
+
since?: string;
|
|
206
|
+
kinds?: string[];
|
|
207
|
+
tail?: number;
|
|
208
|
+
}): Array<{
|
|
209
|
+
id: string;
|
|
210
|
+
meshId: string;
|
|
211
|
+
timestamp: string;
|
|
212
|
+
kind: string;
|
|
213
|
+
nodeId: string | null;
|
|
214
|
+
sessionId: string | null;
|
|
215
|
+
providerType: string | null;
|
|
216
|
+
payload: unknown;
|
|
217
|
+
}>;
|
|
218
|
+
/** Remove all ledger entries for a mesh (mesh deletion / test cleanup). */
|
|
219
|
+
clearLedgerForMesh(meshId: string): number;
|
|
220
|
+
/** G2: remove entries moved to the JSONL archive so the SQLite runtime set mirrors the active ledger. */
|
|
221
|
+
deleteLedgerEntries(meshId: string, ids: string[]): number;
|
|
222
|
+
hasLedgerEntry(meshId: string, id: string): boolean;
|
|
223
|
+
ledgerEntryCount(meshId: string): number;
|
|
224
|
+
importLedgerEntries(entries: Array<{
|
|
225
|
+
id: string;
|
|
226
|
+
meshId: string;
|
|
227
|
+
timestamp: string;
|
|
228
|
+
kind: string;
|
|
229
|
+
nodeId?: string | null;
|
|
230
|
+
sessionId?: string | null;
|
|
231
|
+
providerType?: string | null;
|
|
232
|
+
payload?: unknown;
|
|
233
|
+
}>): number;
|
|
234
|
+
/**
|
|
235
|
+
* G4: Read a bounded, cursor-addressable ledger slice directly from the SQLite
|
|
236
|
+
* mesh_event_ledger table. This is the P2P reconcile read path; JSONL files are
|
|
237
|
+
* retained as export/import/debug/legacy artifacts only.
|
|
238
|
+
*
|
|
239
|
+
* The return shape is structurally compatible with MeshLedgerSlice so callers
|
|
240
|
+
* in mesh-tools.ts can pass it directly to buildMeshLedgerReplicaEvidence.
|
|
241
|
+
*/
|
|
242
|
+
readLedgerSlice(meshId: string, opts?: {
|
|
243
|
+
afterId?: string;
|
|
244
|
+
since?: string;
|
|
245
|
+
kind?: string;
|
|
246
|
+
limit?: number;
|
|
247
|
+
}): {
|
|
248
|
+
protocol: 'adhdev.mesh.ledger.slice.v1';
|
|
249
|
+
meshId: string;
|
|
250
|
+
entries: Array<{
|
|
251
|
+
id: string;
|
|
252
|
+
meshId: string;
|
|
253
|
+
timestamp: string;
|
|
254
|
+
kind: string;
|
|
255
|
+
nodeId: string | null;
|
|
256
|
+
sessionId: string | null;
|
|
257
|
+
providerType: string | null;
|
|
258
|
+
payload: unknown;
|
|
259
|
+
}>;
|
|
260
|
+
cursor: {
|
|
261
|
+
afterId: string | null;
|
|
262
|
+
nextAfterId: string | null;
|
|
263
|
+
limit: number;
|
|
264
|
+
hasMore: boolean;
|
|
265
|
+
};
|
|
266
|
+
sourceOfTruth: {
|
|
267
|
+
kind: 'local_sqlite';
|
|
268
|
+
table: 'mesh_event_ledger';
|
|
269
|
+
bounded: true;
|
|
270
|
+
maxLimit: number;
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
insertPendingEvent(event: {
|
|
274
|
+
id: string;
|
|
275
|
+
meshId: string;
|
|
276
|
+
coordinatorDaemonId?: string | null;
|
|
277
|
+
event: string;
|
|
278
|
+
payload?: unknown;
|
|
279
|
+
fingerprint?: string | null;
|
|
280
|
+
queuedAt: number;
|
|
281
|
+
}): boolean;
|
|
282
|
+
drainPendingEvents(meshId: string, coordinatorDaemonId?: string | null): Array<{
|
|
283
|
+
id: string;
|
|
284
|
+
event: string;
|
|
285
|
+
payload: unknown;
|
|
286
|
+
}>;
|
|
287
|
+
/** Non-destructive peek — returns undrained events without marking them drained. */
|
|
288
|
+
peekPendingEvents(meshId: string, coordinatorDaemonId?: string | null): Array<{
|
|
289
|
+
id: string;
|
|
290
|
+
event: string;
|
|
291
|
+
payload: unknown;
|
|
292
|
+
}>;
|
|
293
|
+
hasPendingEventFingerprint(meshId: string, fingerprint: string): boolean;
|
|
294
|
+
upsertMission(mission: {
|
|
295
|
+
id: string;
|
|
296
|
+
meshId: string;
|
|
297
|
+
title: string;
|
|
298
|
+
goal?: string;
|
|
299
|
+
status?: string;
|
|
300
|
+
}): void;
|
|
301
|
+
getMission(meshId: string, missionId: string): {
|
|
302
|
+
id: string;
|
|
303
|
+
meshId: string;
|
|
304
|
+
title: string;
|
|
305
|
+
goal: string;
|
|
306
|
+
status: string;
|
|
307
|
+
createdAt: string;
|
|
308
|
+
updatedAt: string;
|
|
309
|
+
} | null;
|
|
310
|
+
getMissions(meshId: string, statuses?: string[]): Array<{
|
|
311
|
+
id: string;
|
|
312
|
+
meshId: string;
|
|
313
|
+
title: string;
|
|
314
|
+
goal: string;
|
|
315
|
+
status: string;
|
|
316
|
+
createdAt: string;
|
|
317
|
+
updatedAt: string;
|
|
318
|
+
}>;
|
|
319
|
+
/** Remove all missions for a mesh — mesh deletion / test cleanup. */
|
|
320
|
+
clearMissionsForMesh(meshId: string): number;
|
|
321
|
+
/** Remove all pending-event rows (drained included) for a mesh — mesh deletion / test cleanup. */
|
|
322
|
+
clearPendingEventsForMesh(meshId: string): number;
|
|
323
|
+
pendingEventCount(meshId: string): number;
|
|
149
324
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M7: Operational stats (time/attempts) derived from existing truth.
|
|
3
|
+
*
|
|
4
|
+
* No cost/token accounting — ADHDev observes PTY/CDP and cannot see API
|
|
5
|
+
* tokens (explicit non-goal). Everything here is derived at query time from
|
|
6
|
+
* the SQLite ledger and queue rows; there is no separate aggregate table.
|
|
7
|
+
* Tasks with missing ledger evidence report incompleteEvidence instead of
|
|
8
|
+
* estimated numbers.
|
|
9
|
+
*/
|
|
10
|
+
export interface MeshTaskStats {
|
|
11
|
+
taskId: string;
|
|
12
|
+
status: string;
|
|
13
|
+
dispatchedAt: string | null;
|
|
14
|
+
terminalAt: string | null;
|
|
15
|
+
terminalKind: 'task_completed' | 'task_failed' | null;
|
|
16
|
+
/** dispatched → terminal wall clock; null when evidence is incomplete. */
|
|
17
|
+
durationMs: number | null;
|
|
18
|
+
/** Number of task_dispatched ledger entries observed for this task. */
|
|
19
|
+
dispatchCount: number;
|
|
20
|
+
/** Queue requeueCount (0 when the row is gone or never requeued). */
|
|
21
|
+
requeueCount: number;
|
|
22
|
+
/** True when dispatch or terminal ledger evidence is missing — numbers are withheld, never estimated. */
|
|
23
|
+
incompleteEvidence?: true;
|
|
24
|
+
}
|
|
25
|
+
export interface MeshMissionStats {
|
|
26
|
+
missionId: string;
|
|
27
|
+
taskCount: number;
|
|
28
|
+
completed: number;
|
|
29
|
+
failed: number;
|
|
30
|
+
/** Sum of per-task durations with complete evidence. */
|
|
31
|
+
totalDurationMs: number;
|
|
32
|
+
/** First dispatch → last terminal across the mission's tasks; null without complete endpoints. */
|
|
33
|
+
wallClockMs: number | null;
|
|
34
|
+
/** Total requeue attempts across the mission's tasks. */
|
|
35
|
+
retries: number;
|
|
36
|
+
/** Task ids whose ledger evidence was incomplete (excluded from sums). */
|
|
37
|
+
incompleteTaskIds: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compute per-task stats from ledger entries. Scans a bounded tail window —
|
|
41
|
+
* stats are an operational view of recent work, not a full historical report.
|
|
42
|
+
*/
|
|
43
|
+
export declare function computeMeshTaskStats(meshId: string, opts?: {
|
|
44
|
+
taskIds?: string[];
|
|
45
|
+
missionId?: string;
|
|
46
|
+
tail?: number;
|
|
47
|
+
}): MeshTaskStats[];
|
|
48
|
+
/** Mission rollup — derived from per-task stats, no stored aggregates. */
|
|
49
|
+
export declare function computeMeshMissionStats(meshId: string, missionId: string): MeshMissionStats;
|
|
@@ -27,6 +27,20 @@ export interface MeshWorkQueueEntry {
|
|
|
27
27
|
targetSessionId?: string;
|
|
28
28
|
/** If specified, a node must expose all tags before it can claim the task. */
|
|
29
29
|
requiredTags?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* M1: ids of tasks that must reach 'completed' before this task is claimable.
|
|
32
|
+
* Forward references (ids not yet enqueued) are allowed for batch flows and
|
|
33
|
+
* simply keep the task waiting until the referenced task exists and completes.
|
|
34
|
+
*/
|
|
35
|
+
dependsOn?: string[];
|
|
36
|
+
/** M1/M3: mission this task belongs to (joins mesh_missions). */
|
|
37
|
+
missionId?: string;
|
|
38
|
+
/**
|
|
39
|
+
* M1: why this task is held back (e.g. "dependency_failed:<taskId>").
|
|
40
|
+
* Only set by the system on dependency failure under the 'block' policy;
|
|
41
|
+
* waiting-on-dependency state is computed at view time, not stored.
|
|
42
|
+
*/
|
|
43
|
+
blockedReason?: string;
|
|
30
44
|
/** The node that actually claimed and is executing the task */
|
|
31
45
|
assignedNodeId?: string;
|
|
32
46
|
/** The session currently executing the task */
|
|
@@ -38,6 +52,8 @@ export interface MeshWorkQueueEntry {
|
|
|
38
52
|
requeueReason?: string;
|
|
39
53
|
requeuedAt?: string;
|
|
40
54
|
requeueCount?: number;
|
|
55
|
+
/** Max automatic requeue attempts. When requeueCount reaches this, task is auto-failed. */
|
|
56
|
+
maxRetries?: number;
|
|
41
57
|
/** Last automatic queue session spin-up attempt, for mesh_view_queue/debug visibility. */
|
|
42
58
|
autoLaunch?: {
|
|
43
59
|
status: 'skipped' | 'started' | 'failed' | 'completed';
|
|
@@ -59,8 +75,16 @@ export declare function normalizeMeshCapabilityTags(value: unknown): string[];
|
|
|
59
75
|
export declare function buildMeshNodeCapabilityTags(node: {
|
|
60
76
|
capabilities?: unknown;
|
|
61
77
|
policy?: unknown;
|
|
78
|
+
isLocalWorktree?: unknown;
|
|
79
|
+
worktreeBranch?: unknown;
|
|
62
80
|
} | undefined, providerType?: string): string[];
|
|
63
81
|
export declare function nodeSatisfiesRequiredTags(requiredTags: unknown, capabilityTags: unknown): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* M1: detect dependency cycles before enqueue. Walks the dependency graph of
|
|
84
|
+
* existing queue entries plus the new task's edges. Fail-closed: a cycle
|
|
85
|
+
* rejects the enqueue entirely. Synchronous and bounded by queue size.
|
|
86
|
+
*/
|
|
87
|
+
export declare function assertNoDependencyCycle(meshId: string, newTaskId: string, dependsOn: string[]): void;
|
|
64
88
|
/**
|
|
65
89
|
* Add a new task to the mesh queue.
|
|
66
90
|
*/
|
|
@@ -69,6 +93,12 @@ export declare function enqueueTask(meshId: string, message: string, opts?: {
|
|
|
69
93
|
targetSessionId?: string;
|
|
70
94
|
taskMode?: MeshTaskMode | string;
|
|
71
95
|
requiredTags?: string[];
|
|
96
|
+
/** M1: tasks that must complete before this one is claimable. */
|
|
97
|
+
dependsOn?: string[];
|
|
98
|
+
/** M1/M3: mission this task belongs to. */
|
|
99
|
+
missionId?: string;
|
|
100
|
+
/** Explicit task id for batch/template flows (M5). Random UUID when omitted. */
|
|
101
|
+
id?: string;
|
|
72
102
|
} & MeshQueueMutationOptions): MeshWorkQueueEntry;
|
|
73
103
|
/**
|
|
74
104
|
* Get all tasks in the queue, optionally filtered by status.
|
|
@@ -81,6 +111,7 @@ export declare function getMeshQueueRevision(meshId: string): string;
|
|
|
81
111
|
* Find the next pending task that this node is allowed to claim, and mark it as assigned.
|
|
82
112
|
*/
|
|
83
113
|
export declare function claimNextTask(meshId: string, nodeId: string, sessionId: string, capabilityTags?: string[]): MeshWorkQueueEntry | null;
|
|
114
|
+
export type DependencyFailurePolicy = 'block' | 'cancel';
|
|
84
115
|
/**
|
|
85
116
|
* Update the status of a specific task.
|
|
86
117
|
* Used when a session completes, fails, or stalls.
|
|
@@ -97,12 +128,30 @@ export declare function cancelTask(meshId: string, taskId: string, opts?: {
|
|
|
97
128
|
* Return a queue task to pending for retry. By default, dead session targeting
|
|
98
129
|
* and assigned ownership are cleared so stale assignments do not strand again.
|
|
99
130
|
*/
|
|
131
|
+
export type RequeueResult = {
|
|
132
|
+
status: 'requeued';
|
|
133
|
+
entry: MeshWorkQueueEntry;
|
|
134
|
+
} | {
|
|
135
|
+
status: 'failed_max_retries';
|
|
136
|
+
entry: MeshWorkQueueEntry;
|
|
137
|
+
maxRetries: number;
|
|
138
|
+
requeueCount: number;
|
|
139
|
+
} | {
|
|
140
|
+
status: 'not_found';
|
|
141
|
+
};
|
|
100
142
|
export declare function requeueTask(meshId: string, taskId: string, opts?: {
|
|
101
143
|
reason?: string;
|
|
102
144
|
targetNodeId?: string;
|
|
103
145
|
targetSessionId?: string;
|
|
104
146
|
clearTargetNode?: boolean;
|
|
105
147
|
clearTargetSession?: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Override the retry cap for this call. Use only for explicit operator actions.
|
|
150
|
+
* If true, the task is requeued even when requeueCount >= maxRetries.
|
|
151
|
+
*/
|
|
152
|
+
force?: boolean;
|
|
153
|
+
/** Per-task retry cap override. Falls back to mesh policy maxTaskRetries (default 1). */
|
|
154
|
+
maxRetries?: number;
|
|
106
155
|
} & MeshQueueMutationOptions): MeshWorkQueueEntry | null;
|
|
107
156
|
/**
|
|
108
157
|
* Update the status of the task currently assigned to a specific session.
|
|
@@ -110,6 +159,20 @@ export declare function requeueTask(meshId: string, taskId: string, opts?: {
|
|
|
110
159
|
export declare function updateSessionTaskStatus(meshId: string, sessionId: string, status: MeshTaskStatus, opts?: {
|
|
111
160
|
occurredAt?: string;
|
|
112
161
|
}): MeshWorkQueueEntry | null;
|
|
162
|
+
/**
|
|
163
|
+
* M1-3: true when at least one pending task is waiting on the given task.
|
|
164
|
+
* Used by the completion event path to decide whether to wake the queue.
|
|
165
|
+
*/
|
|
166
|
+
export declare function hasPendingDependents(meshId: string, taskId: string): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* M1-4: view-time dependency state for a task — unmet dependency ids and
|
|
169
|
+
* whether the task is currently claimable from a dependency standpoint.
|
|
170
|
+
* Not stored (truth stays in task statuses).
|
|
171
|
+
*/
|
|
172
|
+
export declare function describeTaskDependencyState(entry: Pick<MeshWorkQueueEntry, 'dependsOn' | 'blockedReason'>, statusById: Map<string, MeshTaskStatus | string>): {
|
|
173
|
+
waitingOn: string[];
|
|
174
|
+
dependenciesSatisfied: boolean;
|
|
175
|
+
};
|
|
113
176
|
export interface MeshWorkQueueStats {
|
|
114
177
|
total: number;
|
|
115
178
|
active: number;
|
|
@@ -154,3 +217,22 @@ export declare function getActiveDirectDispatches(meshId: string): DirectDispatc
|
|
|
154
217
|
export declare function updateDirectDispatchStatus(meshId: string, sessionId: string, status: 'acked' | 'completed' | 'failed' | 'stale'): void;
|
|
155
218
|
export declare function cleanupTerminalDirectDispatches(olderThanMs?: number): void;
|
|
156
219
|
export declare function markStaleDirectDispatches(meshId: string, olderThanMs?: number): void;
|
|
220
|
+
export type MeshToolCallRateResult = {
|
|
221
|
+
rateLimitExceeded: boolean;
|
|
222
|
+
callsInWindow: number;
|
|
223
|
+
advisory: string | null;
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Record a coordinator tool call and return a rate-limit advisory when the
|
|
227
|
+
* call rate for that tool exceeds the allowed threshold.
|
|
228
|
+
*
|
|
229
|
+
* Defaults: 10-second sliding window, max 5 calls before advisory is raised.
|
|
230
|
+
* Returns { rateLimitExceeded: false } on any store error so callers are not blocked.
|
|
231
|
+
*/
|
|
232
|
+
export declare function recordMeshToolCall(opts: {
|
|
233
|
+
meshId: string;
|
|
234
|
+
tool: string;
|
|
235
|
+
sessionId?: string | null;
|
|
236
|
+
windowMs?: number;
|
|
237
|
+
maxCalls?: number;
|
|
238
|
+
}): MeshToolCallRateResult;
|
|
@@ -23,8 +23,18 @@ export interface RepoMeshRefineConfig {
|
|
|
23
23
|
validation?: {
|
|
24
24
|
required?: boolean;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* M2-2 (v2): how Refinery sources its bootstrap stage.
|
|
27
|
+
* 'inherit' (default) — consume the worktree_bootstrap config/state:
|
|
28
|
+
* skip when the node's bootstrap is 'ready' (staleInputs unchanged),
|
|
29
|
+
* run the worktree_bootstrap definition when stale/never-ran.
|
|
30
|
+
* 'skip' — no bootstrap stage at all (validation commands run as-is).
|
|
31
|
+
*/
|
|
32
|
+
bootstrap?: 'inherit' | 'skip';
|
|
33
|
+
/**
|
|
34
|
+
* DEPRECATED (M2-2): define bootstrap once in
|
|
35
|
+
* .adhdev/worktree_bootstrap.json instead. Still honored when no
|
|
36
|
+
* worktree_bootstrap config exists, with a deprecation warning; when
|
|
37
|
+
* both exist the worktree_bootstrap config wins.
|
|
28
38
|
*/
|
|
29
39
|
bootstrapCommands?: RepoMeshRefineValidationCommandConfig[];
|
|
30
40
|
commands?: RepoMeshRefineValidationCommandConfig[];
|
|
@@ -51,9 +61,13 @@ export interface MeshRefineConfigLoadResult {
|
|
|
51
61
|
export interface MeshRefineValidationPlan {
|
|
52
62
|
source: string;
|
|
53
63
|
sourceType: MeshRefineConfigLoadResult['sourceType'];
|
|
64
|
+
/** M2-2: how the bootstrap stage is sourced ('inherit' consumes worktree_bootstrap; 'skip' disables it). */
|
|
65
|
+
bootstrapMode: 'inherit' | 'skip';
|
|
54
66
|
bootstrapCommands: MeshRefineValidationCommandPlan[];
|
|
55
67
|
commands: MeshRefineValidationCommandPlan[];
|
|
56
68
|
rejectedCommands: Array<Record<string, unknown>>;
|
|
69
|
+
/** M2-2: deprecation notices (e.g. validation.bootstrapCommands present). */
|
|
70
|
+
deprecationWarnings: string[];
|
|
57
71
|
suggestions: RepoMeshRefineValidationCommandConfig[];
|
|
58
72
|
suggestedConfig?: RepoMeshRefineConfig;
|
|
59
73
|
unavailableReason?: string;
|
|
@@ -82,6 +96,11 @@ export declare const MESH_REFINE_CONFIG_SCHEMA: {
|
|
|
82
96
|
readonly type: "boolean";
|
|
83
97
|
readonly default: true;
|
|
84
98
|
};
|
|
99
|
+
readonly bootstrap: {
|
|
100
|
+
readonly enum: readonly ["inherit", "skip"];
|
|
101
|
+
readonly default: "inherit";
|
|
102
|
+
readonly description: "M2-2 (v2): 'inherit' consumes the worktree_bootstrap config/state (skip when ready, rerun when stale); 'skip' disables the bootstrap stage entirely.";
|
|
103
|
+
};
|
|
85
104
|
readonly commands: {
|
|
86
105
|
readonly type: "array";
|
|
87
106
|
readonly minItems: 1;
|
|
@@ -129,6 +148,7 @@ export declare const MESH_REFINE_CONFIG_SCHEMA: {
|
|
|
129
148
|
readonly bootstrapCommands: {
|
|
130
149
|
readonly type: "array";
|
|
131
150
|
readonly maxItems: 4;
|
|
151
|
+
readonly description: "DEPRECATED: define bootstrap once in .adhdev/worktree_bootstrap.json. Honored only when no worktree_bootstrap config exists (with a deprecation warning); worktree_bootstrap wins when both exist.";
|
|
132
152
|
readonly items: {
|
|
133
153
|
readonly type: "object";
|
|
134
154
|
readonly additionalProperties: false;
|
|
@@ -184,6 +204,8 @@ export declare function validateMeshRefineConfig(config: unknown, source?: strin
|
|
|
184
204
|
bootstrapCommands: MeshRefineValidationCommandPlan[];
|
|
185
205
|
commands: MeshRefineValidationCommandPlan[];
|
|
186
206
|
rejectedCommands: Array<Record<string, unknown>>;
|
|
207
|
+
bootstrapMode: 'inherit' | 'skip';
|
|
208
|
+
deprecationWarnings: string[];
|
|
187
209
|
};
|
|
188
210
|
export declare function loadMeshRefineConfig(mesh: any, workspace: string): MeshRefineConfigLoadResult;
|
|
189
211
|
export declare function suggestMeshRefineConfig(mesh: any, workspace: string): {
|
|
@@ -18,6 +18,15 @@ export interface WorktreeBootstrapState extends MeshAsyncJobLifecycle {
|
|
|
18
18
|
exitCode?: number | null;
|
|
19
19
|
commandsRun?: Array<Record<string, unknown>>;
|
|
20
20
|
staleInputs?: string[];
|
|
21
|
+
/**
|
|
22
|
+
* M2-1: sha256 per staleInputs path recorded when the bootstrap reached
|
|
23
|
+
* 'ready'. evaluateWorktreeBootstrapState compares current file hashes
|
|
24
|
+
* against this to detect staleness (e.g. base merge changed a lockfile).
|
|
25
|
+
* Missing files hash to the literal 'absent'.
|
|
26
|
+
*/
|
|
27
|
+
staleInputsDigest?: Record<string, string>;
|
|
28
|
+
/** M2-1: why an evaluated state resolved to stale (digest_mismatch | never_ran). */
|
|
29
|
+
staleReason?: string;
|
|
21
30
|
}
|
|
22
31
|
export interface WorktreeBootstrapConfigLoadResult {
|
|
23
32
|
config?: RepoMeshWorktreeBootstrapConfig;
|
|
@@ -110,4 +119,17 @@ export declare function validateMeshWorktreeBootstrapConfig(config: unknown, sou
|
|
|
110
119
|
rejectedCommands: Array<Record<string, unknown>>;
|
|
111
120
|
};
|
|
112
121
|
export declare function loadMeshWorktreeBootstrapConfig(mesh: any, workspace: string): WorktreeBootstrapConfigLoadResult;
|
|
122
|
+
/** M2-1: hash staleInputs files so 'ready' can be invalidated when they change. */
|
|
123
|
+
export declare function computeStaleInputsDigest(workspace: string, staleInputs: string[] | undefined): Record<string, string>;
|
|
124
|
+
/**
|
|
125
|
+
* M2-1: the official bootstrap state contract. Resolves the effective state
|
|
126
|
+
* for a node workspace from config presence + the persisted last-run state +
|
|
127
|
+
* a staleInputs digest comparison. Read-only — never runs commands.
|
|
128
|
+
*
|
|
129
|
+
* ready — last run succeeded and staleInputs are unchanged
|
|
130
|
+
* stale — never ran, or a staleInputs file changed since 'ready'
|
|
131
|
+
* running/failed — persisted lifecycle state passes through
|
|
132
|
+
* not_configured / disabled / (invalid → failed) — from config resolution
|
|
133
|
+
*/
|
|
134
|
+
export declare function evaluateWorktreeBootstrapState(mesh: any, workspace: string, persisted?: WorktreeBootstrapState | null): WorktreeBootstrapState;
|
|
113
135
|
export declare function runMeshWorktreeBootstrap(mesh: any, workspace: string): Promise<WorktreeBootstrapState>;
|
|
@@ -44,6 +44,8 @@ export declare class AcpProviderInstance implements ProviderInstance {
|
|
|
44
44
|
private partialBlocks;
|
|
45
45
|
/** Tool calls collected during current turn */
|
|
46
46
|
private turnToolCalls;
|
|
47
|
+
/** Guard: prevent concurrent sendPrompt calls from racing on shared state */
|
|
48
|
+
private _sendPromptInFlight;
|
|
47
49
|
private errorMessage;
|
|
48
50
|
private errorReason;
|
|
49
51
|
private stderrBuffer;
|
|
@@ -136,8 +136,16 @@ export declare class SpecDriver {
|
|
|
136
136
|
private lastModalAt;
|
|
137
137
|
/** The modal state snapshot held across busy blips. */
|
|
138
138
|
private lastModalState;
|
|
139
|
+
/** Timestamp of when we last *exited* a modal state (approval/picker → idle
|
|
140
|
+
* or directly via completion_idle_after). Used to suppress completion_idle_after
|
|
141
|
+
* firings that were queued before the modal appeared and expire immediately
|
|
142
|
+
* after the modal is dismissed — without this the agent appears idle even
|
|
143
|
+
* though it is still generating. */
|
|
144
|
+
private lastModalExitAt;
|
|
139
145
|
private completionIdleFirstSeenAt;
|
|
140
146
|
private completionIdleKey;
|
|
147
|
+
/** Previous screen lines — passed to evaluate() for `changed` condition detection. */
|
|
148
|
+
private prevScreenLines;
|
|
141
149
|
/** Timer that re-runs evaluate() once the hold window expires. Needed
|
|
142
150
|
* because the PTY stops emitting once the agent finishes; without an
|
|
143
151
|
* explicit wake-up there's nothing to trigger the busy → idle
|
|
@@ -45,11 +45,10 @@ export interface SpecEvaluation {
|
|
|
45
45
|
trace: TraceEntry[];
|
|
46
46
|
}
|
|
47
47
|
export declare function evaluate(spec: CliSpec, screenText: string,
|
|
48
|
-
/** Optional cursor position (0-based row and col).
|
|
49
|
-
* with cursor_row_min/max or cursor_col_min/max predicates are filtered.
|
|
50
|
-
* When omitted, cursor predicates are ignored and evaluation is text-only
|
|
51
|
-
* (backward-compatible with all existing specs and call sites). */
|
|
48
|
+
/** Optional cursor position (0-based row and col). */
|
|
52
49
|
cursor?: {
|
|
53
50
|
row: number;
|
|
54
51
|
col: number;
|
|
55
|
-
}
|
|
52
|
+
},
|
|
53
|
+
/** Optional previous screen lines for `changed` condition detection. */
|
|
54
|
+
prevLines?: string[]): SpecEvaluation;
|
|
@@ -10,5 +10,6 @@ export interface SpecLoadError {
|
|
|
10
10
|
sourcePath: string;
|
|
11
11
|
}
|
|
12
12
|
export declare function loadSpec(sourcePath: string): SpecLoadResult | SpecLoadError;
|
|
13
|
+
export declare function migrateV1toV3(raw: any): any;
|
|
13
14
|
/** Convenience: look up a provider's spec.json next to its provider dir. */
|
|
14
15
|
export declare function resolveSpecPath(providerDir: string): string;
|