@adhdev/daemon-core 0.9.82-rc.361 → 0.9.82-rc.363
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/cli-state-engine.d.ts +1 -1
- package/dist/cli-adapters/provider-cli-shared.d.ts +10 -0
- package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
- package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
- package/dist/commands/low-family/diagnostics.d.ts +2 -0
- package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
- package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
- package/dist/commands/low-family/notification.d.ts +2 -0
- package/dist/commands/low-family/status-meta.d.ts +2 -0
- package/dist/commands/low-family/types.d.ts +17 -0
- package/dist/index.js +2290 -2177
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2296 -2183
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-utils.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +2 -0
- package/package.json +2 -2
- package/src/cli-adapters/cli-state-engine.ts +7 -1
- package/src/cli-adapters/provider-cli-adapter.ts +1 -0
- package/src/cli-adapters/provider-cli-shared.ts +10 -0
- package/src/commands/low-family/coordinator-prompt.ts +72 -0
- package/src/commands/low-family/daemon-lifecycle.ts +107 -0
- package/src/commands/low-family/diagnostics.ts +57 -0
- package/src/commands/low-family/index.ts +14 -0
- package/src/commands/low-family/mesh-ledger.ts +62 -0
- package/src/commands/low-family/mesh-node-logs.ts +81 -0
- package/src/commands/low-family/notification.ts +116 -0
- package/src/commands/low-family/status-meta.ts +112 -0
- package/src/commands/low-family/types.ts +20 -0
- package/src/commands/router.ts +8 -522
- package/src/mesh/mesh-events-coordinator.ts +37 -0
- package/src/mesh/mesh-events-utils.ts +28 -2
- package/src/providers/cli-provider-instance.ts +46 -0
|
@@ -195,6 +195,23 @@ function readEventTimestampValue(value: unknown): number {
|
|
|
195
195
|
return 0;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
// A completion whose evidence is WEAK: the worker FSM reached idle but the turn's
|
|
199
|
+
// final assistant message was never confirmed (missing_final_assistant / a
|
|
200
|
+
// finalAssistantPresent=false diagnostic), or the event self-declares insufficient/weak
|
|
201
|
+
// evidence. cli-provider-instance emits this on the CANON-C decoupled-immediate path and
|
|
202
|
+
// on a forced finalization timeout, and the new structural approval-resolution gate
|
|
203
|
+
// (FALSEIDLE-a) can also let an unconfirmed approval→idle through. Such a completion is NOT
|
|
204
|
+
// trustworthy terminal evidence — surface a verify hint so the coordinator confirms via
|
|
205
|
+
// mesh_read_chat / git status before declaring the task done. Mirrors
|
|
206
|
+
// isWeakCompletionMetadata in mesh-events-pending.ts.
|
|
207
|
+
export function isWeakCompletionMetadata(metadataEvent: Record<string, unknown>): boolean {
|
|
208
|
+
const evidenceLevel = readNonEmptyString(metadataEvent.evidenceLevel);
|
|
209
|
+
if (evidenceLevel === 'insufficient' || evidenceLevel === 'weak') return true;
|
|
210
|
+
if (metadataEvent.reviewRecommended === true) return true;
|
|
211
|
+
const diag = readRecord(metadataEvent.completionDiagnostic);
|
|
212
|
+
return diag?.finalAssistantPresent === false || diag?.blockReason === 'missing_final_assistant';
|
|
213
|
+
}
|
|
214
|
+
|
|
198
215
|
function formatCompletionMetadata(event: Record<string, unknown>): string {
|
|
199
216
|
const completionDiagnostic = event.completionDiagnostic && typeof event.completionDiagnostic === 'object'
|
|
200
217
|
? event.completionDiagnostic as Record<string, unknown>
|
|
@@ -229,6 +246,13 @@ export function buildMeshSystemMessage(args: {
|
|
|
229
246
|
return `[System] ${args.nodeLabel} already has completion evidence${metadata}. The no-progress monitor reconciled the terminal handoff and marked the session complete; wait for the queued completion event/status refresh before doing any manual transcript check.`;
|
|
230
247
|
}
|
|
231
248
|
const reviewRecommended = args.metadataEvent.reviewRecommended === true;
|
|
249
|
+
// FALSEIDLE-b: a weak completion (missing final assistant / finalAssistantPresent=false /
|
|
250
|
+
// insufficient evidence) is not trustworthy terminal evidence even when reviewRecommended
|
|
251
|
+
// is not set. Append an explicit verify hint so the coordinator does not declare the task
|
|
252
|
+
// done off a false idle. Only the weak case is affected — a genuine completion (final
|
|
253
|
+
// assistant confirmed, no weak diagnostic) carries no extra note and is unchanged.
|
|
254
|
+
const weakCompletion = isWeakCompletionMetadata(args.metadataEvent);
|
|
255
|
+
const verifyTextNote = ' Completion evidence is weak — verify via mesh_read_chat or git status before declaring the task done; the worker may still be parked on an approval/modal.';
|
|
232
256
|
// Auto-surface the worker's final summary directly into the coordinator chat so it
|
|
233
257
|
// does not have to call mesh_read_chat just to see the result. The summary IS the
|
|
234
258
|
// worker's final assistant message; embedding it here replaces the previous
|
|
@@ -244,12 +268,14 @@ export function buildMeshSystemMessage(args: {
|
|
|
244
268
|
: completionSummary;
|
|
245
269
|
const verifyNote = reviewRecommended
|
|
246
270
|
? ' Completion evidence is insufficient — verify via git status or provider_session_id before assuming the task is done.'
|
|
247
|
-
: '';
|
|
271
|
+
: (weakCompletion ? verifyTextNote : '');
|
|
248
272
|
return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. Its final summary is included below — read it directly and only call mesh_read_chat if you need the full transcript.${verifyNote}\n\n--- ${args.nodeLabel} final summary ---\n${surfaced}`;
|
|
249
273
|
}
|
|
250
274
|
const reviewNote = reviewRecommended
|
|
251
275
|
? ' Completion evidence is insufficient — verify via git status or provider_session_id before assuming the task is done. Use mesh_read_chat once if needed, but do not poll repeatedly.'
|
|
252
|
-
:
|
|
276
|
+
: (weakCompletion
|
|
277
|
+
? `${verifyTextNote} Use mesh_read_chat once if needed, but do not poll repeatedly.`
|
|
278
|
+
: ' Use mesh_read_chat once to review its final progress, but do not poll repeatedly.');
|
|
253
279
|
return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path;${reviewNote}`;
|
|
254
280
|
}
|
|
255
281
|
if (args.event === 'agent:waiting_approval') {
|
|
@@ -1401,6 +1401,12 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1401
1401
|
}
|
|
1402
1402
|
}
|
|
1403
1403
|
|
|
1404
|
+
// (FALSEIDLE-a) Structural approval-resolution gate. Runs BEFORE the brittle
|
|
1405
|
+
// screen-text heuristic below so it also catches modals whose text does not match
|
|
1406
|
+
// looksLikeActiveApprovalPromptText (e.g. claude-cli's cd / "untrusted hooks" prompt).
|
|
1407
|
+
const approvalResolutionBlock = this.approvalResolutionFinalizationBlock(pending);
|
|
1408
|
+
if (approvalResolutionBlock) return approvalResolutionBlock;
|
|
1409
|
+
|
|
1404
1410
|
// Guard: if the screen still shows an approval/choice prompt as the last visible text,
|
|
1405
1411
|
// the turn is not complete even if the parsed status says idle and there is an assistant
|
|
1406
1412
|
// message. This catches the case where waiting_approval→idle transitions occur before
|
|
@@ -1420,6 +1426,46 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1420
1426
|
return null;
|
|
1421
1427
|
}
|
|
1422
1428
|
|
|
1429
|
+
// (FALSEIDLE-a) Positive, structural proof that the latest approval entry was resolved
|
|
1430
|
+
// through ADHDev. resolveModal() — driven by auto-approve, dashboard/mesh_approve, and
|
|
1431
|
+
// dev-cli-debug alike — advances the engine's lastResolvedEntrySeq to the current
|
|
1432
|
+
// approvalEntrySeq. So `lastResolvedEntrySeq >= approvalEntrySeq` (with a real entry,
|
|
1433
|
+
// approvalEntrySeq > 0) means the modal we last saw was actually answered. Absence of this
|
|
1434
|
+
// evidence after a waiting_approval→idle transition means the idle is suspect: the spec's
|
|
1435
|
+
// text-based approval→idle rule false-tripped while the modal is still unresolved.
|
|
1436
|
+
// Fails OPEN (returns true) when the seq fields are unavailable, so the gate can never wedge
|
|
1437
|
+
// a session on a provider/adapter that does not surface the counters.
|
|
1438
|
+
private hasApprovalResolutionEvidence(): boolean {
|
|
1439
|
+
try {
|
|
1440
|
+
const status = this.adapter.getStatus({ allowParse: false }) as any;
|
|
1441
|
+
const entrySeq = typeof status?.approvalEntrySeq === 'number' ? status.approvalEntrySeq : 0;
|
|
1442
|
+
if (entrySeq <= 0) return true;
|
|
1443
|
+
const resolvedSeq = typeof status?.lastResolvedEntrySeq === 'number' ? status.lastResolvedEntrySeq : undefined;
|
|
1444
|
+
if (resolvedSeq === undefined) return true;
|
|
1445
|
+
return resolvedSeq >= entrySeq;
|
|
1446
|
+
} catch {
|
|
1447
|
+
return true;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// (FALSEIDLE-a) Hold a completion that is the anomalous DIRECT waiting_approval→idle
|
|
1452
|
+
// transition with no positive resolution evidence. A genuinely resolved approval routes
|
|
1453
|
+
// through resolveModal → setStatus('generating'), so its completion's previousStatus is
|
|
1454
|
+
// 'generating' (not 'waiting_approval') and this gate never fires for it. Scoped to
|
|
1455
|
+
// delegated mesh/coordinator sessions — whose only modal-resolution path is auto-approve /
|
|
1456
|
+
// mesh_approve (both advance lastResolvedEntrySeq) — so an interactive local session, where
|
|
1457
|
+
// a human may answer the PTY prompt directly and leave no resolveModal record, is untouched.
|
|
1458
|
+
// Non-terminal: the hold is bounded by COMPLETED_FINALIZATION_MAX_WAIT_MS (30s), giving a
|
|
1459
|
+
// settling auto-approve time to fire and advance the seq, and guaranteeing no permanent wedge
|
|
1460
|
+
// if resolution ever happens via a path that does not record evidence.
|
|
1461
|
+
private approvalResolutionFinalizationBlock(pending: CompletedDebouncePending): CompletedFinalizationBlock | null {
|
|
1462
|
+
if (pending.previousStatus !== 'waiting_approval') return null;
|
|
1463
|
+
const meshContext = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
|
|
1464
|
+
if (!meshContext) return null;
|
|
1465
|
+
if (this.hasApprovalResolutionEvidence()) return null;
|
|
1466
|
+
return { reason: 'approval_resolution_unconfirmed', terminal: false };
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1423
1469
|
private scheduleCompletedDebounceFlush(delayMs: number): void {
|
|
1424
1470
|
if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
|
|
1425
1471
|
this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
|