@adhdev/daemon-core 0.9.82-rc.400 → 0.9.82-rc.401
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-adapter-types.d.ts +2 -1
- package/dist/cli-adapters/cli-state-engine.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +3 -1
- package/dist/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/dist/git/git-worktree.d.ts +49 -1
- package/dist/git/index.d.ts +1 -1
- package/dist/index.js +190 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +190 -28
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +10 -0
- package/package.json +2 -2
- package/src/cli-adapter-types.d.ts +2 -1
- package/src/cli-adapter-types.ts +2 -2
- package/src/cli-adapters/cli-state-engine.ts +15 -0
- package/src/cli-adapters/provider-cli-adapter.ts +32 -11
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +6 -0
- package/src/commands/cli-manager.ts +16 -2
- package/src/commands/med-family/mesh-crud.ts +9 -0
- package/src/git/git-worktree.ts +185 -3
- package/src/git/index.ts +1 -0
- package/src/mesh/mesh-event-forwarding.ts +13 -2
- package/src/mesh/mesh-queue-assignment.ts +12 -0
- package/src/mesh/mesh-reconcile-loop.ts +4 -0
- package/src/mesh/mesh-runtime-store.ts +20 -2
- package/src/providers/cli-provider-instance.ts +52 -8
package/dist/index.mjs
CHANGED
|
@@ -394,10 +394,10 @@ function readInjected(value) {
|
|
|
394
394
|
}
|
|
395
395
|
function getDaemonBuildInfo() {
|
|
396
396
|
if (cached) return cached;
|
|
397
|
-
const commit = readInjected(true ? "
|
|
398
|
-
const commitShort = readInjected(true ? "
|
|
399
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
400
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
397
|
+
const commit = readInjected(true ? "c31eb449e8febc28e378bd25394830a96a67594e" : void 0) ?? "unknown";
|
|
398
|
+
const commitShort = readInjected(true ? "c31eb449" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
399
|
+
const version = readInjected(true ? "0.9.82-rc.401" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
400
|
+
const builtAt = readInjected(true ? "2026-06-27T16:14:32.200Z" : void 0);
|
|
401
401
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
402
402
|
return cached;
|
|
403
403
|
}
|
|
@@ -1441,16 +1441,103 @@ function resolveWorktreePath(repoRoot, meshName, branch) {
|
|
|
1441
1441
|
const parentDir = path4.dirname(repoRoot);
|
|
1442
1442
|
return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
|
|
1443
1443
|
}
|
|
1444
|
+
async function tryGit(cwd, args) {
|
|
1445
|
+
try {
|
|
1446
|
+
const { stdout, stderr } = await execFileAsync2("git", args, {
|
|
1447
|
+
cwd,
|
|
1448
|
+
encoding: "utf8",
|
|
1449
|
+
timeout: GIT_TIMEOUT_MS,
|
|
1450
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
1451
|
+
windowsHide: true
|
|
1452
|
+
});
|
|
1453
|
+
return { ok: true, stdout: (stdout || "").trim(), stderr: (stderr || "").trim() };
|
|
1454
|
+
} catch (error) {
|
|
1455
|
+
return {
|
|
1456
|
+
ok: false,
|
|
1457
|
+
stdout: typeof error?.stdout === "string" ? error.stdout.trim() : "",
|
|
1458
|
+
stderr: typeof error?.stderr === "string" ? error.stderr.trim() : error?.message || ""
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
async function resolveWorktreeBaseStartPoint(repoRoot, baseBranch, remote) {
|
|
1463
|
+
const fetchResult = await tryGit(repoRoot, ["fetch", remote, baseBranch]);
|
|
1464
|
+
const fetched = fetchResult.ok;
|
|
1465
|
+
const localRev = await tryGit(repoRoot, ["rev-parse", "--verify", "--quiet", `refs/heads/${baseBranch}`]);
|
|
1466
|
+
const remoteRev = await tryGit(repoRoot, ["rev-parse", "--verify", "--quiet", `refs/remotes/${remote}/${baseBranch}`]);
|
|
1467
|
+
const localSha = localRev.ok && localRev.stdout ? localRev.stdout : void 0;
|
|
1468
|
+
const remoteSha = remoteRev.ok && remoteRev.stdout ? remoteRev.stdout : void 0;
|
|
1469
|
+
const remoteRef = `${remote}/${baseBranch}`;
|
|
1470
|
+
const base = {
|
|
1471
|
+
branch: baseBranch,
|
|
1472
|
+
remote,
|
|
1473
|
+
startRef: baseBranch,
|
|
1474
|
+
fetched,
|
|
1475
|
+
localSha,
|
|
1476
|
+
remoteSha,
|
|
1477
|
+
behindBy: 0,
|
|
1478
|
+
aheadBy: 0,
|
|
1479
|
+
action: "up_to_date"
|
|
1480
|
+
};
|
|
1481
|
+
const fetchWarn = fetched ? "" : ` (warning: git fetch ${remote} ${baseBranch} failed: ${fetchResult.stderr || "unknown error"})`;
|
|
1482
|
+
if (!remoteSha) {
|
|
1483
|
+
return {
|
|
1484
|
+
...base,
|
|
1485
|
+
action: "no_remote_ref_used_local",
|
|
1486
|
+
...fetched ? {} : { warning: `Could not fetch ${remoteRef}${fetchWarn}; worktree branched from local ${baseBranch}.` }
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
if (!localSha) {
|
|
1490
|
+
return {
|
|
1491
|
+
...base,
|
|
1492
|
+
startRef: remoteRef,
|
|
1493
|
+
action: "no_local_ref_used_remote"
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
if (localSha === remoteSha) {
|
|
1497
|
+
return base;
|
|
1498
|
+
}
|
|
1499
|
+
const localIsAncestor = (await tryGit(repoRoot, ["merge-base", "--is-ancestor", localSha, remoteSha])).ok;
|
|
1500
|
+
const remoteIsAncestor = (await tryGit(repoRoot, ["merge-base", "--is-ancestor", remoteSha, localSha])).ok;
|
|
1501
|
+
const behindBy = Number((await tryGit(repoRoot, ["rev-list", "--count", `${localSha}..${remoteSha}`])).stdout) || 0;
|
|
1502
|
+
const aheadBy = Number((await tryGit(repoRoot, ["rev-list", "--count", `${remoteSha}..${localSha}`])).stdout) || 0;
|
|
1503
|
+
if (localIsAncestor && !remoteIsAncestor) {
|
|
1504
|
+
return {
|
|
1505
|
+
...base,
|
|
1506
|
+
startRef: remoteRef,
|
|
1507
|
+
behindBy,
|
|
1508
|
+
aheadBy,
|
|
1509
|
+
action: "local_behind_used_remote",
|
|
1510
|
+
warning: `Base node local ${baseBranch} was behind ${remoteRef} by ${behindBy} commit(s); worktree branched from ${remoteRef} (${remoteSha.slice(0, 8)}) instead of stale local ${localSha.slice(0, 8)}.${fetchWarn}`
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
if (remoteIsAncestor) {
|
|
1514
|
+
return { ...base, behindBy, aheadBy, action: "local_ahead_used_local" };
|
|
1515
|
+
}
|
|
1516
|
+
return {
|
|
1517
|
+
...base,
|
|
1518
|
+
behindBy,
|
|
1519
|
+
aheadBy,
|
|
1520
|
+
action: "diverged_used_local",
|
|
1521
|
+
warning: `Base node local ${baseBranch} (${localSha.slice(0, 8)}) has DIVERGED from ${remoteRef} (${remoteSha.slice(0, 8)}): behind ${behindBy}, ahead ${aheadBy}. Worktree branched from local; a rebase onto ${remoteRef} will be required before its push can fast-forward.${fetchWarn}`
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1444
1524
|
async function createWorktree(opts) {
|
|
1445
1525
|
const { repoRoot, branch, baseBranch, meshName } = opts;
|
|
1526
|
+
const remote = (opts.remote || "origin").trim() || "origin";
|
|
1446
1527
|
const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
|
|
1447
1528
|
if (existsSync2(targetDir)) {
|
|
1448
1529
|
throw new Error(`Worktree target directory already exists: ${targetDir}`);
|
|
1449
1530
|
}
|
|
1450
1531
|
await mkdir(path4.dirname(targetDir), { recursive: true });
|
|
1532
|
+
let baseSync;
|
|
1533
|
+
let startRef = baseBranch;
|
|
1534
|
+
if (baseBranch && opts.syncBaseFromRemote !== false) {
|
|
1535
|
+
baseSync = await resolveWorktreeBaseStartPoint(repoRoot, baseBranch, remote);
|
|
1536
|
+
startRef = baseSync.startRef;
|
|
1537
|
+
}
|
|
1451
1538
|
const args = ["worktree", "add", targetDir, "-b", branch];
|
|
1452
|
-
if (
|
|
1453
|
-
args.push(
|
|
1539
|
+
if (startRef) {
|
|
1540
|
+
args.push(startRef);
|
|
1454
1541
|
}
|
|
1455
1542
|
try {
|
|
1456
1543
|
await execFileAsync2("git", args, {
|
|
@@ -1473,7 +1560,8 @@ async function createWorktree(opts) {
|
|
|
1473
1560
|
return {
|
|
1474
1561
|
success: true,
|
|
1475
1562
|
worktreePath: targetDir,
|
|
1476
|
-
branch
|
|
1563
|
+
branch,
|
|
1564
|
+
...baseSync ? { baseSync } : {}
|
|
1477
1565
|
};
|
|
1478
1566
|
}
|
|
1479
1567
|
async function removeWorktree(repoRoot, worktreePath, opts = {}) {
|
|
@@ -5647,11 +5735,14 @@ var init_mesh_runtime_store = __esm({
|
|
|
5647
5735
|
}
|
|
5648
5736
|
/** A node may only execute one write task at a time (worktree isolation). */
|
|
5649
5737
|
hasActiveNodeAssignment(meshId, nodeId) {
|
|
5738
|
+
const nodeIdForms = expandDaemonIdForms(nodeId);
|
|
5739
|
+
if (nodeIdForms.length === 0) return false;
|
|
5740
|
+
const placeholders = nodeIdForms.map(() => "?").join(", ");
|
|
5650
5741
|
const row = this.db.prepare(`
|
|
5651
5742
|
SELECT 1 FROM mesh_queue
|
|
5652
|
-
WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id
|
|
5743
|
+
WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id IN (${placeholders})
|
|
5653
5744
|
LIMIT 1
|
|
5654
|
-
`).get(meshId,
|
|
5745
|
+
`).get(meshId, ...nodeIdForms);
|
|
5655
5746
|
return row !== void 0;
|
|
5656
5747
|
}
|
|
5657
5748
|
/**
|
|
@@ -11870,7 +11961,14 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
11870
11961
|
targetSessionId: sessionId,
|
|
11871
11962
|
cliType: providerType,
|
|
11872
11963
|
action: "send_chat",
|
|
11873
|
-
message: task.message
|
|
11964
|
+
message: task.message,
|
|
11965
|
+
meshContext: {
|
|
11966
|
+
meshId,
|
|
11967
|
+
nodeId,
|
|
11968
|
+
taskId: task.id,
|
|
11969
|
+
...readNonEmptyString2(loadConfig().machineId) ? { coordinatorDaemonId: readNonEmptyString2(loadConfig().machineId) } : {},
|
|
11970
|
+
...readNonEmptyString2(task.sourceCoordinatorSessionId) ? { coordinatorSessionId: readNonEmptyString2(task.sourceCoordinatorSessionId) } : {}
|
|
11971
|
+
}
|
|
11874
11972
|
}),
|
|
11875
11973
|
{
|
|
11876
11974
|
meshId,
|
|
@@ -19538,6 +19636,15 @@ var init_cli_state_engine = __esm({
|
|
|
19538
19636
|
currentStatus = "starting";
|
|
19539
19637
|
isWaitingForResponse = false;
|
|
19540
19638
|
currentTurnScope = null;
|
|
19639
|
+
// ARCH-REFACTOR R1 (per-turn task identity): the mesh taskId bound to the most
|
|
19640
|
+
// recently STARTED turn. Unlike currentTurnScope (nulled the moment the turn
|
|
19641
|
+
// settles, before the completion event is even built), this persists past
|
|
19642
|
+
// completion and is only overwritten when the NEXT turn starts. That window is
|
|
19643
|
+
// exactly what the completion path needs: when a turn settles to idle, this still
|
|
19644
|
+
// holds THAT turn's taskId (the next task's turn cannot have started yet — it is
|
|
19645
|
+
// queued in pendingOutbound and only flushed asynchronously after idle), so the
|
|
19646
|
+
// completion event carries the correct id instead of the racy session scalar.
|
|
19647
|
+
currentTurnTaskId = null;
|
|
19541
19648
|
activeModal = null;
|
|
19542
19649
|
// ── Approval ─────────────────────────────────────
|
|
19543
19650
|
lastApprovalResolvedAt = 0;
|
|
@@ -19647,6 +19754,7 @@ var init_cli_state_engine = __esm({
|
|
|
19647
19754
|
this.finishRetryCount = 0;
|
|
19648
19755
|
this.clearIdleFinishCandidate("send_message");
|
|
19649
19756
|
this.currentTurnScope = turnScope;
|
|
19757
|
+
this.currentTurnTaskId = typeof turnScope.taskId === "string" && turnScope.taskId.trim() ? turnScope.taskId : null;
|
|
19650
19758
|
this.responseEpoch += 1;
|
|
19651
19759
|
}
|
|
19652
19760
|
/** Called when PTY exits */
|
|
@@ -21598,15 +21706,18 @@ ${lastSnapshot}`;
|
|
|
21598
21706
|
}
|
|
21599
21707
|
async sendMessage(text, options = {}) {
|
|
21600
21708
|
if (options.force === true) {
|
|
21601
|
-
await this.forceSendMessage(text);
|
|
21709
|
+
await this.forceSendMessage(text, options.meshTaskId);
|
|
21602
21710
|
return;
|
|
21603
21711
|
}
|
|
21604
|
-
await this.sendMessageNow(text, true);
|
|
21712
|
+
await this.sendMessageNow(text, true, options.meshTaskId);
|
|
21605
21713
|
}
|
|
21606
|
-
async forceSendMessage(text) {
|
|
21714
|
+
async forceSendMessage(text, meshTaskId) {
|
|
21607
21715
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
21608
21716
|
const content = String(text || "");
|
|
21609
21717
|
if (!content.trim()) return;
|
|
21718
|
+
if (typeof meshTaskId === "string" && meshTaskId.trim()) {
|
|
21719
|
+
this.engine.currentTurnTaskId = meshTaskId;
|
|
21720
|
+
}
|
|
21610
21721
|
if (this.engine.currentStatus === "waiting_approval" || this.engine.hasActionableApproval()) {
|
|
21611
21722
|
LOG.info("CLI", `[${this.cliType}] force-send held \u2014 session parked on approval modal (status=${this.engine.currentStatus})`);
|
|
21612
21723
|
return;
|
|
@@ -21619,7 +21730,7 @@ ${lastSnapshot}`;
|
|
|
21619
21730
|
async waitForForceSubmitSettle() {
|
|
21620
21731
|
await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_SETTLE_MS));
|
|
21621
21732
|
}
|
|
21622
|
-
enqueuePendingOutboundMessage(text, reason) {
|
|
21733
|
+
enqueuePendingOutboundMessage(text, reason, meshTaskId) {
|
|
21623
21734
|
const content = String(text || "");
|
|
21624
21735
|
const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
|
|
21625
21736
|
if (duplicate) {
|
|
@@ -21631,7 +21742,8 @@ ${lastSnapshot}`;
|
|
|
21631
21742
|
role: "user",
|
|
21632
21743
|
content,
|
|
21633
21744
|
queuedAt,
|
|
21634
|
-
source: "sendMessage"
|
|
21745
|
+
source: "sendMessage",
|
|
21746
|
+
...typeof meshTaskId === "string" && meshTaskId.trim() ? { meshTaskId } : {}
|
|
21635
21747
|
};
|
|
21636
21748
|
this.pendingOutboundQueue.push(message);
|
|
21637
21749
|
LOG.info("CLI", `[${this.cliType}] queued outbound message while busy (${reason}); queue=${this.pendingOutboundQueue.length}`);
|
|
@@ -21674,7 +21786,7 @@ ${lastSnapshot}`;
|
|
|
21674
21786
|
if (this.engine.currentStatus !== "idle" || this.engine.isWaitingForResponse || this.engine.hasActionableApproval()) break;
|
|
21675
21787
|
const next = this.pendingOutboundQueue[0];
|
|
21676
21788
|
try {
|
|
21677
|
-
await this.sendMessageNow(next.content, false);
|
|
21789
|
+
await this.sendMessageNow(next.content, false, next.meshTaskId);
|
|
21678
21790
|
this.pendingOutboundQueue.shift();
|
|
21679
21791
|
this.onStatusChange?.();
|
|
21680
21792
|
} catch (error) {
|
|
@@ -21687,7 +21799,7 @@ ${lastSnapshot}`;
|
|
|
21687
21799
|
this.pendingOutboundFlushInFlight = false;
|
|
21688
21800
|
}
|
|
21689
21801
|
}
|
|
21690
|
-
async sendMessageNow(text, allowQueue) {
|
|
21802
|
+
async sendMessageNow(text, allowQueue, meshTaskId) {
|
|
21691
21803
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
21692
21804
|
const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
|
|
21693
21805
|
const allowInterventionPrompt = allowInputDuringGeneration && this.engine.isWaitingForResponse && !this.engine.hasActionableApproval();
|
|
@@ -21707,7 +21819,7 @@ ${lastSnapshot}`;
|
|
|
21707
21819
|
})() : null;
|
|
21708
21820
|
const queueReason = this.shouldQueuePendingOutboundMessage(parsedStatusBeforeSend);
|
|
21709
21821
|
if (allowQueue && queueReason) {
|
|
21710
|
-
this.enqueuePendingOutboundMessage(text, queueReason);
|
|
21822
|
+
this.enqueuePendingOutboundMessage(text, queueReason, meshTaskId);
|
|
21711
21823
|
return;
|
|
21712
21824
|
}
|
|
21713
21825
|
if (!allowInterventionPrompt) {
|
|
@@ -21724,7 +21836,7 @@ ${lastSnapshot}`;
|
|
|
21724
21836
|
}
|
|
21725
21837
|
if (!this.ready) {
|
|
21726
21838
|
if (allowQueue) {
|
|
21727
|
-
this.enqueuePendingOutboundMessage(text, "not_ready_pending_prompt");
|
|
21839
|
+
this.enqueuePendingOutboundMessage(text, "not_ready_pending_prompt", meshTaskId);
|
|
21728
21840
|
return;
|
|
21729
21841
|
}
|
|
21730
21842
|
throw new Error(`${this.cliName} not ready (status: ${this.engine.currentStatus})`);
|
|
@@ -21738,7 +21850,7 @@ ${lastSnapshot}`;
|
|
|
21738
21850
|
const terminalLooksIdle = this.engine.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.engine.isWaitingForResponse && !this.engine.currentTurnScope && !this.engine.hasActionableApproval() && !parsedHasActionableModal;
|
|
21739
21851
|
if (!terminalLooksIdle) {
|
|
21740
21852
|
if (allowQueue) {
|
|
21741
|
-
this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}
|
|
21853
|
+
this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}`, meshTaskId);
|
|
21742
21854
|
return;
|
|
21743
21855
|
}
|
|
21744
21856
|
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
@@ -21748,7 +21860,7 @@ ${lastSnapshot}`;
|
|
|
21748
21860
|
const snap = this.getSnapshot();
|
|
21749
21861
|
if (!this.engine.clearStaleIdleResponseGuard("send_message_guard", snap) && !this.engine.clearParsedIdleResponseGuard("send_message_parsed_idle_guard", parsedStatusBeforeSend, snap)) {
|
|
21750
21862
|
if (allowQueue) {
|
|
21751
|
-
this.enqueuePendingOutboundMessage(text, "waiting_for_response");
|
|
21863
|
+
this.enqueuePendingOutboundMessage(text, "waiting_for_response", meshTaskId);
|
|
21752
21864
|
return;
|
|
21753
21865
|
}
|
|
21754
21866
|
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
@@ -21759,7 +21871,11 @@ ${lastSnapshot}`;
|
|
|
21759
21871
|
prompt: text,
|
|
21760
21872
|
startedAt: Date.now(),
|
|
21761
21873
|
bufferStart: this.accumulatedBuffer.length,
|
|
21762
|
-
rawBufferStart: this.accumulatedRawBuffer.length
|
|
21874
|
+
rawBufferStart: this.accumulatedRawBuffer.length,
|
|
21875
|
+
// ARCH-REFACTOR R1: bind this turn to its mesh task. engine.onTurnStarted
|
|
21876
|
+
// copies this into currentTurnTaskId so the turn's completion event carries
|
|
21877
|
+
// the right id even if a later task overwrites the session scalar meanwhile.
|
|
21878
|
+
...typeof meshTaskId === "string" && meshTaskId.trim() ? { taskId: meshTaskId } : {}
|
|
21763
21879
|
};
|
|
21764
21880
|
LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${turnScope.bufferStart} raw=${turnScope.rawBufferStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
|
|
21765
21881
|
if (this.submitRetryTimer) {
|
|
@@ -22109,6 +22225,13 @@ ${lastSnapshot}`;
|
|
|
22109
22225
|
set currentTurnScope(v) {
|
|
22110
22226
|
this.engine.currentTurnScope = v;
|
|
22111
22227
|
}
|
|
22228
|
+
// ARCH-REFACTOR R1: the mesh taskId bound to the most recently started turn,
|
|
22229
|
+
// surviving past turn settle until the next turn starts. The provider instance
|
|
22230
|
+
// reads this when stamping completion events so they carry the completing turn's
|
|
22231
|
+
// task rather than the racy last-write-wins session scalar.
|
|
22232
|
+
get currentTurnTaskId() {
|
|
22233
|
+
return this.engine.currentTurnTaskId;
|
|
22234
|
+
}
|
|
22112
22235
|
get responseEpoch() {
|
|
22113
22236
|
return this.engine.responseEpoch;
|
|
22114
22237
|
}
|
|
@@ -40324,11 +40447,28 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40324
40447
|
isMeshWorkerSession() {
|
|
40325
40448
|
return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
|
|
40326
40449
|
}
|
|
40450
|
+
/**
|
|
40451
|
+
* ARCH-REFACTOR R1: the taskId to attribute the CURRENTLY-completing turn to.
|
|
40452
|
+
* Prefers the per-turn binding (engine.currentTurnTaskId, set when the turn was
|
|
40453
|
+
* submitted and surviving until the next turn starts) over the last-write-wins
|
|
40454
|
+
* session scalar (settings.meshActiveTaskId). The scalar is retained only as a
|
|
40455
|
+
* backward-compat alias for the "current/last assignment" and is the source of the
|
|
40456
|
+
* NOTIF-MISDELIVER / TASK-MSG-MISROUTE race: a second task attaching before this
|
|
40457
|
+
* turn completes overwrites it. Returns undefined for a non-task ad-hoc turn.
|
|
40458
|
+
*/
|
|
40459
|
+
completingTurnTaskId() {
|
|
40460
|
+
const turnTaskId = this.adapter?.currentTurnTaskId;
|
|
40461
|
+
if (typeof turnTaskId === "string" && turnTaskId.trim()) return turnTaskId;
|
|
40462
|
+
const scalar = this.settings.meshActiveTaskId;
|
|
40463
|
+
return typeof scalar === "string" && scalar.trim() ? scalar : void 0;
|
|
40464
|
+
}
|
|
40327
40465
|
// EVTTRACE correlation context for this session's completion lifecycle. taskId is
|
|
40328
40466
|
// the primary grep anchor; instanceId is the session fallback.
|
|
40329
40467
|
meshTraceCtx(event = "agent:generating_completed") {
|
|
40330
40468
|
return {
|
|
40331
|
-
|
|
40469
|
+
// ARCH-REFACTOR R1: trace the per-turn taskId (falling back to the scalar) so
|
|
40470
|
+
// EvtTrace anchors on the same id the completion event actually carries.
|
|
40471
|
+
taskId: this.completingTurnTaskId(),
|
|
40332
40472
|
sessionId: this.instanceId,
|
|
40333
40473
|
nodeId: this.settings.meshNodeId,
|
|
40334
40474
|
meshId: this.settings.meshNodeFor,
|
|
@@ -40387,6 +40527,8 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40387
40527
|
chatTitle: pending.chatTitle,
|
|
40388
40528
|
duration: pending.duration,
|
|
40389
40529
|
timestamp: pending.timestamp,
|
|
40530
|
+
// ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
|
|
40531
|
+
...pending.taskId ? { taskId: pending.taskId } : {},
|
|
40390
40532
|
// When finalization is forced past the timeout on a `parsed_status:` block
|
|
40391
40533
|
// (the parser never confirmed a final assistant turn) we previously rode an
|
|
40392
40534
|
// empty `finalSummary` unconditionally. That empty value propagates to the
|
|
@@ -40412,6 +40554,8 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40412
40554
|
chatTitle: pending.chatTitle,
|
|
40413
40555
|
duration: pending.duration,
|
|
40414
40556
|
timestamp: pending.timestamp,
|
|
40557
|
+
// ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
|
|
40558
|
+
...pending.taskId ? { taskId: pending.taskId } : {},
|
|
40415
40559
|
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
|
|
40416
40560
|
});
|
|
40417
40561
|
this.completedDebouncePending = null;
|
|
@@ -40688,7 +40832,11 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40688
40832
|
duration,
|
|
40689
40833
|
timestamp: now,
|
|
40690
40834
|
firstObservedAt: now,
|
|
40691
|
-
previousStatus: this.lastStatus
|
|
40835
|
+
previousStatus: this.lastStatus,
|
|
40836
|
+
// ARCH-REFACTOR R1: snapshot the completing turn's taskId NOW (sync),
|
|
40837
|
+
// before any follow-up task's flush can start a new turn and move
|
|
40838
|
+
// engine.currentTurnTaskId.
|
|
40839
|
+
...this.completingTurnTaskId() ? { taskId: this.completingTurnTaskId() } : {}
|
|
40692
40840
|
};
|
|
40693
40841
|
const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
|
|
40694
40842
|
const meshWorkerSession = this.isMeshWorkerSession();
|
|
@@ -40791,10 +40939,11 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40791
40939
|
workspace: typeof event.workspace === "string" && event.workspace.trim() ? event.workspace : this.workingDir,
|
|
40792
40940
|
providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
|
|
40793
40941
|
};
|
|
40794
|
-
if (this.isMeshWorkerSession()
|
|
40942
|
+
if (this.isMeshWorkerSession()) {
|
|
40795
40943
|
const existingTaskId = typeof enrichedEvent.taskId === "string" && enrichedEvent.taskId.trim() ? enrichedEvent.taskId : void 0;
|
|
40796
40944
|
if (!existingTaskId) {
|
|
40797
|
-
|
|
40945
|
+
const resolved = this.completingTurnTaskId();
|
|
40946
|
+
if (resolved) enrichedEvent.taskId = resolved;
|
|
40798
40947
|
}
|
|
40799
40948
|
}
|
|
40800
40949
|
if (this.context?.emitProviderEvent) {
|
|
@@ -43679,11 +43828,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
43679
43828
|
}
|
|
43680
43829
|
const message = input.textFallback;
|
|
43681
43830
|
if (!message) throw new Error("message required for send_chat");
|
|
43831
|
+
const meshTaskId = meshContext && typeof meshContext === "object" && typeof meshContext.taskId === "string" && meshContext.taskId.trim() ? meshContext.taskId : void 0;
|
|
43682
43832
|
const forceSend = args?.force === true || args?.forceSend === true;
|
|
43683
43833
|
if (forceSend && typeof adapter.forceSendMessage === "function") {
|
|
43684
|
-
await adapter.forceSendMessage(message);
|
|
43834
|
+
if (meshTaskId) await adapter.forceSendMessage(message, meshTaskId);
|
|
43835
|
+
else await adapter.forceSendMessage(message);
|
|
43685
43836
|
} else if (forceSend) {
|
|
43686
|
-
await adapter.sendMessage(message, { force: true });
|
|
43837
|
+
await adapter.sendMessage(message, meshTaskId ? { force: true, meshTaskId } : { force: true });
|
|
43838
|
+
} else if (meshTaskId) {
|
|
43839
|
+
await adapter.sendMessage(message, { meshTaskId });
|
|
43687
43840
|
} else {
|
|
43688
43841
|
await adapter.sendMessage(message);
|
|
43689
43842
|
}
|
|
@@ -48211,6 +48364,11 @@ var meshCrudHandlers = {
|
|
|
48211
48364
|
baseBranch,
|
|
48212
48365
|
meshName: mesh.name
|
|
48213
48366
|
});
|
|
48367
|
+
if (result.baseSync?.warning) {
|
|
48368
|
+
console.warn(`[mesh] clone_mesh_node base sync (${result.baseSync.action}): ${result.baseSync.warning}`);
|
|
48369
|
+
} else if (result.baseSync && result.baseSync.action !== "up_to_date") {
|
|
48370
|
+
console.log(`[mesh] clone_mesh_node base sync: ${result.baseSync.action} (startRef=${result.baseSync.startRef})`);
|
|
48371
|
+
}
|
|
48214
48372
|
let node;
|
|
48215
48373
|
if (meshRecord.inline) {
|
|
48216
48374
|
const { randomUUID: randomUUID15 } = await import("crypto");
|
|
@@ -48401,6 +48559,8 @@ var meshCrudHandlers = {
|
|
|
48401
48559
|
node,
|
|
48402
48560
|
worktreePath: result.worktreePath,
|
|
48403
48561
|
branch: result.branch,
|
|
48562
|
+
...result.baseSync ? { baseSync: result.baseSync } : {},
|
|
48563
|
+
...result.baseSync?.warning ? { baseStaleWarning: result.baseSync.warning } : {},
|
|
48404
48564
|
worktreeBootstrap: runningBootstrapState,
|
|
48405
48565
|
worktreeSetup: {
|
|
48406
48566
|
status: "running",
|
|
@@ -48416,6 +48576,8 @@ var meshCrudHandlers = {
|
|
|
48416
48576
|
node,
|
|
48417
48577
|
worktreePath: result.worktreePath,
|
|
48418
48578
|
branch: result.branch,
|
|
48579
|
+
...result.baseSync ? { baseSync: result.baseSync } : {},
|
|
48580
|
+
...result.baseSync?.warning ? { baseStaleWarning: result.baseSync.warning } : {},
|
|
48419
48581
|
submodulesInitialized,
|
|
48420
48582
|
worktreeBootstrap: bootstrapState
|
|
48421
48583
|
};
|