@adhdev/daemon-core 0.9.82-rc.429 → 0.9.82-rc.430
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/index.d.ts +1 -0
- package/dist/index.js +186 -132
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +185 -132
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-missions.d.ts +25 -0
- package/dist/mesh/mesh-runtime-store.d.ts +3 -0
- package/dist/repo-mesh-types.d.ts +12 -0
- package/package.json +2 -2
- package/src/commands/high-family/mesh-status.ts +32 -0
- package/src/index.ts +3 -0
- package/src/mesh/mesh-missions.ts +46 -4
- package/src/mesh/mesh-runtime-store.ts +23 -6
- package/src/repo-mesh-types.ts +12 -0
|
@@ -14,12 +14,27 @@
|
|
|
14
14
|
import { type MeshMissionStats } from './mesh-task-stats.js';
|
|
15
15
|
export type MeshMissionStatus = 'active' | 'paused' | 'completed' | 'abandoned';
|
|
16
16
|
export declare const MESH_MISSION_STATUSES: MeshMissionStatus[];
|
|
17
|
+
/**
|
|
18
|
+
* Provenance of a mission. `magi` marks an inline mission auto-created by a
|
|
19
|
+
* mesh_magi_review fan-out (one per cross-verification run). `coordinator` (the
|
|
20
|
+
* default semantic for an unstamped/legacy mission) marks a coordinator- or
|
|
21
|
+
* user-authored mission. Used to bound the accumulation of completed MAGI missions
|
|
22
|
+
* out of the default mesh_mission_list surface — see listMeshMissionSummaries.
|
|
23
|
+
*/
|
|
24
|
+
export type MeshMissionSource = 'magi' | 'coordinator';
|
|
17
25
|
export interface MeshMissionRecord {
|
|
18
26
|
id: string;
|
|
19
27
|
meshId: string;
|
|
20
28
|
title: string;
|
|
21
29
|
goal: string;
|
|
22
30
|
status: MeshMissionStatus;
|
|
31
|
+
/**
|
|
32
|
+
* Optional provenance tag. Absent on missions created before this field existed
|
|
33
|
+
* and on coordinator/user missions that don't bother stamping it — both are
|
|
34
|
+
* treated as coordinator missions (never auto-hidden). Only explicit `magi`
|
|
35
|
+
* missions are bounded out of the default list once completed.
|
|
36
|
+
*/
|
|
37
|
+
source?: MeshMissionSource;
|
|
23
38
|
createdAt: string;
|
|
24
39
|
updatedAt: string;
|
|
25
40
|
}
|
|
@@ -74,6 +89,7 @@ export declare function upsertMeshMission(meshId: string, input: {
|
|
|
74
89
|
title: string;
|
|
75
90
|
goal?: string;
|
|
76
91
|
status?: string;
|
|
92
|
+
source?: MeshMissionSource;
|
|
77
93
|
}): MeshMissionRecord;
|
|
78
94
|
export declare function getMeshMissions(meshId: string, statuses?: MeshMissionStatus[]): MeshMissionRecord[];
|
|
79
95
|
export declare function getMeshMission(meshId: string, missionId: string): MeshMissionRecord | null;
|
|
@@ -149,12 +165,21 @@ export declare function getMeshStatusMissionsCompact(meshId: string, options?: {
|
|
|
149
165
|
* coordinator can deliberately surface paused/abandoned/completed missions that
|
|
150
166
|
* the live status view would hide or truncate.
|
|
151
167
|
*
|
|
168
|
+
* MAGI bounding: by default this EXCLUDES completed MAGI missions (source==='magi'
|
|
169
|
+
* && status==='completed') — a mesh_magi_review fan-out auto-creates one inline
|
|
170
|
+
* mission per run and auto-closes it on collection, so without this they accumulate
|
|
171
|
+
* unbounded and drown out coordinator missions in the list. In-progress MAGI missions
|
|
172
|
+
* (active/paused) are still shown so a running cross-verification stays visible. Pass
|
|
173
|
+
* `includeMagi: true` to return every mission including completed MAGI ones. A mission
|
|
174
|
+
* with no `source` (legacy / coordinator) is never affected.
|
|
175
|
+
*
|
|
152
176
|
* Compact (the default) elides each goal to a capped preview + goalTruncated
|
|
153
177
|
* flag; verbose returns the full goal text. The stored goal is never mutated.
|
|
154
178
|
*/
|
|
155
179
|
export declare function listMeshMissionSummaries(meshId: string, options?: {
|
|
156
180
|
statuses?: MeshMissionStatus[];
|
|
157
181
|
verbose?: boolean;
|
|
182
|
+
includeMagi?: boolean;
|
|
158
183
|
}): MeshMissionSummary[] | MeshMissionSlimSummary[];
|
|
159
184
|
/**
|
|
160
185
|
* M3-3: render active missions as a prompt section for {{mission}}.
|
|
@@ -405,6 +405,7 @@ export declare class MeshRuntimeStore {
|
|
|
405
405
|
title: string;
|
|
406
406
|
goal?: string;
|
|
407
407
|
status?: string;
|
|
408
|
+
source?: string;
|
|
408
409
|
}): void;
|
|
409
410
|
getMission(meshId: string, missionId: string): {
|
|
410
411
|
id: string;
|
|
@@ -412,6 +413,7 @@ export declare class MeshRuntimeStore {
|
|
|
412
413
|
title: string;
|
|
413
414
|
goal: string;
|
|
414
415
|
status: string;
|
|
416
|
+
source?: string;
|
|
415
417
|
createdAt: string;
|
|
416
418
|
updatedAt: string;
|
|
417
419
|
} | null;
|
|
@@ -421,6 +423,7 @@ export declare class MeshRuntimeStore {
|
|
|
421
423
|
title: string;
|
|
422
424
|
goal: string;
|
|
423
425
|
status: string;
|
|
426
|
+
source?: string;
|
|
424
427
|
createdAt: string;
|
|
425
428
|
updatedAt: string;
|
|
426
429
|
}>;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
|
|
14
14
|
import type { MeshMissionSummary, MeshMissionSlimSummary } from './mesh/mesh-missions.js';
|
|
15
|
+
import type { MeshMagiActivitySummary } from './mesh/mesh-magi-status.js';
|
|
15
16
|
import type { MagiPanelMap } from '@adhdev/mesh-shared';
|
|
16
17
|
export interface RepoMesh {
|
|
17
18
|
id: string;
|
|
@@ -667,6 +668,17 @@ export interface RepoMeshStatus {
|
|
|
667
668
|
* an optional `stats` operational rollup (durations / retries).
|
|
668
669
|
*/
|
|
669
670
|
missions?: (MeshMissionSummary | MeshMissionSlimSummary)[];
|
|
671
|
+
/**
|
|
672
|
+
* MAGI cross-verification activity, reconstructed from the mesh ledger
|
|
673
|
+
* (magi_dispatched / magi_synthesis entries) and folded in so the dashboard's
|
|
674
|
+
* MAGI surface can read synthesis output — needs_verification counts, the
|
|
675
|
+
* independence banner, git skew, and a bounded needs_verification preview —
|
|
676
|
+
* without re-running collection. Running groups are always included; synthesized
|
|
677
|
+
* groups are bounded to recent ones (see summarizeMeshMagiActivity). Omitted by
|
|
678
|
+
* daemons predating the exposure and when no MAGI run is present; treat as
|
|
679
|
+
* optional. Mirrors the MCP `mesh_status` tool's `magiActivity` field.
|
|
680
|
+
*/
|
|
681
|
+
magiActivity?: MeshMagiActivitySummary[];
|
|
670
682
|
}
|
|
671
683
|
export type { RepoMeshSessionStatus } from '@adhdev/mesh-shared';
|
|
672
684
|
import type { RepoMeshSessionStatus } from '@adhdev/mesh-shared';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "0.9.82-rc.
|
|
3
|
+
"version": "0.9.82-rc.430",
|
|
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",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"author": "vilmire",
|
|
47
47
|
"license": "AGPL-3.0-or-later",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@adhdev/mesh-shared": "0.9.82-rc.
|
|
49
|
+
"@adhdev/mesh-shared": "0.9.82-rc.430",
|
|
50
50
|
"@adhdev/session-host-core": "*",
|
|
51
51
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
52
52
|
"ajv": "^8.20.0",
|
|
@@ -494,6 +494,24 @@ export const meshStatusHandlers: Record<string, HighFamilyHandler> = {
|
|
|
494
494
|
// returned here (live + capped history), so the cost stays linear
|
|
495
495
|
// in visible missions rather than the whole mesh history.
|
|
496
496
|
const missions = getMeshStatusMissionSummaries(meshId, { verbose: verboseMissions, withStats: true });
|
|
497
|
+
|
|
498
|
+
// FIX C-backend: fold persisted MAGI cross-verification activity into the
|
|
499
|
+
// dashboard mesh_status payload so the web MAGI surface (extractMagiActivity)
|
|
500
|
+
// can read synthesis output — needs_verification counts, the independence
|
|
501
|
+
// banner, git skew, and a bounded needs_verification preview — without
|
|
502
|
+
// re-running collection. Mirrors the MCP mesh_status tool
|
|
503
|
+
// (mesh-tools-status.ts buildMeshMagiActivity / summarizeMeshMagiActivity).
|
|
504
|
+
// Read magi_dispatched/magi_synthesis entries over a wider tail than the 20
|
|
505
|
+
// rendered above (MAGI events are sparse — a 20-entry tail routinely misses
|
|
506
|
+
// the dispatch/synthesis pair). Compact (the default) folds synthesized groups
|
|
507
|
+
// to a bounded recent set + a count summary; verbose carries the full list.
|
|
508
|
+
const { buildMeshMagiActivity, summarizeMeshMagiActivity } = await import('../../mesh/mesh-magi-status.js');
|
|
509
|
+
const magiLedgerEntries = readLedgerEntries(meshId, { kind: ['magi_dispatched', 'magi_synthesis'], tail: 200 });
|
|
510
|
+
const magiActivity = buildMeshMagiActivity({ meshId, ledgerEntries: magiLedgerEntries });
|
|
511
|
+
let magiActivityFold: ReturnType<typeof summarizeMeshMagiActivity> | undefined;
|
|
512
|
+
if (magiActivity.length > 0 && !verboseMissions) {
|
|
513
|
+
magiActivityFold = summarizeMeshMagiActivity(magiActivity);
|
|
514
|
+
}
|
|
497
515
|
const statusResult = {
|
|
498
516
|
success: true,
|
|
499
517
|
meshId: mesh.id,
|
|
@@ -550,6 +568,20 @@ export const meshStatusHandlers: Record<string, HighFamilyHandler> = {
|
|
|
550
568
|
queue: { tasks: queue, summary: queueSummary },
|
|
551
569
|
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|
|
552
570
|
...(missions.length > 0 ? { missions } : {}),
|
|
571
|
+
// Compact (default): bounded folded groups + a status-count summary.
|
|
572
|
+
// Verbose: the full reconstructed activity list. Mirrors the MCP tool.
|
|
573
|
+
...(magiActivity.length > 0
|
|
574
|
+
? (magiActivityFold
|
|
575
|
+
? {
|
|
576
|
+
...(magiActivityFold.groups.length > 0 ? { magiActivity: magiActivityFold.groups } : {}),
|
|
577
|
+
magiActivitySummary: {
|
|
578
|
+
total: magiActivityFold.total,
|
|
579
|
+
byStatus: magiActivityFold.byStatus,
|
|
580
|
+
...(magiActivityFold.staleSynthesized > 0 ? { staleSynthesized: magiActivityFold.staleSynthesized } : {}),
|
|
581
|
+
},
|
|
582
|
+
}
|
|
583
|
+
: { magiActivity })
|
|
584
|
+
: {}),
|
|
553
585
|
...(asyncRefineJobs.length > 0 ? { asyncRefineJobs } : {}),
|
|
554
586
|
...(historicalSessions ? { historicalSessions } : {}),
|
|
555
587
|
...(pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {}),
|
package/src/index.ts
CHANGED
|
@@ -207,6 +207,9 @@ export type {
|
|
|
207
207
|
MagiResponseSource, MagiReplicaGitRef, MagiGitSkew, MagiSynthesizedResponse,
|
|
208
208
|
MagiClusterCategory, MagiClusterMember, MagiClaimCluster, MagiSynthesis,
|
|
209
209
|
} from '@adhdev/mesh-shared';
|
|
210
|
+
// Value re-export: per-replica raw-answer truncation cap (used by the mcp-server
|
|
211
|
+
// collection path, which depends only on @adhdev/daemon-core).
|
|
212
|
+
export { MAGI_RAW_ANSWER_CAP } from '@adhdev/mesh-shared';
|
|
210
213
|
|
|
211
214
|
// ── Mesh shared daemon-id / node-id helpers (re-export so external tooling —
|
|
212
215
|
// e.g. the mcp-server, which depends only on @adhdev/daemon-core — can
|
|
@@ -34,12 +34,28 @@ export type MeshMissionStatus = 'active' | 'paused' | 'completed' | 'abandoned';
|
|
|
34
34
|
|
|
35
35
|
export const MESH_MISSION_STATUSES: MeshMissionStatus[] = ['active', 'paused', 'completed', 'abandoned'];
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Provenance of a mission. `magi` marks an inline mission auto-created by a
|
|
39
|
+
* mesh_magi_review fan-out (one per cross-verification run). `coordinator` (the
|
|
40
|
+
* default semantic for an unstamped/legacy mission) marks a coordinator- or
|
|
41
|
+
* user-authored mission. Used to bound the accumulation of completed MAGI missions
|
|
42
|
+
* out of the default mesh_mission_list surface — see listMeshMissionSummaries.
|
|
43
|
+
*/
|
|
44
|
+
export type MeshMissionSource = 'magi' | 'coordinator';
|
|
45
|
+
|
|
37
46
|
export interface MeshMissionRecord {
|
|
38
47
|
id: string;
|
|
39
48
|
meshId: string;
|
|
40
49
|
title: string;
|
|
41
50
|
goal: string;
|
|
42
51
|
status: MeshMissionStatus;
|
|
52
|
+
/**
|
|
53
|
+
* Optional provenance tag. Absent on missions created before this field existed
|
|
54
|
+
* and on coordinator/user missions that don't bother stamping it — both are
|
|
55
|
+
* treated as coordinator missions (never auto-hidden). Only explicit `magi`
|
|
56
|
+
* missions are bounded out of the default list once completed.
|
|
57
|
+
*/
|
|
58
|
+
source?: MeshMissionSource;
|
|
43
59
|
createdAt: string;
|
|
44
60
|
updatedAt: string;
|
|
45
61
|
}
|
|
@@ -101,11 +117,16 @@ function normalizeMissionStatus(value: unknown): MeshMissionStatus {
|
|
|
101
117
|
: 'active';
|
|
102
118
|
}
|
|
103
119
|
|
|
120
|
+
function normalizeMissionSource(value: unknown): MeshMissionSource | undefined {
|
|
121
|
+
return value === 'magi' || value === 'coordinator' ? value : undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
104
124
|
export function upsertMeshMission(meshId: string, input: {
|
|
105
125
|
id?: string;
|
|
106
126
|
title: string;
|
|
107
127
|
goal?: string;
|
|
108
128
|
status?: string;
|
|
129
|
+
source?: MeshMissionSource;
|
|
109
130
|
}): MeshMissionRecord {
|
|
110
131
|
const title = typeof input.title === 'string' ? input.title.trim() : '';
|
|
111
132
|
if (!title) throw new Error('mission_title_required: a mission needs a non-empty title');
|
|
@@ -123,10 +144,18 @@ export function upsertMeshMission(meshId: string, input: {
|
|
|
123
144
|
title,
|
|
124
145
|
goal: typeof input.goal === 'string' ? input.goal : existing?.goal ?? '',
|
|
125
146
|
status: normalizeMissionStatus(input.status ?? existing?.status),
|
|
147
|
+
// source is write-once: only forwarded when the caller supplies one. The
|
|
148
|
+
// store COALESCEs it against the existing value, so a later status/goal
|
|
149
|
+
// upsert that omits source never clears a previously-stamped tag.
|
|
150
|
+
...(input.source ? { source: input.source } : {}),
|
|
126
151
|
};
|
|
127
152
|
store.upsertMission(record);
|
|
128
153
|
const saved = store.getMission(meshId, id)!;
|
|
129
|
-
const result: MeshMissionRecord = {
|
|
154
|
+
const result: MeshMissionRecord = {
|
|
155
|
+
...saved,
|
|
156
|
+
status: normalizeMissionStatus(saved.status),
|
|
157
|
+
source: normalizeMissionSource(saved.source),
|
|
158
|
+
};
|
|
130
159
|
|
|
131
160
|
// Mission audit trail: record this mutation in the mesh ledger so mission
|
|
132
161
|
// lifecycle (create, goal rewrite, status transition) is auditable alongside
|
|
@@ -201,12 +230,12 @@ function appendMissionLedgerEntries(
|
|
|
201
230
|
|
|
202
231
|
export function getMeshMissions(meshId: string, statuses?: MeshMissionStatus[]): MeshMissionRecord[] {
|
|
203
232
|
return MeshRuntimeStore.getInstance().getMissions(meshId, statuses)
|
|
204
|
-
.map(m => ({ ...m, status: normalizeMissionStatus(m.status) }));
|
|
233
|
+
.map(m => ({ ...m, status: normalizeMissionStatus(m.status), source: normalizeMissionSource(m.source) }));
|
|
205
234
|
}
|
|
206
235
|
|
|
207
236
|
export function getMeshMission(meshId: string, missionId: string): MeshMissionRecord | null {
|
|
208
237
|
const record = MeshRuntimeStore.getInstance().getMission(meshId, missionId);
|
|
209
|
-
return record ? { ...record, status: normalizeMissionStatus(record.status) } : null;
|
|
238
|
+
return record ? { ...record, status: normalizeMissionStatus(record.status), source: normalizeMissionSource(record.source) } : null;
|
|
210
239
|
}
|
|
211
240
|
|
|
212
241
|
/** Aggregate task statuses for a mission at query time (no stored progress). */
|
|
@@ -367,15 +396,28 @@ export function getMeshStatusMissionsCompact(
|
|
|
367
396
|
* coordinator can deliberately surface paused/abandoned/completed missions that
|
|
368
397
|
* the live status view would hide or truncate.
|
|
369
398
|
*
|
|
399
|
+
* MAGI bounding: by default this EXCLUDES completed MAGI missions (source==='magi'
|
|
400
|
+
* && status==='completed') — a mesh_magi_review fan-out auto-creates one inline
|
|
401
|
+
* mission per run and auto-closes it on collection, so without this they accumulate
|
|
402
|
+
* unbounded and drown out coordinator missions in the list. In-progress MAGI missions
|
|
403
|
+
* (active/paused) are still shown so a running cross-verification stays visible. Pass
|
|
404
|
+
* `includeMagi: true` to return every mission including completed MAGI ones. A mission
|
|
405
|
+
* with no `source` (legacy / coordinator) is never affected.
|
|
406
|
+
*
|
|
370
407
|
* Compact (the default) elides each goal to a capped preview + goalTruncated
|
|
371
408
|
* flag; verbose returns the full goal text. The stored goal is never mutated.
|
|
372
409
|
*/
|
|
373
410
|
export function listMeshMissionSummaries(
|
|
374
411
|
meshId: string,
|
|
375
|
-
options?: { statuses?: MeshMissionStatus[]; verbose?: boolean },
|
|
412
|
+
options?: { statuses?: MeshMissionStatus[]; verbose?: boolean; includeMagi?: boolean },
|
|
376
413
|
): MeshMissionSummary[] | MeshMissionSlimSummary[] {
|
|
377
414
|
const statuses = options?.statuses && options.statuses.length > 0 ? options.statuses : undefined;
|
|
415
|
+
const includeMagi = options?.includeMagi === true;
|
|
378
416
|
const missions = getMeshMissions(meshId, statuses)
|
|
417
|
+
// Bound completed-MAGI accumulation by default. Only a mission EXPLICITLY
|
|
418
|
+
// tagged source==='magi' AND completed is hidden — coordinator/legacy
|
|
419
|
+
// (source undefined) missions and in-progress MAGI missions always pass.
|
|
420
|
+
.filter(m => includeMagi || !(m.source === 'magi' && m.status === 'completed'))
|
|
379
421
|
.sort((a, b) => (b.updatedAt || '').localeCompare(a.updatedAt || ''));
|
|
380
422
|
const full = missions.map(mission => summarizeMeshMission(meshId, mission));
|
|
381
423
|
return options?.verbose ? full : full.map(summary => slimMissionSummary(summary));
|
|
@@ -298,6 +298,7 @@ export class MeshRuntimeStore {
|
|
|
298
298
|
title TEXT NOT NULL,
|
|
299
299
|
goal TEXT NOT NULL DEFAULT '',
|
|
300
300
|
status TEXT NOT NULL DEFAULT 'active',
|
|
301
|
+
source TEXT,
|
|
301
302
|
created_at TEXT NOT NULL,
|
|
302
303
|
updated_at TEXT NOT NULL
|
|
303
304
|
);
|
|
@@ -373,6 +374,15 @@ export class MeshRuntimeStore {
|
|
|
373
374
|
);
|
|
374
375
|
`);
|
|
375
376
|
}
|
|
377
|
+
|
|
378
|
+
// 3. mesh_missions.source: nullable provenance tag ('magi' | 'coordinator').
|
|
379
|
+
// Pre-existing rows keep source NULL — listMeshMissionSummaries treats a
|
|
380
|
+
// NULL/absent source as a coordinator mission (never auto-hidden), so the
|
|
381
|
+
// completed-MAGI bounding only ever affects rows explicitly stamped 'magi'.
|
|
382
|
+
const missionCols = this.tableColumns('mesh_missions');
|
|
383
|
+
if (!missionCols.has('source')) {
|
|
384
|
+
this.db.exec(`ALTER TABLE mesh_missions ADD COLUMN source TEXT`);
|
|
385
|
+
}
|
|
376
386
|
} catch (err: any) {
|
|
377
387
|
// Best-effort: a failed isolation migration must not brick the store. The
|
|
378
388
|
// CREATE-TABLE definitions above already carry the new schema for fresh DBs;
|
|
@@ -1742,15 +1752,21 @@ export class MeshRuntimeStore {
|
|
|
1742
1752
|
title: string;
|
|
1743
1753
|
goal?: string;
|
|
1744
1754
|
status?: string;
|
|
1755
|
+
source?: string;
|
|
1745
1756
|
}): void {
|
|
1746
1757
|
const now = new Date().toISOString();
|
|
1758
|
+
// `source` is a write-once provenance tag: on conflict we only overwrite it
|
|
1759
|
+
// with a non-null incoming value (COALESCE(excluded, existing)), so a later
|
|
1760
|
+
// status/goal upsert that omits source never clears a previously-stamped
|
|
1761
|
+
// 'magi'/'coordinator' tag.
|
|
1747
1762
|
this.db.prepare(
|
|
1748
|
-
`INSERT INTO mesh_missions (id, mesh_id, title, goal, status, created_at, updated_at)
|
|
1749
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1763
|
+
`INSERT INTO mesh_missions (id, mesh_id, title, goal, status, source, created_at, updated_at)
|
|
1764
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
1750
1765
|
ON CONFLICT(id) DO UPDATE SET
|
|
1751
1766
|
title = excluded.title,
|
|
1752
1767
|
goal = excluded.goal,
|
|
1753
1768
|
status = excluded.status,
|
|
1769
|
+
source = COALESCE(excluded.source, mesh_missions.source),
|
|
1754
1770
|
updated_at = excluded.updated_at`
|
|
1755
1771
|
).run(
|
|
1756
1772
|
mission.id,
|
|
@@ -1758,21 +1774,22 @@ export class MeshRuntimeStore {
|
|
|
1758
1774
|
mission.title,
|
|
1759
1775
|
mission.goal ?? '',
|
|
1760
1776
|
mission.status ?? 'active',
|
|
1777
|
+
mission.source ?? null,
|
|
1761
1778
|
now,
|
|
1762
1779
|
now,
|
|
1763
1780
|
);
|
|
1764
1781
|
this.maybeCheckpointWal();
|
|
1765
1782
|
}
|
|
1766
1783
|
|
|
1767
|
-
getMission(meshId: string, missionId: string): { id: string; meshId: string; title: string; goal: string; status: string; createdAt: string; updatedAt: string } | null {
|
|
1784
|
+
getMission(meshId: string, missionId: string): { id: string; meshId: string; title: string; goal: string; status: string; source?: string; createdAt: string; updatedAt: string } | null {
|
|
1768
1785
|
const row = this.db.prepare(
|
|
1769
1786
|
'SELECT * FROM mesh_missions WHERE mesh_id = ? AND id = ?'
|
|
1770
1787
|
).get(meshId, missionId) as Record<string, string> | undefined;
|
|
1771
1788
|
if (!row) return null;
|
|
1772
|
-
return { id: row.id, meshId: row.mesh_id, title: row.title, goal: row.goal, status: row.status, createdAt: row.created_at, updatedAt: row.updated_at };
|
|
1789
|
+
return { id: row.id, meshId: row.mesh_id, title: row.title, goal: row.goal, status: row.status, source: row.source ?? undefined, createdAt: row.created_at, updatedAt: row.updated_at };
|
|
1773
1790
|
}
|
|
1774
1791
|
|
|
1775
|
-
getMissions(meshId: string, statuses?: string[]): Array<{ id: string; meshId: string; title: string; goal: string; status: string; createdAt: string; updatedAt: string }> {
|
|
1792
|
+
getMissions(meshId: string, statuses?: string[]): Array<{ id: string; meshId: string; title: string; goal: string; status: string; source?: string; createdAt: string; updatedAt: string }> {
|
|
1776
1793
|
let rows: Array<Record<string, string>>;
|
|
1777
1794
|
if (statuses?.length) {
|
|
1778
1795
|
const placeholders = statuses.map(() => '?').join(', ');
|
|
@@ -1784,7 +1801,7 @@ export class MeshRuntimeStore {
|
|
|
1784
1801
|
'SELECT * FROM mesh_missions WHERE mesh_id = ? ORDER BY updated_at DESC'
|
|
1785
1802
|
).all(meshId) as Array<Record<string, string>>;
|
|
1786
1803
|
}
|
|
1787
|
-
return rows.map(row => ({ id: row.id, meshId: row.mesh_id, title: row.title, goal: row.goal, status: row.status, createdAt: row.created_at, updatedAt: row.updated_at }));
|
|
1804
|
+
return rows.map(row => ({ id: row.id, meshId: row.mesh_id, title: row.title, goal: row.goal, status: row.status, source: row.source ?? undefined, createdAt: row.created_at, updatedAt: row.updated_at }));
|
|
1788
1805
|
}
|
|
1789
1806
|
|
|
1790
1807
|
/** Remove all missions for a mesh — mesh deletion / test cleanup. */
|
package/src/repo-mesh-types.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
|
|
15
15
|
import type { MeshMissionSummary, MeshMissionSlimSummary } from './mesh/mesh-missions.js';
|
|
16
|
+
import type { MeshMagiActivitySummary } from './mesh/mesh-magi-status.js';
|
|
16
17
|
import type { MagiPanelMap } from '@adhdev/mesh-shared';
|
|
17
18
|
|
|
18
19
|
// ─── Core Mesh Types ────────────────────────────
|
|
@@ -944,6 +945,17 @@ export interface RepoMeshStatus {
|
|
|
944
945
|
* an optional `stats` operational rollup (durations / retries).
|
|
945
946
|
*/
|
|
946
947
|
missions?: (MeshMissionSummary | MeshMissionSlimSummary)[];
|
|
948
|
+
/**
|
|
949
|
+
* MAGI cross-verification activity, reconstructed from the mesh ledger
|
|
950
|
+
* (magi_dispatched / magi_synthesis entries) and folded in so the dashboard's
|
|
951
|
+
* MAGI surface can read synthesis output — needs_verification counts, the
|
|
952
|
+
* independence banner, git skew, and a bounded needs_verification preview —
|
|
953
|
+
* without re-running collection. Running groups are always included; synthesized
|
|
954
|
+
* groups are bounded to recent ones (see summarizeMeshMagiActivity). Omitted by
|
|
955
|
+
* daemons predating the exposure and when no MAGI run is present; treat as
|
|
956
|
+
* optional. Mirrors the MCP `mesh_status` tool's `magiActivity` field.
|
|
957
|
+
*/
|
|
958
|
+
magiActivity?: MeshMagiActivitySummary[];
|
|
947
959
|
}
|
|
948
960
|
|
|
949
961
|
// RepoMeshSessionStatus shape now lives in @adhdev/mesh-shared (shared with
|