@adhdev/daemon-core 0.9.82-rc.481 → 0.9.82-rc.483
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/config/mesh-config.d.ts +10 -28
- package/dist/index.d.ts +2 -2
- package/dist/index.js +337 -249
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +337 -244
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/contracts.d.ts +35 -9
- package/dist/mesh/mesh-reconcile-loop.d.ts +4 -0
- package/dist/mesh/mesh-runtime-store.d.ts +47 -2
- package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +4 -0
- package/dist/repo-mesh-types.d.ts +8 -14
- package/dist/types.d.ts +15 -6
- package/package.json +3 -3
- package/src/commands/chat-commands-read.ts +81 -60
- package/src/commands/low-family/coordinator-prompt.ts +53 -0
- package/src/commands/med-family/mesh-crud.ts +19 -62
- package/src/config/mesh-config.ts +21 -140
- package/src/index.ts +1 -2
- package/src/mesh/contracts.ts +59 -18
- package/src/mesh/coordinator-prompt.ts +22 -6
- package/src/mesh/mesh-event-forwarding.ts +38 -102
- package/src/mesh/mesh-events-pending.ts +20 -0
- package/src/mesh/mesh-reconcile-loop.ts +157 -2
- package/src/mesh/mesh-runtime-store.ts +118 -3
- package/src/mesh/mesh-unresolved-forward-outbox.ts +30 -0
- package/src/repo-mesh-types.ts +8 -14
- package/src/types.ts +21 -6
package/dist/index.js
CHANGED
|
@@ -188,7 +188,7 @@ var init_repo_mesh_types = __esm({
|
|
|
188
188
|
"checkpoint_then_continue"
|
|
189
189
|
]);
|
|
190
190
|
MESH_MAX_PARALLEL_TASKS_MIN = 1;
|
|
191
|
-
MESH_MAX_PARALLEL_TASKS_MAX =
|
|
191
|
+
MESH_MAX_PARALLEL_TASKS_MAX = 64;
|
|
192
192
|
DEFAULT_MESH_READONLY_MULTIPLIER = 2;
|
|
193
193
|
}
|
|
194
194
|
});
|
|
@@ -409,10 +409,10 @@ function readInjected(value) {
|
|
|
409
409
|
}
|
|
410
410
|
function getDaemonBuildInfo() {
|
|
411
411
|
if (cached) return cached;
|
|
412
|
-
const commit = readInjected(true ? "
|
|
413
|
-
const commitShort = readInjected(true ? "
|
|
414
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
415
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
412
|
+
const commit = readInjected(true ? "0862a3f10fa9de60a46591c0894a7209534db2e2" : void 0) ?? "unknown";
|
|
413
|
+
const commitShort = readInjected(true ? "0862a3f1" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
414
|
+
const version = readInjected(true ? "0.9.82-rc.483" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
415
|
+
const builtAt = readInjected(true ? "2026-07-08T04:27:00.139Z" : void 0);
|
|
416
416
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
417
417
|
return cached;
|
|
418
418
|
}
|
|
@@ -2819,8 +2819,6 @@ var init_dist = __esm({
|
|
|
2819
2819
|
"mesh_review_inbox",
|
|
2820
2820
|
"mesh_magi_review",
|
|
2821
2821
|
"mesh_magi_collect",
|
|
2822
|
-
"mesh_magi_panel_set",
|
|
2823
|
-
"mesh_magi_panel_list",
|
|
2824
2822
|
"mesh_magi_kind_panel_set",
|
|
2825
2823
|
"mesh_magi_kind_panel_list"
|
|
2826
2824
|
];
|
|
@@ -2920,24 +2918,19 @@ __export(mesh_config_exports, {
|
|
|
2920
2918
|
createMeshHostPairingToken: () => createMeshHostPairingToken,
|
|
2921
2919
|
deleteMesh: () => deleteMesh,
|
|
2922
2920
|
getMagiKindPanel: () => getMagiKindPanel,
|
|
2923
|
-
getMagiPanel: () => getMagiPanel,
|
|
2924
2921
|
getMesh: () => getMesh,
|
|
2925
2922
|
getMeshByRepo: () => getMeshByRepo,
|
|
2926
2923
|
listMagiKindPanels: () => listMagiKindPanels,
|
|
2927
|
-
listMagiPanels: () => listMagiPanels,
|
|
2928
2924
|
listMeshes: () => listMeshes,
|
|
2929
2925
|
markMeshHostPairingJoined: () => markMeshHostPairingJoined,
|
|
2930
|
-
normalizeMagiPanel: () => normalizeMagiPanel,
|
|
2931
2926
|
normalizeMagiSlots: () => normalizeMagiSlots,
|
|
2932
2927
|
normalizeRepoIdentity: () => normalizeRepoIdentity,
|
|
2933
2928
|
removeMagiKindPanel: () => removeMagiKindPanel,
|
|
2934
|
-
removeMagiPanel: () => removeMagiPanel,
|
|
2935
2929
|
removeNode: () => removeNode,
|
|
2936
2930
|
setMagiKindPanel: () => setMagiKindPanel,
|
|
2937
2931
|
tokenIdForManualPairing: () => tokenIdForManualPairing,
|
|
2938
2932
|
updateMesh: () => updateMesh,
|
|
2939
|
-
updateNode: () => updateNode
|
|
2940
|
-
upsertMagiPanel: () => upsertMagiPanel
|
|
2933
|
+
updateNode: () => updateNode
|
|
2941
2934
|
});
|
|
2942
2935
|
function getMeshConfigPath() {
|
|
2943
2936
|
return (0, import_path3.join)(getConfigDir(), "meshes.json");
|
|
@@ -3316,6 +3309,11 @@ function updateNode(meshId, nodeId, opts) {
|
|
|
3316
3309
|
node.reportedDaemonBuildVersion = opts.reportedDaemonBuildVersion.trim();
|
|
3317
3310
|
}
|
|
3318
3311
|
if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
|
|
3312
|
+
if (Object.prototype.hasOwnProperty.call(opts, "capabilities")) {
|
|
3313
|
+
const tags = normalizeCapabilityTags(opts.capabilities);
|
|
3314
|
+
if (tags && tags.length) node.capabilities = tags;
|
|
3315
|
+
else delete node.capabilities;
|
|
3316
|
+
}
|
|
3319
3317
|
if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
|
|
3320
3318
|
if (Object.prototype.hasOwnProperty.call(opts, "systemPrompt")) {
|
|
3321
3319
|
if (opts.systemPrompt && opts.systemPrompt.trim()) {
|
|
@@ -3333,99 +3331,6 @@ function normalizeReplicaCount(value) {
|
|
|
3333
3331
|
const n = Math.floor(value);
|
|
3334
3332
|
return n >= 1 ? n : void 0;
|
|
3335
3333
|
}
|
|
3336
|
-
function normalizeMagiPanelDefaultKind(raw) {
|
|
3337
|
-
if (raw == null) return void 0;
|
|
3338
|
-
const s2 = typeof raw === "string" ? raw.trim().toLowerCase() : "";
|
|
3339
|
-
if (s2 === "claim_audit" || s2 === "rca" || s2 === "design") return s2;
|
|
3340
|
-
if (s2 === "freeform") {
|
|
3341
|
-
console.warn(
|
|
3342
|
-
"[magi] panel defaultKind='freeform' rejected \u2014 freeform contributes no structured claims to cross-verification; dropping (use claim_audit / rca / design, or omit)."
|
|
3343
|
-
);
|
|
3344
|
-
return void 0;
|
|
3345
|
-
}
|
|
3346
|
-
return void 0;
|
|
3347
|
-
}
|
|
3348
|
-
function normalizeMagiPanel(config) {
|
|
3349
|
-
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
3350
|
-
throw new Error("invalid_magi_panel: config must be an object");
|
|
3351
|
-
}
|
|
3352
|
-
const raw = config;
|
|
3353
|
-
const rawMembers = raw.members;
|
|
3354
|
-
if (!Array.isArray(rawMembers) || rawMembers.length === 0) {
|
|
3355
|
-
throw new Error("invalid_magi_panel: members must be a non-empty array");
|
|
3356
|
-
}
|
|
3357
|
-
if (rawMembers.length > MAX_MAGI_PANEL_MEMBERS) {
|
|
3358
|
-
throw new Error(`invalid_magi_panel: too many members (max ${MAX_MAGI_PANEL_MEMBERS})`);
|
|
3359
|
-
}
|
|
3360
|
-
const members = rawMembers.map((entry, idx) => {
|
|
3361
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
3362
|
-
throw new Error(`invalid_magi_panel: member[${idx}] must be an object`);
|
|
3363
|
-
}
|
|
3364
|
-
const m = entry;
|
|
3365
|
-
const provider = typeof m.provider === "string" ? m.provider.trim() : "";
|
|
3366
|
-
if (!provider) {
|
|
3367
|
-
throw new Error(`invalid_magi_panel: member[${idx}].provider is required`);
|
|
3368
|
-
}
|
|
3369
|
-
const nodeId = typeof m.nodeId === "string" && m.nodeId.trim() ? m.nodeId.trim() : void 0;
|
|
3370
|
-
const model = typeof m.model === "string" && m.model.trim() ? m.model.trim() : void 0;
|
|
3371
|
-
const capabilityTags = normalizeCapabilityTags(m.capabilityTags);
|
|
3372
|
-
const n = normalizeReplicaCount(m.n);
|
|
3373
|
-
return {
|
|
3374
|
-
provider,
|
|
3375
|
-
...nodeId ? { nodeId } : {},
|
|
3376
|
-
...model ? { model } : {},
|
|
3377
|
-
...capabilityTags ? { capabilityTags } : {},
|
|
3378
|
-
...n !== void 0 ? { n } : {}
|
|
3379
|
-
};
|
|
3380
|
-
});
|
|
3381
|
-
const description = typeof raw.description === "string" && raw.description.trim() ? raw.description.trim().slice(0, 200) : void 0;
|
|
3382
|
-
const defaultN = normalizeReplicaCount(raw.defaultN);
|
|
3383
|
-
const defaultKind = normalizeMagiPanelDefaultKind(raw.defaultKind);
|
|
3384
|
-
return {
|
|
3385
|
-
...description ? { description } : {},
|
|
3386
|
-
members,
|
|
3387
|
-
...defaultN !== void 0 ? { defaultN } : {},
|
|
3388
|
-
...defaultKind !== void 0 ? { defaultKind } : {},
|
|
3389
|
-
// dedupExempt is always meaningful for a MAGI panel (intentional same-prompt
|
|
3390
|
-
// fan-out). Persist it true unless the caller explicitly disables it.
|
|
3391
|
-
dedupExempt: raw.dedupExempt === false ? false : true
|
|
3392
|
-
};
|
|
3393
|
-
}
|
|
3394
|
-
function normalizePanelName(name) {
|
|
3395
|
-
const trimmed = typeof name === "string" ? name.trim() : "";
|
|
3396
|
-
if (!trimmed) throw new Error("invalid_magi_panel: panel name is required");
|
|
3397
|
-
return trimmed.slice(0, 100);
|
|
3398
|
-
}
|
|
3399
|
-
function listMagiPanels() {
|
|
3400
|
-
return loadMeshConfig().magiPanels ?? {};
|
|
3401
|
-
}
|
|
3402
|
-
function getMagiPanel(name) {
|
|
3403
|
-
const key2 = typeof name === "string" ? name.trim() : "";
|
|
3404
|
-
if (!key2) return void 0;
|
|
3405
|
-
return loadMeshConfig().magiPanels?.[key2];
|
|
3406
|
-
}
|
|
3407
|
-
function upsertMagiPanel(name, config, opts = {}) {
|
|
3408
|
-
const key2 = normalizePanelName(name);
|
|
3409
|
-
const panel = normalizeMagiPanel(config);
|
|
3410
|
-
const stored = loadMeshConfig();
|
|
3411
|
-
const panels = stored.magiPanels ?? {};
|
|
3412
|
-
if (panels[key2] && opts.overwrite !== true) {
|
|
3413
|
-
throw new Error(`magi_panel_exists: panel '${key2}' already exists \u2014 pass overwrite=true to replace it`);
|
|
3414
|
-
}
|
|
3415
|
-
panels[key2] = panel;
|
|
3416
|
-
stored.magiPanels = panels;
|
|
3417
|
-
saveMeshConfig(stored);
|
|
3418
|
-
return panel;
|
|
3419
|
-
}
|
|
3420
|
-
function removeMagiPanel(name) {
|
|
3421
|
-
const key2 = typeof name === "string" ? name.trim() : "";
|
|
3422
|
-
if (!key2) return false;
|
|
3423
|
-
const stored = loadMeshConfig();
|
|
3424
|
-
if (!stored.magiPanels || !stored.magiPanels[key2]) return false;
|
|
3425
|
-
delete stored.magiPanels[key2];
|
|
3426
|
-
saveMeshConfig(stored);
|
|
3427
|
-
return true;
|
|
3428
|
-
}
|
|
3429
3334
|
function normalizeMagiTaskKindKey(raw) {
|
|
3430
3335
|
const s2 = typeof raw === "string" ? raw.trim().toLowerCase() : "";
|
|
3431
3336
|
if (!MAGI_KIND_PANEL_KINDS.includes(s2)) {
|
|
@@ -3497,7 +3402,7 @@ function removeMagiKindPanel(kind) {
|
|
|
3497
3402
|
saveMeshConfig(stored);
|
|
3498
3403
|
return true;
|
|
3499
3404
|
}
|
|
3500
|
-
var import_fs3, import_path3, import_crypto3, mergeMeshPolicy,
|
|
3405
|
+
var import_fs3, import_path3, import_crypto3, mergeMeshPolicy, MAGI_KIND_PANEL_KINDS, MAX_MAGI_KIND_SLOTS;
|
|
3501
3406
|
var init_mesh_config = __esm({
|
|
3502
3407
|
"src/config/mesh-config.ts"() {
|
|
3503
3408
|
"use strict";
|
|
@@ -3509,7 +3414,6 @@ var init_mesh_config = __esm({
|
|
|
3509
3414
|
init_repo_mesh_types();
|
|
3510
3415
|
init_mesh_host_ownership();
|
|
3511
3416
|
mergeMeshPolicy = mergeAndNormalizePolicy;
|
|
3512
|
-
MAX_MAGI_PANEL_MEMBERS = 24;
|
|
3513
3417
|
MAGI_KIND_PANEL_KINDS = ["claim_audit", "rca", "design", "freeform"];
|
|
3514
3418
|
MAX_MAGI_KIND_SLOTS = 24;
|
|
3515
3419
|
}
|
|
@@ -3702,6 +3606,21 @@ function buildNodeConfigSection(mesh) {
|
|
|
3702
3606
|
}).filter(Boolean) : [];
|
|
3703
3607
|
const providerRolesSuffix = providerRoles.length ? ` | caps: ${providerRoles.join(", ")}` : "";
|
|
3704
3608
|
lines.push(`- ${explicitLabel} nodeId: \`${n.id}\` | workspace: \`${n.workspace}\`${n.daemonId ? ` | daemon: \`${n.daemonId}\`` : ""}${providerPriority}${providerRolesSuffix}${suffix}`);
|
|
3609
|
+
const routingTags = [];
|
|
3610
|
+
const custom = Array.isArray(n.capabilities) ? n.capabilities : [];
|
|
3611
|
+
for (const t of custom) {
|
|
3612
|
+
const s2 = typeof t === "string" ? t.trim() : "";
|
|
3613
|
+
if (s2) routingTags.push(s2);
|
|
3614
|
+
}
|
|
3615
|
+
const tagOs = (n.userOverrides?.platform || n.reportedPlatform || "").toString().trim();
|
|
3616
|
+
const tagArch = (n.userOverrides?.arch || n.reportedArch || "").toString().trim();
|
|
3617
|
+
if (tagOs) routingTags.push(`os=${tagOs}`);
|
|
3618
|
+
if (tagArch) routingTags.push(`arch=${tagArch}`);
|
|
3619
|
+
const wtBranch = typeof n.worktreeBranch === "string" ? n.worktreeBranch.trim() : "";
|
|
3620
|
+
if (n.isLocalWorktree && wtBranch) routingTags.push(`worktree=${wtBranch}`);
|
|
3621
|
+
if (routingTags.length) {
|
|
3622
|
+
lines.push(` \u{1F3F7}\uFE0F routing tags: ${routingTags.map((t) => `\`${t}\``).join(", ")}`);
|
|
3623
|
+
}
|
|
3705
3624
|
const nodePrompt = typeof n.systemPrompt === "string" ? n.systemPrompt.trim() : "";
|
|
3706
3625
|
if (nodePrompt) {
|
|
3707
3626
|
lines.push(` \u{1F4CC} Node instruction: ${indentFollowing(nodePrompt, " ")}`);
|
|
@@ -3803,6 +3722,7 @@ function buildRulesSection(coordinatorCliType) {
|
|
|
3803
3722
|
- **Route, don't implement.** Delegate all code reading, analysis, and execution to node agents. Never read source files or run commands in the coordinator \u2014 keep context lean.
|
|
3804
3723
|
- **Front-load task messages.** Include everything the agent needs (files, problem, expected fix) in \`mesh_enqueue_task\` / \`mesh_send_task\`. Append a structured result request at the end: ask the worker to conclude with a JSON block containing \`status\`, \`changedFiles\`, \`gitStatus\`, \`validationResults\`, \`errors\`, \`nextAction\`. The daemon parses this automatically; you can read it from \`mesh_task_history\`.
|
|
3805
3724
|
- **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start fresh only for independent work, provider mismatch, transcript contamination, or required worktree isolation.
|
|
3725
|
+
- **Worktree affinity.** A worktree is a durable per-branch workspace; keep all of a branch's code_change/fix/review work on its worktree node by targeting \`required_tags: ["worktree=<branch>"]\` or \`target_node_id\`. Get the id/branch from the \`mesh_clone_node\` result or a live \`mesh_status\` \u2014 the Configured Nodes snapshot won't list a worktree cloned after launch. Untargeted same-branch follow-ups drift to the base node. Only \`convergence\` (merge/push) runs on the base, never pinned to the worktree.
|
|
3806
3726
|
- **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
|
|
3807
3727
|
- **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
|
|
3808
3728
|
- **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
|
|
@@ -3880,9 +3800,7 @@ var init_coordinator_prompt = __esm({
|
|
|
3880
3800
|
| \`mesh_write_mesh_json_config\` | Gated write of \`.adhdev/mesh.json\` (repo coordinator-prompt config) from the mesh entry \u2014 dry-run/overwrite like mesh_init |
|
|
3881
3801
|
| \`mesh_magi_review\` | Cross-verify a read-only investigation across a standing panel of independent mesh agents (different machines/providers) instead of a single worker |
|
|
3882
3802
|
| \`mesh_magi_collect\` | Collect + synthesize a previously dispatched MAGI fan-out by its consensus group id (async companion to mesh_magi_review wait:false) |
|
|
3883
|
-
| \`
|
|
3884
|
-
| \`mesh_magi_panel_list\` | List configured MAGI panels and resolve each member's availability against the current mesh (read-only) |
|
|
3885
|
-
| \`mesh_magi_kind_panel_set\` | Bind a task_kind \u2192 MAGI kind-panel slots (machine-local, wholesale replacement \u2014 approve current-vs-new first) |
|
|
3803
|
+
| \`mesh_magi_kind_panel_set\` | Bind a task_kind \u2192 MAGI kind-panel slots (the SOLE MAGI panel-resolution surface; machine-local, wholesale replacement \u2014 approve current-vs-new first) |
|
|
3886
3804
|
| \`mesh_magi_kind_panel_list\` | List configured task_kind \u2192 MAGI kind-panel slot bindings (machine-local, read-only) |`;
|
|
3887
3805
|
TOOL_EXPOSURE_PREFLIGHT_SECTION = `## Tool Exposure Preflight
|
|
3888
3806
|
|
|
@@ -3894,6 +3812,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
3894
3812
|
3. **Queue / Delegate** \u2014 The Mesh uses an autonomous pull-based Work Queue:
|
|
3895
3813
|
a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
|
|
3896
3814
|
b. **Node Preparation**: Reuse an existing idle session on the correct node/provider before launching a new chat/session. Call \`mesh_launch_session\` only when no suitable session exists, when the user explicitly asks for a fresh provider/session, or when branch/worktree isolation requires it. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
3815
|
+
b1. **Keep a branch's work on its worktree (worktree affinity).** A worktree node is a durable per-branch workspace, not a one-task throwaway \u2014 implement, review, and fix for the same branch all belong on the SAME worktree, and it lives until its work is converged (merged/pushed) and it is cleaned up. So once you clone a worktree for a branch, route every subsequent \`code_change\`/\`validation\`/fix task for that branch back to that same node: pass \`required_tags: ["worktree=<branch>"]\` or \`target_node_id: <that worktree node's id>\`. **Where to get the node id / tag:** the \`mesh_clone_node\` result returns the new node's \`id\` and \`worktreeBranch\` directly \u2014 use them immediately. The Configured Nodes list in this prompt is a launch-time snapshot and will NOT list a worktree you cloned after this session started, so do not rely on it for freshly-cloned worktrees; take the id/branch from the \`mesh_clone_node\` result, or call \`mesh_status\` to re-list the live nodes (each worktree there advertises its \`worktree=<branch>\` tag). Do NOT leave same-branch follow-ups untargeted \u2014 an untargeted task is claimed by whichever node polls first (usually the base machine node), which strands the work off the branch's worktree. The ONE exception is a \`convergence\` task (merge/push): that is base-only and must NOT be pinned to the worktree.
|
|
3897
3816
|
c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
|
|
3898
3817
|
d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
|
|
3899
3818
|
e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
|
|
@@ -3922,7 +3841,7 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
|
|
|
3922
3841
|
|
|
3923
3842
|
**Save scopes \u2014 label every draft with its scope before asking for approval:**
|
|
3924
3843
|
- **repo-file (commit target)** \u2014 \`.adhdev/refine.json\`, \`.adhdev/worktree_bootstrap.json\`, \`.adhdev/change-impact.json\`, \`.adhdev/mesh.json\`. These are committed to the repository and shared with every machine/contributor.
|
|
3925
|
-
- **machine-local** \u2014 MAGI kind\u2192panel bindings
|
|
3844
|
+
- **machine-local** \u2014 MAGI kind\u2192panel bindings, node providerPriority (\`~/.adhdev/meshes.json\`). These stay on this machine and are NOT committed.
|
|
3926
3845
|
|
|
3927
3846
|
**Guided sequence:**
|
|
3928
3847
|
1. **Scan (dry-run)** \u2014 Call \`mesh_init\` (write=false, the default). It returns per-domain suggested configs for refine / worktree_bootstrap / change-impact, a recommended providerPriority, AND \`currentConfig\` \u2014 the currently-saved config per domain (repo files + machine-local \`magiKindPanels\`). Nothing is written.
|
|
@@ -3930,8 +3849,7 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
|
|
|
3930
3849
|
3. **Approve \u2192 gated write** \u2014 Only after the user approves, call the matching gated-write tool:
|
|
3931
3850
|
- repo \`.adhdev/*\` config files \u2192 \`mesh_init\` with \`write=true\` (and \`overwrite=true\` ONLY for domains the user approved replacing).
|
|
3932
3851
|
- \`.adhdev/mesh.json\` (coordinator prompt / operating notes) \u2192 \`mesh_write_mesh_json_config\` (write=true, overwrite only if approved).
|
|
3933
|
-
- machine-local MAGI kind\u2192panel slots \u2192 \`mesh_magi_kind_panel_set\` (write=true). NOTE: a kind binding is a **wholesale replacement** of that kind's slot list \u2014 present the current-vs-new slots first.
|
|
3934
|
-
- machine-local named MAGI panels \u2192 \`mesh_magi_panel_set\`. providerPriority \u2192 apply via node policy update.
|
|
3852
|
+
- machine-local MAGI kind\u2192panel slots \u2192 \`mesh_magi_kind_panel_set\` (write=true). NOTE: a kind binding is a **wholesale replacement** of that kind's slot list \u2014 present the current-vs-new slots first. providerPriority \u2192 apply via node policy update.
|
|
3935
3853
|
|
|
3936
3854
|
**init vs reinit:**
|
|
3937
3855
|
- **\`mesh_init\`** \u2014 for a fresh, never-onboarded repo. Existing config files are kept (existing-wins) unless the user explicitly approves overwrite. Use for first-time setup.
|
|
@@ -4345,9 +4263,11 @@ function shouldDeliverPendingEventToCoordinator(event, drainer) {
|
|
|
4345
4263
|
if (!event.intendedFor) return false;
|
|
4346
4264
|
return coordinatorIdentityEquals(event.intendedFor, drainer);
|
|
4347
4265
|
}
|
|
4266
|
+
function isTerminalTaskEvent(eventName) {
|
|
4267
|
+
return TERMINAL_TASK_EVENTS.has(eventName);
|
|
4268
|
+
}
|
|
4348
4269
|
function defaultScopeForEvent(eventName) {
|
|
4349
|
-
if (
|
|
4350
|
-
if (TERMINAL_TASK_EVENTS.has(eventName)) return "unicast";
|
|
4270
|
+
if (TERMINAL_TASK_EVENTS.has(eventName) || COORDINATOR_ALERT_EVENTS.has(eventName)) return "unicast";
|
|
4351
4271
|
return "broadcast";
|
|
4352
4272
|
}
|
|
4353
4273
|
function coordinatorIdentityFromEmitFields(fields) {
|
|
@@ -4362,7 +4282,11 @@ function buildPendingEventEmitStamp(opts) {
|
|
|
4362
4282
|
let scope = opts.scope ?? defaultScopeForEvent(opts.eventName);
|
|
4363
4283
|
let intendedFor = opts.intendedFor;
|
|
4364
4284
|
if (scope === "unicast" && !intendedFor) {
|
|
4365
|
-
|
|
4285
|
+
if (isTerminalTaskEvent(opts.eventName)) {
|
|
4286
|
+
intendedFor = opts.dispatchedBy;
|
|
4287
|
+
} else {
|
|
4288
|
+
scope = "broadcast";
|
|
4289
|
+
}
|
|
4366
4290
|
}
|
|
4367
4291
|
if (scope !== "unicast") intendedFor = void 0;
|
|
4368
4292
|
return {
|
|
@@ -4373,7 +4297,7 @@ function buildPendingEventEmitStamp(opts) {
|
|
|
4373
4297
|
...intendedFor ? { intendedFor } : {}
|
|
4374
4298
|
};
|
|
4375
4299
|
}
|
|
4376
|
-
var MESH_PROTOCOL_VERSION_V1, MESH_PROTOCOL_VERSION_V2, SUPPORTED_MESH_PROTOCOL_VERSIONS, MESH_EVENT_SCOPES, MeshContractViolationError, TERMINAL_TASK_EVENTS,
|
|
4300
|
+
var MESH_PROTOCOL_VERSION_V1, MESH_PROTOCOL_VERSION_V2, SUPPORTED_MESH_PROTOCOL_VERSIONS, MESH_EVENT_SCOPES, MeshContractViolationError, TERMINAL_TASK_EVENTS, COORDINATOR_ALERT_EVENTS;
|
|
4377
4301
|
var init_contracts = __esm({
|
|
4378
4302
|
"src/mesh/contracts.ts"() {
|
|
4379
4303
|
"use strict";
|
|
@@ -4402,7 +4326,7 @@ var init_contracts = __esm({
|
|
|
4402
4326
|
"refine:failed",
|
|
4403
4327
|
"refine:accepted"
|
|
4404
4328
|
]);
|
|
4405
|
-
|
|
4329
|
+
COORDINATOR_ALERT_EVENTS = /* @__PURE__ */ new Set([
|
|
4406
4330
|
"mesh:dispatch_blocked"
|
|
4407
4331
|
]);
|
|
4408
4332
|
}
|
|
@@ -6354,7 +6278,22 @@ function meshRuntimeStorePath() {
|
|
|
6354
6278
|
}
|
|
6355
6279
|
return nextPath;
|
|
6356
6280
|
}
|
|
6357
|
-
|
|
6281
|
+
function pruneMeshRuntimeRetention() {
|
|
6282
|
+
try {
|
|
6283
|
+
const store = MeshRuntimeStore.getInstance();
|
|
6284
|
+
const ledger = store.pruneEventLedger(MESH_EVENT_LEDGER_RETENTION_MS);
|
|
6285
|
+
const toolCalls = store.pruneToolCallLog(MESH_TOOL_CALL_LOG_RETENTION_MS);
|
|
6286
|
+
const terminalQueue = store.pruneTerminalQueueEntries(MESH_TERMINAL_QUEUE_RETENTION_MS);
|
|
6287
|
+
if (ledger + toolCalls + terminalQueue > 0) {
|
|
6288
|
+
LOG.info("MeshRuntimeStore", `Retention prune removed ${ledger} ledger / ${toolCalls} tool-call / ${terminalQueue} terminal-queue row(s)`);
|
|
6289
|
+
}
|
|
6290
|
+
return { ledger, toolCalls, terminalQueue };
|
|
6291
|
+
} catch (e) {
|
|
6292
|
+
LOG.warn("MeshRuntimeStore", `Runtime retention prune failed: ${e?.message || e}`);
|
|
6293
|
+
return { ledger: 0, toolCalls: 0, terminalQueue: 0 };
|
|
6294
|
+
}
|
|
6295
|
+
}
|
|
6296
|
+
var import_fs5, import_path5, DatabaseCtor, loggedMigrationFailure, loggedStrayCleanup, MeshRuntimeStore, MESH_EVENT_LEDGER_RETENTION_MS, MESH_TOOL_CALL_LOG_RETENTION_MS, MESH_TERMINAL_QUEUE_RETENTION_MS;
|
|
6358
6297
|
var init_mesh_runtime_store = __esm({
|
|
6359
6298
|
"src/mesh/mesh-runtime-store.ts"() {
|
|
6360
6299
|
"use strict";
|
|
@@ -7466,10 +7405,79 @@ var init_mesh_runtime_store = __esm({
|
|
|
7466
7405
|
}
|
|
7467
7406
|
/**
|
|
7468
7407
|
* Prune tool call log entries older than the given age in ms.
|
|
7469
|
-
*
|
|
7408
|
+
* Returns the number of rows deleted. Also used by the periodic retention
|
|
7409
|
+
* sweep (pruneMeshRuntimeRetention) — the in-write sweep in recordMeshToolCall
|
|
7410
|
+
* only fires every 200 calls and only covers the rate-limit window, so a
|
|
7411
|
+
* quiet mesh otherwise accumulates rows indefinitely.
|
|
7470
7412
|
*/
|
|
7471
7413
|
pruneToolCallLog(olderThanMs) {
|
|
7472
|
-
this.db.prepare("DELETE FROM mesh_tool_call_log WHERE called_at < ?").run(Date.now() - olderThanMs);
|
|
7414
|
+
return this.db.prepare("DELETE FROM mesh_tool_call_log WHERE called_at < ?").run(Date.now() - olderThanMs).changes;
|
|
7415
|
+
}
|
|
7416
|
+
/**
|
|
7417
|
+
* Retention prune for mesh_event_ledger (SoT 1-11 (b)). The ledger is append-only
|
|
7418
|
+
* with NO lifecycle GC of its own, so lifecycle events accumulate without bound
|
|
7419
|
+
* (the dominant mesh-runtime.db growth). Every production reader is bounded to a
|
|
7420
|
+
* recent window (readLedgerEntries tail/limit ≤ a few hundred; task-stats /
|
|
7421
|
+
* terminal-evidence scans look at recent tasks), so rows past a generous age only
|
|
7422
|
+
* cost space. Excluded from deletion — retained forever:
|
|
7423
|
+
* - coordinator_operating_note / _tombstone: runtime-accumulated lessons whose
|
|
7424
|
+
* whole point is surviving restarts; a tombstone must also outlive the notes
|
|
7425
|
+
* it retracts.
|
|
7426
|
+
* Timestamps are ISO-8601 TEXT, so the lexicographic `<` cutoff is a correct time
|
|
7427
|
+
* comparison; a malformed timestamp compares greater than any ISO date and is
|
|
7428
|
+
* conservatively retained. Returns rows deleted.
|
|
7429
|
+
*/
|
|
7430
|
+
pruneEventLedger(olderThanMs) {
|
|
7431
|
+
const cutoffIso = new Date(Date.now() - Math.max(0, olderThanMs)).toISOString();
|
|
7432
|
+
return this.db.prepare(
|
|
7433
|
+
`DELETE FROM mesh_event_ledger
|
|
7434
|
+
WHERE timestamp < ?
|
|
7435
|
+
AND kind NOT IN ('coordinator_operating_note', 'coordinator_operating_note_tombstone')`
|
|
7436
|
+
).run(cutoffIso).changes;
|
|
7437
|
+
}
|
|
7438
|
+
/**
|
|
7439
|
+
* Retention prune for TERMINAL (completed/cancelled/failed) mesh_queue rows
|
|
7440
|
+
* (SoT 1-11 (b)). Terminal rows are kept as recent history (mesh_task_history,
|
|
7441
|
+
* completion-dedup taskId lookups) but nothing ever deletes them, so the queue
|
|
7442
|
+
* table grows monotonically. Rows past the retention window serve no reader —
|
|
7443
|
+
* every dedup/attribution path operates on recent tasks — EXCEPT as a dependency
|
|
7444
|
+
* anchor: taskDependenciesSatisfied resolves dependsOn by id and treats a MISSING
|
|
7445
|
+
* row as not-completed, so deleting a completed row that a still-live
|
|
7446
|
+
* (pending/assigned) row depends on would permanently strand the dependent.
|
|
7447
|
+
* Those ids are collected first and excluded. Returns rows deleted.
|
|
7448
|
+
*/
|
|
7449
|
+
pruneTerminalQueueEntries(olderThanMs) {
|
|
7450
|
+
const cutoffIso = new Date(Date.now() - Math.max(0, olderThanMs)).toISOString();
|
|
7451
|
+
return this.transaction(() => {
|
|
7452
|
+
const liveRows = this.db.prepare(
|
|
7453
|
+
`SELECT payload FROM mesh_queue WHERE status IN ('pending', 'assigned')`
|
|
7454
|
+
).all();
|
|
7455
|
+
const protectedIds = /* @__PURE__ */ new Set();
|
|
7456
|
+
for (const row of liveRows) {
|
|
7457
|
+
try {
|
|
7458
|
+
const entry = JSON.parse(row.payload);
|
|
7459
|
+
if (Array.isArray(entry.dependsOn)) {
|
|
7460
|
+
for (const dep of entry.dependsOn) {
|
|
7461
|
+
if (typeof dep === "string" && dep) protectedIds.add(dep);
|
|
7462
|
+
}
|
|
7463
|
+
}
|
|
7464
|
+
} catch {
|
|
7465
|
+
}
|
|
7466
|
+
}
|
|
7467
|
+
const candidates = this.db.prepare(
|
|
7468
|
+
`SELECT id FROM mesh_queue
|
|
7469
|
+
WHERE status IN ('completed', 'cancelled', 'failed') AND updated_at < ?`
|
|
7470
|
+
).all(cutoffIso);
|
|
7471
|
+
const deletable = candidates.map((r) => r.id).filter((id) => !protectedIds.has(id));
|
|
7472
|
+
let removed = 0;
|
|
7473
|
+
for (let i = 0; i < deletable.length; i += 500) {
|
|
7474
|
+
const chunk = deletable.slice(i, i + 500);
|
|
7475
|
+
removed += this.db.prepare(
|
|
7476
|
+
`DELETE FROM mesh_queue WHERE id IN (${chunk.map(() => "?").join(",")})`
|
|
7477
|
+
).run(...chunk).changes;
|
|
7478
|
+
}
|
|
7479
|
+
return removed;
|
|
7480
|
+
});
|
|
7473
7481
|
}
|
|
7474
7482
|
// ── G2: Event Ledger ────────────────────────────────────────────────────
|
|
7475
7483
|
appendLedgerEntry(entry) {
|
|
@@ -7955,6 +7963,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
7955
7963
|
return removed;
|
|
7956
7964
|
}
|
|
7957
7965
|
};
|
|
7966
|
+
MESH_EVENT_LEDGER_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
7967
|
+
MESH_TOOL_CALL_LOG_RETENTION_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
7968
|
+
MESH_TERMINAL_QUEUE_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
7958
7969
|
}
|
|
7959
7970
|
});
|
|
7960
7971
|
|
|
@@ -8430,6 +8441,16 @@ function routeV2EventsForDrainer(events, drainer, ctx) {
|
|
|
8430
8441
|
continue;
|
|
8431
8442
|
}
|
|
8432
8443
|
if (validated.scope !== "unicast") {
|
|
8444
|
+
if (validated.scope === "broadcast" && isTerminalTaskEvent(validated.event)) {
|
|
8445
|
+
if (identityDeliversTo(validated.dispatchedBy, drainer)) {
|
|
8446
|
+
ctx.batchSeen.add(eventId);
|
|
8447
|
+
bump("v2Delivered");
|
|
8448
|
+
kept.push(event);
|
|
8449
|
+
} else {
|
|
8450
|
+
bump("v2RoutedAway");
|
|
8451
|
+
}
|
|
8452
|
+
continue;
|
|
8453
|
+
}
|
|
8433
8454
|
if (shouldDeliverPendingEventToCoordinator(validated, drainer)) {
|
|
8434
8455
|
ctx.batchSeen.add(eventId);
|
|
8435
8456
|
bump("v2Delivered");
|
|
@@ -16567,6 +16588,15 @@ function getStore() {
|
|
|
16567
16588
|
return void 0;
|
|
16568
16589
|
}
|
|
16569
16590
|
}
|
|
16591
|
+
function registerUnresolvedForwardRetryNudge(handler) {
|
|
16592
|
+
retryNudgeHandler = handler;
|
|
16593
|
+
}
|
|
16594
|
+
function nudgeUnresolvedForwardRetry() {
|
|
16595
|
+
try {
|
|
16596
|
+
retryNudgeHandler?.();
|
|
16597
|
+
} catch {
|
|
16598
|
+
}
|
|
16599
|
+
}
|
|
16570
16600
|
function enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, forwardPayload) {
|
|
16571
16601
|
const target = readNonEmptyString2(coordinatorDaemonId);
|
|
16572
16602
|
const event = readNonEmptyString2(eventName);
|
|
@@ -16650,7 +16680,7 @@ function expireStaleUnresolvedDelegateForwards(nowMs = Date.now()) {
|
|
|
16650
16680
|
return 0;
|
|
16651
16681
|
}
|
|
16652
16682
|
}
|
|
16653
|
-
var import_crypto9, UNRESOLVED_FORWARD_OUTBOX_MESH_ID, UNRESOLVED_FORWARD_MAX_AGE_MS;
|
|
16683
|
+
var import_crypto9, UNRESOLVED_FORWARD_OUTBOX_MESH_ID, UNRESOLVED_FORWARD_MAX_AGE_MS, retryNudgeHandler;
|
|
16654
16684
|
var init_mesh_unresolved_forward_outbox = __esm({
|
|
16655
16685
|
"src/mesh/mesh-unresolved-forward-outbox.ts"() {
|
|
16656
16686
|
"use strict";
|
|
@@ -19042,6 +19072,7 @@ function sweepExpiredRemoteIdleSessions() {
|
|
|
19042
19072
|
if (now - lastPendingEventsPruneAt >= PENDING_EVENTS_PRUNE_INTERVAL_MS) {
|
|
19043
19073
|
lastPendingEventsPruneAt = now;
|
|
19044
19074
|
prunePendingMeshCoordinatorEventsRetention();
|
|
19075
|
+
pruneMeshRuntimeRetention();
|
|
19045
19076
|
}
|
|
19046
19077
|
}
|
|
19047
19078
|
function isIntentionalCleanupStopMetadata(event) {
|
|
@@ -19898,25 +19929,6 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
19898
19929
|
v2Envelope: readV2EnvelopeFromWire(payload)
|
|
19899
19930
|
});
|
|
19900
19931
|
}
|
|
19901
|
-
function enqueueCoordinatorForwardPush(coordinatorDaemonId, run) {
|
|
19902
|
-
let lane = coordinatorForwardLanes.get(coordinatorDaemonId);
|
|
19903
|
-
if (!lane) {
|
|
19904
|
-
lane = { tail: Promise.resolve(), depth: 0 };
|
|
19905
|
-
coordinatorForwardLanes.set(coordinatorDaemonId, lane);
|
|
19906
|
-
}
|
|
19907
|
-
const wasIdle = lane.depth === 0;
|
|
19908
|
-
lane.depth += 1;
|
|
19909
|
-
const dec = () => {
|
|
19910
|
-
lane.depth -= 1;
|
|
19911
|
-
};
|
|
19912
|
-
if (wasIdle) {
|
|
19913
|
-
lane.tail = Promise.resolve(run()).catch(() => {
|
|
19914
|
-
}).then(dec, dec);
|
|
19915
|
-
} else {
|
|
19916
|
-
lane.tail = lane.tail.then(() => run()).catch(() => {
|
|
19917
|
-
}).then(dec, dec);
|
|
19918
|
-
}
|
|
19919
|
-
}
|
|
19920
19932
|
function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
19921
19933
|
const coordinatorDaemonId = readNonEmptyString2(routing.coordinatorDaemonId);
|
|
19922
19934
|
if (!coordinatorDaemonId) return false;
|
|
@@ -19953,28 +19965,15 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
19953
19965
|
nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId),
|
|
19954
19966
|
event: eventName
|
|
19955
19967
|
};
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
|
|
19959
|
-
|
|
19960
|
-
|
|
19961
|
-
|
|
19962
|
-
|
|
19963
|
-
return;
|
|
19964
|
-
}
|
|
19965
|
-
if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
|
|
19966
|
-
}).catch((e) => {
|
|
19967
|
-
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued for retry`);
|
|
19968
|
-
}));
|
|
19969
|
-
LOG.info("MeshEvents", `Durably forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
|
|
19968
|
+
if (!persisted) {
|
|
19969
|
+
traceMeshEventDrop("outbox_enqueue_failed", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId}`);
|
|
19970
|
+
return false;
|
|
19971
|
+
}
|
|
19972
|
+
traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=${readNonEmptyString2(payload.meshId) || "absent"}`);
|
|
19973
|
+
nudgeUnresolvedForwardRetry();
|
|
19974
|
+
LOG.info("MeshEvents", `Durably queued ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId} (reconcile PHASE 0 delivers)`);
|
|
19970
19975
|
return true;
|
|
19971
19976
|
}
|
|
19972
|
-
function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload) {
|
|
19973
|
-
const match = peekUnresolvedDelegateForwards().find(
|
|
19974
|
-
(entry) => daemonIdsEquivalent(entry.coordinatorDaemonId, coordinatorDaemonId) && readNonEmptyString2(entry.payload.event) === eventName && readNonEmptyString2(entry.payload.targetSessionId || entry.payload.sessionId || entry.payload.instanceId) === readNonEmptyString2(payload.targetSessionId || payload.sessionId || payload.instanceId) && readNonEmptyString2(entry.payload.workspace) === readNonEmptyString2(payload.workspace)
|
|
19975
|
-
);
|
|
19976
|
-
if (match) ackUnresolvedDelegateForward(match.id);
|
|
19977
|
-
}
|
|
19978
19977
|
function flushPendingForMeshIdleCoordinators(components, meshId) {
|
|
19979
19978
|
try {
|
|
19980
19979
|
const store = MeshRuntimeStore.getInstance();
|
|
@@ -20107,7 +20106,7 @@ function setupMeshEventForwarding(components) {
|
|
|
20107
20106
|
flushPendingForMeshIdleCoordinators(components, routing.meshId);
|
|
20108
20107
|
});
|
|
20109
20108
|
}
|
|
20110
|
-
var REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, lastPendingEventsPruneAt, PENDING_EVENTS_PRUNE_INTERVAL_MS, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, RECONCILED_COMPLETION_SOURCES
|
|
20109
|
+
var REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, lastPendingEventsPruneAt, PENDING_EVENTS_PRUNE_INTERVAL_MS, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, RECONCILED_COMPLETION_SOURCES;
|
|
20111
20110
|
var init_mesh_event_forwarding = __esm({
|
|
20112
20111
|
"src/mesh/mesh-event-forwarding.ts"() {
|
|
20113
20112
|
"use strict";
|
|
@@ -20144,7 +20143,6 @@ var init_mesh_event_forwarding = __esm({
|
|
|
20144
20143
|
"mcp_mesh_status_transcript_reconciliation",
|
|
20145
20144
|
"no_progress_reconciliation"
|
|
20146
20145
|
]);
|
|
20147
|
-
coordinatorForwardLanes = /* @__PURE__ */ new Map();
|
|
20148
20146
|
}
|
|
20149
20147
|
});
|
|
20150
20148
|
|
|
@@ -21123,6 +21121,65 @@ function recoverStrandedAssignedDispatches(components, meshId, store) {
|
|
|
21123
21121
|
}
|
|
21124
21122
|
}
|
|
21125
21123
|
}
|
|
21124
|
+
function reconcileZombieAssignedTasks(components, mesh, selfIds) {
|
|
21125
|
+
const meshId = mesh.id;
|
|
21126
|
+
const assigned = getQueue(meshId, { status: ["assigned"] });
|
|
21127
|
+
if (!assigned.length) return;
|
|
21128
|
+
const nowMs = Date.now();
|
|
21129
|
+
const assignedNodeIsLocal = (assignedNodeId) => {
|
|
21130
|
+
if (!assignedNodeId) return true;
|
|
21131
|
+
if (selfIds.some((id) => daemonIdsEquivalent(id, assignedNodeId))) return true;
|
|
21132
|
+
const nodes = Array.isArray(mesh.nodes) ? mesh.nodes : [];
|
|
21133
|
+
const node = nodes.find((n) => meshNodeIdMatches(n, assignedNodeId));
|
|
21134
|
+
const nodeDaemonId = readNonEmptyString2(node?.daemonId);
|
|
21135
|
+
return !!nodeDaemonId && selfIds.some((id) => daemonIdsEquivalent(id, nodeDaemonId));
|
|
21136
|
+
};
|
|
21137
|
+
for (const row of assigned) {
|
|
21138
|
+
if (Number.isFinite(Date.parse(row.dispatchTimestamp ?? ""))) continue;
|
|
21139
|
+
const updatedMs = Date.parse(row.updatedAt ?? "");
|
|
21140
|
+
const createdMs = Date.parse(row.createdAt ?? "");
|
|
21141
|
+
const anchorMs = Number.isFinite(updatedMs) ? updatedMs : createdMs;
|
|
21142
|
+
if (!Number.isFinite(anchorMs)) continue;
|
|
21143
|
+
if (nowMs - anchorMs < ZOMBIE_ASSIGNED_MIN_AGE_MS) continue;
|
|
21144
|
+
const terminal = findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id });
|
|
21145
|
+
if (terminal) {
|
|
21146
|
+
const status = terminal.kind === "task_completed" ? "completed" : "failed";
|
|
21147
|
+
updateTaskStatus(meshId, row.id, status);
|
|
21148
|
+
LOG.warn("MeshReconcile", `Zombie assigned task ${row.id} on mesh ${meshId} had ${terminal.kind} ledger evidence \u2014 flipped to ${status}`);
|
|
21149
|
+
continue;
|
|
21150
|
+
}
|
|
21151
|
+
if (!assignedNodeIsLocal(row.assignedNodeId)) continue;
|
|
21152
|
+
if (row.assignedSessionId) {
|
|
21153
|
+
const verdict = resolveSessionBusyVerdict(components, row.assignedSessionId);
|
|
21154
|
+
if (verdict !== "UNKNOWN") continue;
|
|
21155
|
+
}
|
|
21156
|
+
const reason = row.assignedSessionId ? "assigned_zombie_session_missing" : "assigned_zombie_no_session_bound";
|
|
21157
|
+
const failed = updateTaskStatus(meshId, row.id, "failed");
|
|
21158
|
+
if (!failed) continue;
|
|
21159
|
+
try {
|
|
21160
|
+
appendLedgerEntry(meshId, {
|
|
21161
|
+
kind: "task_failed",
|
|
21162
|
+
nodeId: row.assignedNodeId,
|
|
21163
|
+
sessionId: row.assignedSessionId,
|
|
21164
|
+
payload: {
|
|
21165
|
+
taskId: row.id,
|
|
21166
|
+
reason,
|
|
21167
|
+
source: "reconcile_zombie_assigned_sweep",
|
|
21168
|
+
ageMs: nowMs - anchorMs
|
|
21169
|
+
}
|
|
21170
|
+
});
|
|
21171
|
+
} catch {
|
|
21172
|
+
}
|
|
21173
|
+
LOG.warn("MeshReconcile", `Failed zombie assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, no dispatchTimestamp, stale ${Math.round((nowMs - anchorMs) / 6e4)}m, ${reason})`);
|
|
21174
|
+
traceMeshEventDrop("assigned_zombie_failed", {
|
|
21175
|
+
taskId: row.id,
|
|
21176
|
+
sessionId: row.assignedSessionId,
|
|
21177
|
+
nodeId: row.assignedNodeId,
|
|
21178
|
+
meshId,
|
|
21179
|
+
event: "agent:generating_completed"
|
|
21180
|
+
}, `${reason} stale=${Math.round((nowMs - anchorMs) / 6e4)}m`);
|
|
21181
|
+
}
|
|
21182
|
+
}
|
|
21126
21183
|
async function runMeshReconcileTick(components) {
|
|
21127
21184
|
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
21128
21185
|
const drainDaemonIds = resolveCoordinatorDaemonIds(components);
|
|
@@ -21161,6 +21218,11 @@ async function runMeshReconcileTick(components) {
|
|
|
21161
21218
|
} catch (e) {
|
|
21162
21219
|
LOG.warn("MeshReconcile", `Assigned-stranded watchdog failed for mesh ${mesh.id}: ${e?.message || e}`);
|
|
21163
21220
|
}
|
|
21221
|
+
try {
|
|
21222
|
+
reconcileZombieAssignedTasks(components, mesh, selfIds);
|
|
21223
|
+
} catch (e) {
|
|
21224
|
+
LOG.warn("MeshReconcile", `Assigned-zombie sweep failed for mesh ${mesh.id}: ${e?.message || e}`);
|
|
21225
|
+
}
|
|
21164
21226
|
}
|
|
21165
21227
|
}
|
|
21166
21228
|
for (const mesh of listMeshes()) {
|
|
@@ -21382,6 +21444,25 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
|
|
|
21382
21444
|
LOG.warn("MeshReconcile", `Failed to ledger-expire strict-unmatched ${pending.event} for mesh ${meshId}: ${e?.message || e}`);
|
|
21383
21445
|
}
|
|
21384
21446
|
}
|
|
21447
|
+
function scheduleUnresolvedForwardNudge(components) {
|
|
21448
|
+
if (!components.dispatchMeshCommand) return;
|
|
21449
|
+
if (unresolvedForwardNudgeTimer) return;
|
|
21450
|
+
unresolvedForwardNudgeTimer = setTimeout(() => {
|
|
21451
|
+
unresolvedForwardNudgeTimer = void 0;
|
|
21452
|
+
if (unresolvedForwardNudgeRunning) return;
|
|
21453
|
+
unresolvedForwardNudgeRunning = true;
|
|
21454
|
+
void retryUnresolvedDelegateForwards(components).catch((e) => LOG.warn("MeshReconcile", `Nudged unresolved-forward retry failed: ${e?.message || e}`)).finally(() => {
|
|
21455
|
+
unresolvedForwardNudgeRunning = false;
|
|
21456
|
+
});
|
|
21457
|
+
}, UNRESOLVED_FORWARD_NUDGE_DELAY_MS);
|
|
21458
|
+
if (typeof unresolvedForwardNudgeTimer.unref === "function") unresolvedForwardNudgeTimer.unref();
|
|
21459
|
+
}
|
|
21460
|
+
function clearUnresolvedForwardNudge() {
|
|
21461
|
+
if (unresolvedForwardNudgeTimer) {
|
|
21462
|
+
clearTimeout(unresolvedForwardNudgeTimer);
|
|
21463
|
+
unresolvedForwardNudgeTimer = void 0;
|
|
21464
|
+
}
|
|
21465
|
+
}
|
|
21385
21466
|
async function retryUnresolvedDelegateForwards(components) {
|
|
21386
21467
|
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
21387
21468
|
if (!dispatchMeshCommand) return;
|
|
@@ -21466,15 +21547,18 @@ function setupMeshReconcileLoop(components) {
|
|
|
21466
21547
|
});
|
|
21467
21548
|
}, intervalMs);
|
|
21468
21549
|
if (typeof timer.unref === "function") timer.unref();
|
|
21550
|
+
registerUnresolvedForwardRetryNudge(() => scheduleUnresolvedForwardNudge(components));
|
|
21469
21551
|
LOG.info("MeshReconcile", `Mesh reconcile loop started (interval ${intervalMs}ms)`);
|
|
21470
21552
|
return {
|
|
21471
21553
|
stop() {
|
|
21472
21554
|
clearInterval(timer);
|
|
21555
|
+
registerUnresolvedForwardRetryNudge(void 0);
|
|
21556
|
+
clearUnresolvedForwardNudge();
|
|
21473
21557
|
LOG.info("MeshReconcile", "Mesh reconcile loop stopped");
|
|
21474
21558
|
}
|
|
21475
21559
|
};
|
|
21476
21560
|
}
|
|
21477
|
-
var coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
|
|
21561
|
+
var coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
|
|
21478
21562
|
var init_mesh_reconcile_loop = __esm({
|
|
21479
21563
|
"src/mesh/mesh-reconcile-loop.ts"() {
|
|
21480
21564
|
"use strict";
|
|
@@ -21506,9 +21590,12 @@ var init_mesh_reconcile_loop = __esm({
|
|
|
21506
21590
|
DELIVERED_NO_TURN_DEADLINE_MS = 15 * 6e4;
|
|
21507
21591
|
RECLAIM_UNKNOWN_GRACE_TICKS = 3;
|
|
21508
21592
|
deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
|
|
21593
|
+
ZOMBIE_ASSIGNED_MIN_AGE_MS = 30 * 60 * 1e3;
|
|
21509
21594
|
STRICT_SESSION_MATCH_TTL_MS = 6e4;
|
|
21510
21595
|
unresolvedForwardRejectionCounts = /* @__PURE__ */ new Map();
|
|
21511
21596
|
MAX_FORWARD_REJECTIONS = 5;
|
|
21597
|
+
UNRESOLVED_FORWARD_NUDGE_DELAY_MS = 250;
|
|
21598
|
+
unresolvedForwardNudgeRunning = false;
|
|
21512
21599
|
}
|
|
21513
21600
|
});
|
|
21514
21601
|
|
|
@@ -27404,7 +27491,6 @@ __export(index_exports, {
|
|
|
27404
27491
|
getLedgerSummary: () => getLedgerSummary,
|
|
27405
27492
|
getLogLevel: () => getLogLevel,
|
|
27406
27493
|
getMagiKindPanel: () => getMagiKindPanel,
|
|
27407
|
-
getMagiPanel: () => getMagiPanel,
|
|
27408
27494
|
getMesh: () => getMesh,
|
|
27409
27495
|
getMeshByRepo: () => getMeshByRepo,
|
|
27410
27496
|
getMeshMagiActivityByGroup: () => getMeshMagiActivityByGroup,
|
|
@@ -27462,7 +27548,6 @@ __export(index_exports, {
|
|
|
27462
27548
|
listCoordinatorsForWorkspace: () => listCoordinatorsForWorkspace,
|
|
27463
27549
|
listHostedCliRuntimes: () => listHostedCliRuntimes,
|
|
27464
27550
|
listMagiKindPanels: () => listMagiKindPanels,
|
|
27465
|
-
listMagiPanels: () => listMagiPanels,
|
|
27466
27551
|
listMeshMissionSummaries: () => listMeshMissionSummaries,
|
|
27467
27552
|
listMeshMissionsForTool: () => listMeshMissionsForTool,
|
|
27468
27553
|
listMeshes: () => listMeshes,
|
|
@@ -27499,7 +27584,6 @@ __export(index_exports, {
|
|
|
27499
27584
|
normalizeInputEnvelope: () => normalizeInputEnvelope,
|
|
27500
27585
|
normalizeInteractivePrompt: () => normalizeInteractivePrompt,
|
|
27501
27586
|
normalizeInteractivePromptResponse: () => normalizeInteractivePromptResponse,
|
|
27502
|
-
normalizeMagiPanel: () => normalizeMagiPanel,
|
|
27503
27587
|
normalizeMagiSlots: () => normalizeMagiSlots,
|
|
27504
27588
|
normalizeManagedStatus: () => normalizeManagedStatus,
|
|
27505
27589
|
normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
|
|
@@ -27542,7 +27626,6 @@ __export(index_exports, {
|
|
|
27542
27626
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
27543
27627
|
registerMeshCoordinator: () => registerMeshCoordinator,
|
|
27544
27628
|
removeMagiKindPanel: () => removeMagiKindPanel,
|
|
27545
|
-
removeMagiPanel: () => removeMagiPanel,
|
|
27546
27629
|
removeNode: () => removeNode,
|
|
27547
27630
|
removeWorktree: () => removeWorktree,
|
|
27548
27631
|
requeueHeldMeshCoordinatorEvents: () => requeueHeldMeshCoordinatorEvents,
|
|
@@ -27605,7 +27688,6 @@ __export(index_exports, {
|
|
|
27605
27688
|
updateSessionDeliveryStatus: () => updateSessionDeliveryStatus,
|
|
27606
27689
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
27607
27690
|
updateTaskStatus: () => updateTaskStatus,
|
|
27608
|
-
upsertMagiPanel: () => upsertMagiPanel,
|
|
27609
27691
|
upsertMeshMission: () => upsertMeshMission,
|
|
27610
27692
|
upsertSavedProviderSession: () => upsertSavedProviderSession,
|
|
27611
27693
|
validateChangeImpactConfig: () => validateChangeImpactConfig,
|
|
@@ -34619,6 +34701,16 @@ function isRuntimeFallbackHistorySessionId(candidateHistorySessionId, targetSess
|
|
|
34619
34701
|
const candidate = typeof candidateHistorySessionId === "string" ? candidateHistorySessionId.trim() : "";
|
|
34620
34702
|
return candidate === target;
|
|
34621
34703
|
}
|
|
34704
|
+
function resolveNativeHistoryReadSession(args, candidateHistorySessionId) {
|
|
34705
|
+
const targetSid = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
34706
|
+
const explicitHistorySessionId = getExplicitHistorySessionId(args);
|
|
34707
|
+
const isRuntimeFallback = Boolean(
|
|
34708
|
+
targetSid && isRuntimeFallbackHistorySessionId(candidateHistorySessionId, targetSid) && (!explicitHistorySessionId || isRuntimeFallbackHistorySessionId(explicitHistorySessionId, targetSid))
|
|
34709
|
+
);
|
|
34710
|
+
const pinnedProviderSessionId = getBoundProviderSessionIdPin(args?.targetSessionId);
|
|
34711
|
+
const effectiveHistorySessionId = isRuntimeFallback ? pinnedProviderSessionId || void 0 : candidateHistorySessionId;
|
|
34712
|
+
return { isRuntimeFallback, pinnedProviderSessionId, effectiveHistorySessionId };
|
|
34713
|
+
}
|
|
34622
34714
|
function getHistorySessionId(h, args) {
|
|
34623
34715
|
const explicit = getExplicitHistorySessionId(args);
|
|
34624
34716
|
if (explicit) return explicit;
|
|
@@ -35453,13 +35545,11 @@ async function handleChatHistory(h, args) {
|
|
|
35453
35545
|
if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
|
|
35454
35546
|
}
|
|
35455
35547
|
const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
|
|
35456
|
-
const
|
|
35457
|
-
|
|
35458
|
-
|
|
35459
|
-
|
|
35460
|
-
);
|
|
35461
|
-
const pinnedProviderSessionIdForHistory = getBoundProviderSessionIdPin(args?.targetSessionId);
|
|
35462
|
-
const effectiveHistorySessionId = historySessionIdIsRuntimeFallback ? pinnedProviderSessionIdForHistory || void 0 : historySessionId;
|
|
35548
|
+
const {
|
|
35549
|
+
isRuntimeFallback: historySessionIdIsRuntimeFallback,
|
|
35550
|
+
pinnedProviderSessionId: pinnedProviderSessionIdForHistory,
|
|
35551
|
+
effectiveHistorySessionId
|
|
35552
|
+
} = resolveNativeHistoryReadSession(args, historySessionId);
|
|
35463
35553
|
const exactNativeHistoryScope = Boolean(
|
|
35464
35554
|
typeof args?.targetSessionId === "string" && args.targetSessionId.trim() || typeof args?.historySessionId === "string" && args.historySessionId.trim() && !historySessionIdIsRuntimeFallback || typeof args?.providerSessionId === "string" && args.providerSessionId.trim()
|
|
35465
35555
|
);
|
|
@@ -35620,12 +35710,10 @@ async function handleReadChat(h, args) {
|
|
|
35620
35710
|
let nativeHistory = null;
|
|
35621
35711
|
let nativeHistoryError;
|
|
35622
35712
|
if (supportsNative) {
|
|
35623
|
-
const
|
|
35624
|
-
|
|
35625
|
-
|
|
35626
|
-
|
|
35627
|
-
);
|
|
35628
|
-
const effectiveNativeReadSessionId = nativeReadSessionIdIsRuntimeFallback ? pinnedProviderSessionIdForRead || void 0 : nativeHistoryReadSessionId;
|
|
35713
|
+
const {
|
|
35714
|
+
pinnedProviderSessionId: pinnedProviderSessionIdForRead,
|
|
35715
|
+
effectiveHistorySessionId: effectiveNativeReadSessionId
|
|
35716
|
+
} = resolveNativeHistoryReadSession(args, nativeHistoryReadSessionId);
|
|
35629
35717
|
try {
|
|
35630
35718
|
nativeHistory = readCliProviderNativeHistory(agentStr, {
|
|
35631
35719
|
canonicalHistory: provider?.nativeHistory,
|
|
@@ -35902,12 +35990,11 @@ async function handleReadChat(h, args) {
|
|
|
35902
35990
|
const workspace = targetSid ? typeof registrySessionWorkspace === "string" ? registrySessionWorkspace : argsWorkspace ?? currentSessionWorkspace : typeof currentSessionWorkspace === "string" ? currentSessionWorkspace : void 0;
|
|
35903
35991
|
const intendedWorkspace = argsWorkspace;
|
|
35904
35992
|
const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory);
|
|
35905
|
-
const
|
|
35906
|
-
|
|
35907
|
-
|
|
35908
|
-
|
|
35909
|
-
);
|
|
35910
|
-
const effectiveHistorySessionIdForRead = historySessionIdIsRuntimeFallback ? pinnedProviderSessionIdForHistory || void 0 : historySessionId;
|
|
35993
|
+
const {
|
|
35994
|
+
isRuntimeFallback: historySessionIdIsRuntimeFallback,
|
|
35995
|
+
pinnedProviderSessionId: pinnedProviderSessionIdForHistory,
|
|
35996
|
+
effectiveHistorySessionId: effectiveHistorySessionIdForRead
|
|
35997
|
+
} = resolveNativeHistoryReadSession(args, historySessionId);
|
|
35911
35998
|
const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
|
|
35912
35999
|
canonicalHistory: provider?.nativeHistory,
|
|
35913
36000
|
historySessionId: effectiveHistorySessionIdForRead,
|
|
@@ -40131,6 +40218,53 @@ var statusMetaHandlers = {
|
|
|
40131
40218
|
|
|
40132
40219
|
// src/commands/low-family/coordinator-prompt.ts
|
|
40133
40220
|
var coordinatorPromptHandlers = {
|
|
40221
|
+
/**
|
|
40222
|
+
* Render the coordinator system prompt for a mesh + CLI type, so the
|
|
40223
|
+
* dashboard can show the operator exactly what a coordinator session
|
|
40224
|
+
* receives by default. This resolves the mesh, applies its repo-mesh
|
|
40225
|
+
* config, and runs the SAME buildCoordinatorSystemPrompt the launch path
|
|
40226
|
+
* uses — minus the runtime-only best-effort sections (mission / recent
|
|
40227
|
+
* activity / operating notes), which are launch-scope and not part of the
|
|
40228
|
+
* static "default base" an operator is trying to preview here.
|
|
40229
|
+
*
|
|
40230
|
+
* It respects mesh-level and user-file override/append layering, so the
|
|
40231
|
+
* preview reflects the effective prompt: with no overrides configured it
|
|
40232
|
+
* shows the pure daemon default; with an override set it shows that.
|
|
40233
|
+
*/
|
|
40234
|
+
coordinator_prompt_preview: async (ctx, args) => {
|
|
40235
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
40236
|
+
const cliType = typeof args?.cliType === "string" && args.cliType.trim() ? args.cliType.trim() : "claude-cli";
|
|
40237
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
40238
|
+
try {
|
|
40239
|
+
let mesh = null;
|
|
40240
|
+
if (ctx.getMeshForCommand) {
|
|
40241
|
+
const resolved = await ctx.getMeshForCommand(meshId);
|
|
40242
|
+
mesh = resolved?.mesh ?? null;
|
|
40243
|
+
}
|
|
40244
|
+
if (!mesh) {
|
|
40245
|
+
const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
40246
|
+
mesh = getMesh2(meshId);
|
|
40247
|
+
}
|
|
40248
|
+
if (!mesh) return { success: false, error: `mesh not found: ${meshId}` };
|
|
40249
|
+
let effectiveMesh = mesh;
|
|
40250
|
+
try {
|
|
40251
|
+
const { loadRepoMeshJsonConfig: loadRepoMeshJsonConfig2, applyRepoMeshConfig: applyRepoMeshConfig2 } = await Promise.resolve().then(() => (init_mesh_json_config(), mesh_json_config_exports));
|
|
40252
|
+
const workspace = typeof mesh?.workspace === "string" ? mesh.workspace : void 0;
|
|
40253
|
+
if (workspace) {
|
|
40254
|
+
const loaded = loadRepoMeshJsonConfig2(workspace);
|
|
40255
|
+
if (loaded?.sourceType !== "invalid") {
|
|
40256
|
+
effectiveMesh = applyRepoMeshConfig2(mesh, loaded?.config);
|
|
40257
|
+
}
|
|
40258
|
+
}
|
|
40259
|
+
} catch {
|
|
40260
|
+
}
|
|
40261
|
+
const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
40262
|
+
const prompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType });
|
|
40263
|
+
return { success: true, prompt, cliType, meshId, bytes: Buffer.byteLength(prompt, "utf8") };
|
|
40264
|
+
} catch (error) {
|
|
40265
|
+
return { success: false, error: error?.message || String(error) };
|
|
40266
|
+
}
|
|
40267
|
+
},
|
|
40134
40268
|
list_coordinator_prompts: async (_ctx, _args) => {
|
|
40135
40269
|
const fs41 = await import("fs");
|
|
40136
40270
|
const path45 = await import("path");
|
|
@@ -54707,61 +54841,15 @@ var meshCrudHandlers = {
|
|
|
54707
54841
|
return { success: false, error: e.message };
|
|
54708
54842
|
}
|
|
54709
54843
|
},
|
|
54710
|
-
// ─── MAGI panels (machine-local config, sibling to meshes) ───────────────
|
|
54711
|
-
// Panels live in ~/.adhdev/meshes.json `magiPanels` and are pure local config
|
|
54712
|
-
// (no mesh ownership). These three handlers mirror list_meshes/create_mesh/
|
|
54713
|
-
// update_mesh: dynamic-import the already-exported mesh-config accessors and
|
|
54714
|
-
// surface normalizeMagiPanel's structured error codes (invalid_magi_panel,
|
|
54715
|
-
// magi_panel_exists) verbatim so the dashboard can render them.
|
|
54716
|
-
//
|
|
54717
|
-
// Permission: magi_panel_set / magi_panel_remove are WRITE commands. They are
|
|
54718
|
-
// intentionally NOT listed in canPeerUsePrivilegedShareCommand (daemon-cloud
|
|
54719
|
-
// data-channel-router), so a peer holding ANY share permission hits its
|
|
54720
|
-
// `default → false` branch — identical owner-only gating to create_mesh /
|
|
54721
|
-
// update_mesh / list_meshes (none of which are listed there either). A trusted
|
|
54722
|
-
// peer (no permission = the owner) passes the top `!permission → true` guard.
|
|
54723
|
-
// Mirror, don't invent: do not add a new policy tier here.
|
|
54724
|
-
//
|
|
54725
|
-
// Resolvability (coupling / stale / available) is deliberately NOT computed
|
|
54726
|
-
// here: buildMagiFanoutPlan lives in mcp-server, unreachable from daemon-core.
|
|
54727
|
-
// magi_panel_list returns the raw definitions only; the dashboard derives
|
|
54728
|
-
// member resolvability client-side (web-core MagiPanelManager, reusing the
|
|
54729
|
-
// MagiGroupRow coupling logic) against live mesh_status.
|
|
54730
|
-
magi_panel_list: async (_ctx, _args) => {
|
|
54731
|
-
try {
|
|
54732
|
-
const { listMagiPanels: listMagiPanels2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
54733
|
-
return { success: true, panels: listMagiPanels2() };
|
|
54734
|
-
} catch (e) {
|
|
54735
|
-
return { success: false, error: e.message };
|
|
54736
|
-
}
|
|
54737
|
-
},
|
|
54738
|
-
magi_panel_set: async (_ctx, args) => {
|
|
54739
|
-
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
54740
|
-
if (!name) return { success: false, error: "invalid_magi_panel: panel name is required" };
|
|
54741
|
-
try {
|
|
54742
|
-
const { upsertMagiPanel: upsertMagiPanel2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
54743
|
-
const panel = upsertMagiPanel2(name, args?.panel, { overwrite: args?.overwrite === true });
|
|
54744
|
-
return { success: true, name, panel };
|
|
54745
|
-
} catch (e) {
|
|
54746
|
-
return { success: false, error: e.message };
|
|
54747
|
-
}
|
|
54748
|
-
},
|
|
54749
|
-
magi_panel_remove: async (_ctx, args) => {
|
|
54750
|
-
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
54751
|
-
if (!name) return { success: false, error: "invalid_magi_panel: panel name is required" };
|
|
54752
|
-
try {
|
|
54753
|
-
const { removeMagiPanel: removeMagiPanel2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
54754
|
-
const removed = removeMagiPanel2(name);
|
|
54755
|
-
return { success: true, removed };
|
|
54756
|
-
} catch (e) {
|
|
54757
|
-
return { success: false, error: e.message };
|
|
54758
|
-
}
|
|
54759
|
-
},
|
|
54760
54844
|
// ─── MAGI kind → panel bindings (MAGI-KIND-PANEL, machine-local config) ───
|
|
54761
|
-
// Per-task_kind slot lists in ~/.adhdev/meshes.json `magiKindPanels
|
|
54762
|
-
//
|
|
54763
|
-
//
|
|
54764
|
-
//
|
|
54845
|
+
// Per-task_kind slot lists in ~/.adhdev/meshes.json `magiKindPanels` — the SOLE
|
|
54846
|
+
// MAGI panel-resolution surface (the former named-panel magi_panel_* handlers were
|
|
54847
|
+
// removed). Owner-only gating: intentionally NOT listed in
|
|
54848
|
+
// canPeerUsePrivilegedShareCommand (daemon-cloud data-channel-router), so a peer
|
|
54849
|
+
// holding ANY share permission hits its `default → false` branch — identical
|
|
54850
|
+
// owner-only gating to create_mesh / update_mesh / list_meshes. A trusted peer (no
|
|
54851
|
+
// permission = the owner) passes the top `!permission → true` guard. set/remove are
|
|
54852
|
+
// WRITE commands; list is read-only. normalizeMagiSlots (inside setMagiKindPanel)
|
|
54765
54853
|
// surfaces invalid_magi_kind_panel: … messages verbatim for the editor.
|
|
54766
54854
|
magi_kind_panel_list: async (_ctx, _args) => {
|
|
54767
54855
|
try {
|
|
@@ -54814,13 +54902,15 @@ var meshCrudHandlers = {
|
|
|
54814
54902
|
const daemonId = typeof args?.daemonId === "string" && args.daemonId.trim() ? args.daemonId.trim() : void 0;
|
|
54815
54903
|
const machineId = typeof args?.machineId === "string" && args.machineId.trim() ? args.machineId.trim() : void 0;
|
|
54816
54904
|
const repoRoot = typeof args?.repoRoot === "string" && args.repoRoot.trim() ? args.repoRoot.trim() : void 0;
|
|
54905
|
+
const capabilities = Array.isArray(args?.capabilities) ? args.capabilities.map((t) => typeof t === "string" ? t.trim() : "").filter(Boolean) : void 0;
|
|
54817
54906
|
const node = addNode2(meshId, {
|
|
54818
54907
|
workspace,
|
|
54819
54908
|
...repoRoot ? { repoRoot } : {},
|
|
54820
54909
|
...daemonId ? { daemonId } : {},
|
|
54821
54910
|
...machineId ? { machineId } : {},
|
|
54822
54911
|
...policy ? { policy } : {},
|
|
54823
|
-
...role ? { role } : {}
|
|
54912
|
+
...role ? { role } : {},
|
|
54913
|
+
...capabilities && capabilities.length ? { capabilities } : {}
|
|
54824
54914
|
});
|
|
54825
54915
|
if (!node) return { success: false, error: "Mesh not found" };
|
|
54826
54916
|
ctx.invalidateAggregateMeshStatus(meshId);
|
|
@@ -54862,6 +54952,9 @@ var meshCrudHandlers = {
|
|
|
54862
54952
|
} else if (args?.systemPrompt === null) {
|
|
54863
54953
|
patch.systemPrompt = void 0;
|
|
54864
54954
|
}
|
|
54955
|
+
if (Array.isArray(args?.capabilities)) {
|
|
54956
|
+
patch.capabilities = args.capabilities.map((t) => typeof t === "string" ? t.trim() : "").filter(Boolean);
|
|
54957
|
+
}
|
|
54865
54958
|
const node = updateNode2(meshId, nodeId, patch);
|
|
54866
54959
|
if (!node) return { success: false, error: "Mesh node not found" };
|
|
54867
54960
|
ctx.invalidateAggregateMeshStatus(meshId);
|
|
@@ -69891,7 +69984,6 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
69891
69984
|
getLedgerSummary,
|
|
69892
69985
|
getLogLevel,
|
|
69893
69986
|
getMagiKindPanel,
|
|
69894
|
-
getMagiPanel,
|
|
69895
69987
|
getMesh,
|
|
69896
69988
|
getMeshByRepo,
|
|
69897
69989
|
getMeshMagiActivityByGroup,
|
|
@@ -69949,7 +70041,6 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
69949
70041
|
listCoordinatorsForWorkspace,
|
|
69950
70042
|
listHostedCliRuntimes,
|
|
69951
70043
|
listMagiKindPanels,
|
|
69952
|
-
listMagiPanels,
|
|
69953
70044
|
listMeshMissionSummaries,
|
|
69954
70045
|
listMeshMissionsForTool,
|
|
69955
70046
|
listMeshes,
|
|
@@ -69986,7 +70077,6 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
69986
70077
|
normalizeInputEnvelope,
|
|
69987
70078
|
normalizeInteractivePrompt,
|
|
69988
70079
|
normalizeInteractivePromptResponse,
|
|
69989
|
-
normalizeMagiPanel,
|
|
69990
70080
|
normalizeMagiSlots,
|
|
69991
70081
|
normalizeManagedStatus,
|
|
69992
70082
|
normalizeMeshCapabilityTags,
|
|
@@ -70029,7 +70119,6 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
70029
70119
|
registerExtensionProviders,
|
|
70030
70120
|
registerMeshCoordinator,
|
|
70031
70121
|
removeMagiKindPanel,
|
|
70032
|
-
removeMagiPanel,
|
|
70033
70122
|
removeNode,
|
|
70034
70123
|
removeWorktree,
|
|
70035
70124
|
requeueHeldMeshCoordinatorEvents,
|
|
@@ -70092,7 +70181,6 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
70092
70181
|
updateSessionDeliveryStatus,
|
|
70093
70182
|
updateSessionTaskStatus,
|
|
70094
70183
|
updateTaskStatus,
|
|
70095
|
-
upsertMagiPanel,
|
|
70096
70184
|
upsertMeshMission,
|
|
70097
70185
|
upsertSavedProviderSession,
|
|
70098
70186
|
validateChangeImpactConfig,
|