@adhdev/daemon-core 0.9.82-rc.506 → 0.9.82-rc.507

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.
@@ -21,6 +21,7 @@
21
21
  * a static prompt, which is also fine.
22
22
  */
23
23
  import type { LocalMeshEntry, RepoMeshStatus } from '../repo-mesh-types.js';
24
+ import type { MagiKindPanelMap } from '@adhdev/mesh-shared';
24
25
  /**
25
26
  * Cheap, locally-derived "what just happened" snapshot for the coordinator
26
27
  * prompt. Built at launch from the local ledger + work-queue stats — no remote
@@ -91,5 +92,25 @@ export interface CoordinatorPromptContext {
91
92
  * section.
92
93
  */
93
94
  operatingNotes?: CoordinatorOperatingNote[];
95
+ /**
96
+ * Machine-local MAGI kind-panel bindings (`~/.adhdev/meshes.json`
97
+ * `magiKindPanels`), read live at launch. Omitted / empty / all-empty →
98
+ * no "## Configured MAGI panels" section, so a mesh with no MAGI configured
99
+ * renders identically to before. Threaded in the same systematic way as the
100
+ * brain presets: read machine-local config at launch, render a pure section.
101
+ */
102
+ magiKindPanels?: MagiKindPanelMap;
94
103
  }
95
104
  export declare function buildCoordinatorSystemPrompt(ctx: CoordinatorPromptContext): string;
105
+ /**
106
+ * Render the machine-local MAGI kind-panel bindings so the coordinator KNOWS
107
+ * which cross-verification panels (rca / design / claim_audit / freeform) are
108
+ * actually configured on this machine. Without this the coordinator only sees
109
+ * the `mesh_magi_*` tools in the static table and has no idea MAGI is set up.
110
+ *
111
+ * Pure — takes the panels map (read live at launch, mirroring how brain presets
112
+ * read getDifficultyBrains). Returns null (section OMITTED) when nothing usable
113
+ * is configured: undefined/null map, or every kind maps to an empty slot list.
114
+ * That keeps a MAGI-less mesh's prompt byte-identical to before.
115
+ */
116
+ export declare function buildMagiKindPanelsSection(panels: MagiKindPanelMap | undefined | null): string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.506",
3
+ "version": "0.9.82-rc.507",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -47,8 +47,8 @@
47
47
  "author": "vilmire",
48
48
  "license": "AGPL-3.0-or-later",
49
49
  "dependencies": {
50
- "@adhdev/mesh-shared": "0.9.82-rc.506",
51
- "@adhdev/session-host-core": "0.9.82-rc.506",
50
+ "@adhdev/mesh-shared": "0.9.82-rc.507",
51
+ "@adhdev/session-host-core": "0.9.82-rc.507",
52
52
  "@agentclientprotocol/sdk": "^0.16.1",
53
53
  "ajv": "^8.20.0",
54
54
  "ajv-formats": "^3.0.1",
@@ -138,6 +138,19 @@ export const meshCoordinatorLaunchHandlers: Record<string, HighFamilyHandler> =
138
138
  } catch { return undefined; }
139
139
  };
140
140
 
141
+ // MAGI panels: load the machine-local kind-panel bindings so the
142
+ // coordinator prompt auto-lists which cross-verification panels
143
+ // (rca / design / claim_audit / freeform) are configured. Same
144
+ // systematic pattern as the brain presets — read machine-local
145
+ // config at launch. Best-effort: a read failure or empty map just
146
+ // omits the "## Configured MAGI panels" section.
147
+ const loadMagiKindPanelsBestEffort = async () => {
148
+ try {
149
+ const { listMagiKindPanels } = await import('../../config/mesh-config.js');
150
+ return listMagiKindPanels();
151
+ } catch { return undefined; }
152
+ };
153
+
141
154
  // Support inline mesh data from cloud (bypasses local meshes.json lookup)
142
155
  let mesh: any;
143
156
  if (args?.inlineMesh && typeof args.inlineMesh === 'object') {
@@ -264,7 +277,7 @@ export const meshCoordinatorLaunchHandlers: Record<string, HighFamilyHandler> =
264
277
  // Build coordinator prompt first — fail closed on errors.
265
278
  let cliCmdSystemPrompt = '';
266
279
  try {
267
- cliCmdSystemPrompt = buildCoordinatorSystemPrompt({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || undefined, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id) });
280
+ cliCmdSystemPrompt = buildCoordinatorSystemPrompt({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || undefined, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort() });
268
281
  } catch (error: any) {
269
282
  const message = error?.message || String(error);
270
283
  LOG.error('MeshCoordinator', `Failed to build coordinator prompt: ${message}`);
@@ -484,7 +497,7 @@ export const meshCoordinatorLaunchHandlers: Record<string, HighFamilyHandler> =
484
497
  // broken mesh state is visible instead of silently launching with weaker rules.
485
498
  let systemPrompt = '';
486
499
  try {
487
- systemPrompt = buildCoordinatorSystemPrompt({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || undefined, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id) });
500
+ systemPrompt = buildCoordinatorSystemPrompt({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || undefined, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort() });
488
501
  } catch (error: any) {
489
502
  const message = error?.message || String(error);
490
503
  LOG.error('MeshCoordinator', `Failed to build coordinator prompt: ${message}`);
@@ -34,6 +34,7 @@ import type {
34
34
  import { mergeAndNormalizePolicy } from '../repo-mesh-types.js';
35
35
  import { getDifficultyBrains } from '../config/mesh-config.js';
36
36
  import { MESH_TASK_DIFFICULTIES } from '@adhdev/mesh-shared';
37
+ import type { MagiKindPanelMap, MagiSlot, MagiTaskKind } from '@adhdev/mesh-shared';
37
38
 
38
39
  /**
39
40
  * Cheap, locally-derived "what just happened" snapshot for the coordinator
@@ -109,6 +110,14 @@ export interface CoordinatorPromptContext {
109
110
  * section.
110
111
  */
111
112
  operatingNotes?: CoordinatorOperatingNote[];
113
+ /**
114
+ * Machine-local MAGI kind-panel bindings (`~/.adhdev/meshes.json`
115
+ * `magiKindPanels`), read live at launch. Omitted / empty / all-empty →
116
+ * no "## Configured MAGI panels" section, so a mesh with no MAGI configured
117
+ * renders identically to before. Threaded in the same systematic way as the
118
+ * brain presets: read machine-local config at launch, render a pure section.
119
+ */
120
+ magiKindPanels?: MagiKindPanelMap;
112
121
  }
113
122
 
114
123
  /**
@@ -284,6 +293,11 @@ Repository: \`${mesh.repoIdentity}\`${mesh.defaultBranch ? `\nDefault branch: \`
284
293
  // ── Brain presets (difficulty → model/thinking) ──
285
294
  sections.push(buildBrainPresetsSection());
286
295
 
296
+ // ── Configured MAGI panels (machine-local magiKindPanels) — only present
297
+ // when at least one task_kind has a non-empty slot list. ──
298
+ const magiSection = buildMagiKindPanelsSection(ctx.magiKindPanels);
299
+ if (magiSection) sections.push(magiSection);
300
+
287
301
  // ── Tools ──
288
302
  sections.push(TOOLS_SECTION);
289
303
 
@@ -634,6 +648,58 @@ function buildBrainPresetsSection(): string {
634
648
  return lines.join('\n');
635
649
  }
636
650
 
651
+ /**
652
+ * Render the machine-local MAGI kind-panel bindings so the coordinator KNOWS
653
+ * which cross-verification panels (rca / design / claim_audit / freeform) are
654
+ * actually configured on this machine. Without this the coordinator only sees
655
+ * the `mesh_magi_*` tools in the static table and has no idea MAGI is set up.
656
+ *
657
+ * Pure — takes the panels map (read live at launch, mirroring how brain presets
658
+ * read getDifficultyBrains). Returns null (section OMITTED) when nothing usable
659
+ * is configured: undefined/null map, or every kind maps to an empty slot list.
660
+ * That keeps a MAGI-less mesh's prompt byte-identical to before.
661
+ */
662
+ export function buildMagiKindPanelsSection(panels: MagiKindPanelMap | undefined | null): string | null {
663
+ if (!panels) return null;
664
+ // Keep only kinds with a non-empty slot list; drop empty/undefined bindings.
665
+ const configured = (Object.entries(panels) as Array<[MagiTaskKind, MagiSlot[] | undefined]>)
666
+ .filter(([, slots]) => Array.isArray(slots) && slots.length > 0) as Array<[MagiTaskKind, MagiSlot[]]>;
667
+ if (configured.length === 0) return null;
668
+
669
+ const lines = [
670
+ '## Configured MAGI panels',
671
+ '',
672
+ 'These machine-local MAGI kind-panels are configured on this mesh — read-only cross-verification quorums:',
673
+ '',
674
+ ];
675
+
676
+ for (const [kind, slots] of configured) {
677
+ const replicaCount = slots.reduce((sum, s) => sum + (s.n && s.n > 0 ? s.n : 1), 0);
678
+ const label = replicaCount === slots.length
679
+ ? `${slots.length} ${slots.length === 1 ? 'slot' : 'slots'}`
680
+ : `${replicaCount} replicas`;
681
+ const rendered = slots.map(renderMagiSlot).join(', ');
682
+ lines.push(`- **${kind}** (${label}): ${rendered}`);
683
+ }
684
+
685
+ lines.push('');
686
+ lines.push('Use these via `mesh_magi_review` (the `task_kind` is REQUIRED — it selects BOTH the output schema and the panel). The live authoritative slot list is `mesh_magi_kind_panel_list`. MAGI worker replicas are read-only and typically do NOT have mesh MCP tools exposed, so for live timing / tool-behavior claims you MUST gather the primary evidence yourself and use MAGI only for independent source-level corroboration.');
687
+
688
+ return lines.join('\n');
689
+ }
690
+
691
+ /** Render one MAGI slot as `provider[@nodeId][ (model, tags…, xN)]`. */
692
+ function renderMagiSlot(slot: MagiSlot): string {
693
+ let s = slot.provider;
694
+ if (slot.nodeId) s += `@${slot.nodeId}`;
695
+ const extra: string[] = [];
696
+ if (slot.model) extra.push(`model: ${slot.model}`);
697
+ if (slot.capabilityTags && slot.capabilityTags.length) extra.push(`tags: ${slot.capabilityTags.join('+')}`);
698
+ if (slot.n && slot.n > 1) extra.push(`×${slot.n}`);
699
+ if (extra.length) s += ` (${extra.join(', ')})`;
700
+ return s;
701
+ }
702
+
637
703
  function buildPolicySection(policy: RepoMeshPolicy): string {
638
704
  const rules: string[] = [];
639
705
  if (policy.requirePreTaskCheckpoint) rules.push('- Create a git checkpoint **before** starting each task');