@goondocks/myco 0.21.1 → 0.21.2
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/{agent-eval-YK2VP2S4.js → agent-eval-2MQKTXX3.js} +4 -4
- package/dist/{agent-run-GEJBD2YD.js → agent-run-XJBTSVJR.js} +4 -4
- package/dist/{agent-tasks-5XSRGTRX.js → agent-tasks-7MWBZOC7.js} +4 -4
- package/dist/{chunk-VRI56337.js → chunk-4D22KTXY.js} +2 -2
- package/dist/{chunk-KTTSXYEK.js → chunk-6FBLL7MD.js} +8 -2
- package/dist/chunk-6FBLL7MD.js.map +1 -0
- package/dist/{chunk-N7Z3LUEZ.js → chunk-DBBO6FHE.js} +2 -10
- package/dist/{chunk-N7Z3LUEZ.js.map → chunk-DBBO6FHE.js.map} +1 -1
- package/dist/{chunk-EEOJWLMP.js → chunk-DMPCC7V6.js} +15 -3
- package/dist/chunk-DMPCC7V6.js.map +1 -0
- package/dist/{chunk-XL75KZGI.js → chunk-EKZG2MCD.js} +7 -3
- package/dist/chunk-EKZG2MCD.js.map +1 -0
- package/dist/{chunk-X2IRGXGF.js → chunk-HCT7RMM2.js} +154 -24
- package/dist/chunk-HCT7RMM2.js.map +1 -0
- package/dist/{chunk-NFO7BRCO.js → chunk-IMW5TJ3O.js} +5 -4
- package/dist/chunk-IMW5TJ3O.js.map +1 -0
- package/dist/{chunk-OZ3FBAK5.js → chunk-TFRUDNLI.js} +2 -2
- package/dist/{chunk-6ALVMIB4.js → chunk-TMAXWERS.js} +85 -2
- package/dist/chunk-TMAXWERS.js.map +1 -0
- package/dist/{chunk-QDLVIW2O.js → chunk-W5L5IHP5.js} +2 -2
- package/dist/{chunk-ENZR5NG7.js → chunk-Z55WGA2J.js} +2 -2
- package/dist/{cli-HSLIG7EX.js → cli-DDHTHU2J.js} +35 -35
- package/dist/{client-Z43DNLJH.js → client-PQU53UQU.js} +5 -3
- package/dist/{doctor-HJCWHAU4.js → doctor-QK6KFY6H.js} +4 -4
- package/dist/{executor-DO6QFC6G.js → executor-FJCMNSXM.js} +5 -5
- package/dist/{init-4KVK7W2E.js → init-GQPD6HHX.js} +5 -5
- package/dist/{main-4J4QZZTZ.js → main-4HKTZFIM.js} +365 -142
- package/dist/main-4HKTZFIM.js.map +1 -0
- package/dist/{open-7TXJQM3H.js → open-3P3DDAOA.js} +4 -4
- package/dist/{post-compact-7AEFVCZS.js → post-compact-QA5LME2J.js} +4 -4
- package/dist/{post-tool-use-TZINWWDH.js → post-tool-use-QRZMPNYL.js} +3 -3
- package/dist/{post-tool-use-failure-TCFEU2GI.js → post-tool-use-failure-XNHIKBZG.js} +4 -4
- package/dist/{pre-compact-LO2VZCGR.js → pre-compact-HDV6X5QM.js} +4 -4
- package/dist/{remove-F77AAALE.js → remove-USQDLGTJ.js} +4 -4
- package/dist/{restart-UEFDPMLT.js → restart-FQLZE2TW.js} +5 -5
- package/dist/{search-NHNVUAQQ.js → search-5COKV6TD.js} +4 -4
- package/dist/{server-AZJSTQEK.js → server-KRMBRW4T.js} +22 -6
- package/dist/{server-AZJSTQEK.js.map → server-KRMBRW4T.js.map} +1 -1
- package/dist/{session-3HLC5KOD.js → session-NJCUW3OX.js} +4 -4
- package/dist/{session-end-FS46UARX.js → session-end-XD27GRYF.js} +3 -3
- package/dist/{session-start-46KPFV2H.js → session-start-RDTXUSYL.js} +7 -7
- package/dist/{setup-llm-JMWSNQ2C.js → setup-llm-FYPPJI6W.js} +4 -4
- package/dist/src/agent/definitions/tasks/skill-evolve.yaml +4 -4
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/post-tool-use.js +1 -1
- package/dist/src/hooks/session-end.js +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +1 -1
- package/dist/src/hooks/user-prompt-submit.js +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/dist/src/symbionts/templates/opencode/plugin.ts +41 -1
- package/dist/src/symbionts/templates/pi/plugin.ts +12 -1
- package/dist/{stats-MKMETHMA.js → stats-JCLZLA5G.js} +5 -5
- package/dist/{stop-OUEX6KA4.js → stop-B7XCXEM5.js} +3 -3
- package/dist/{stop-failure-2BWVNZEG.js → stop-failure-R6QZCUOZ.js} +4 -4
- package/dist/{subagent-start-J4VV6DEE.js → subagent-start-N7A622F3.js} +4 -4
- package/dist/{subagent-stop-JMLVEPIA.js → subagent-stop-SVOG5MZJ.js} +4 -4
- package/dist/{task-completed-65CHMMKA.js → task-completed-3DL5LJXF.js} +4 -4
- package/dist/{team-U2LDKIS4.js → team-VJ3M263F.js} +2 -2
- package/dist/ui/assets/{index-BUGor9dk.js → index-O1kNWlWM.js} +119 -119
- package/dist/ui/assets/index-z2Jm8i4A.css +1 -0
- package/dist/ui/index.html +2 -2
- package/dist/{update-ZSHVXWSQ.js → update-TVXAUJMZ.js} +42 -8
- package/dist/update-TVXAUJMZ.js.map +1 -0
- package/dist/{user-prompt-submit-APMO6FVU.js → user-prompt-submit-KYO2VGLB.js} +7 -6
- package/dist/user-prompt-submit-KYO2VGLB.js.map +1 -0
- package/dist/{version-TXPPS3L5.js → version-LDFEALUJ.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-6ALVMIB4.js.map +0 -1
- package/dist/chunk-EEOJWLMP.js.map +0 -1
- package/dist/chunk-KTTSXYEK.js.map +0 -1
- package/dist/chunk-NFO7BRCO.js.map +0 -1
- package/dist/chunk-X2IRGXGF.js.map +0 -1
- package/dist/chunk-XL75KZGI.js.map +0 -1
- package/dist/main-4J4QZZTZ.js.map +0 -1
- package/dist/ui/assets/index-_OP4ifzH.css +0 -1
- package/dist/update-ZSHVXWSQ.js.map +0 -1
- package/dist/user-prompt-submit-APMO6FVU.js.map +0 -1
- /package/dist/{agent-eval-YK2VP2S4.js.map → agent-eval-2MQKTXX3.js.map} +0 -0
- /package/dist/{agent-run-GEJBD2YD.js.map → agent-run-XJBTSVJR.js.map} +0 -0
- /package/dist/{agent-tasks-5XSRGTRX.js.map → agent-tasks-7MWBZOC7.js.map} +0 -0
- /package/dist/{chunk-VRI56337.js.map → chunk-4D22KTXY.js.map} +0 -0
- /package/dist/{chunk-OZ3FBAK5.js.map → chunk-TFRUDNLI.js.map} +0 -0
- /package/dist/{chunk-QDLVIW2O.js.map → chunk-W5L5IHP5.js.map} +0 -0
- /package/dist/{chunk-ENZR5NG7.js.map → chunk-Z55WGA2J.js.map} +0 -0
- /package/dist/{cli-HSLIG7EX.js.map → cli-DDHTHU2J.js.map} +0 -0
- /package/dist/{client-Z43DNLJH.js.map → client-PQU53UQU.js.map} +0 -0
- /package/dist/{doctor-HJCWHAU4.js.map → doctor-QK6KFY6H.js.map} +0 -0
- /package/dist/{executor-DO6QFC6G.js.map → executor-FJCMNSXM.js.map} +0 -0
- /package/dist/{init-4KVK7W2E.js.map → init-GQPD6HHX.js.map} +0 -0
- /package/dist/{open-7TXJQM3H.js.map → open-3P3DDAOA.js.map} +0 -0
- /package/dist/{post-compact-7AEFVCZS.js.map → post-compact-QA5LME2J.js.map} +0 -0
- /package/dist/{post-tool-use-TZINWWDH.js.map → post-tool-use-QRZMPNYL.js.map} +0 -0
- /package/dist/{post-tool-use-failure-TCFEU2GI.js.map → post-tool-use-failure-XNHIKBZG.js.map} +0 -0
- /package/dist/{pre-compact-LO2VZCGR.js.map → pre-compact-HDV6X5QM.js.map} +0 -0
- /package/dist/{remove-F77AAALE.js.map → remove-USQDLGTJ.js.map} +0 -0
- /package/dist/{restart-UEFDPMLT.js.map → restart-FQLZE2TW.js.map} +0 -0
- /package/dist/{search-NHNVUAQQ.js.map → search-5COKV6TD.js.map} +0 -0
- /package/dist/{session-3HLC5KOD.js.map → session-NJCUW3OX.js.map} +0 -0
- /package/dist/{session-end-FS46UARX.js.map → session-end-XD27GRYF.js.map} +0 -0
- /package/dist/{session-start-46KPFV2H.js.map → session-start-RDTXUSYL.js.map} +0 -0
- /package/dist/{setup-llm-JMWSNQ2C.js.map → setup-llm-FYPPJI6W.js.map} +0 -0
- /package/dist/{stats-MKMETHMA.js.map → stats-JCLZLA5G.js.map} +0 -0
- /package/dist/{stop-OUEX6KA4.js.map → stop-B7XCXEM5.js.map} +0 -0
- /package/dist/{stop-failure-2BWVNZEG.js.map → stop-failure-R6QZCUOZ.js.map} +0 -0
- /package/dist/{subagent-start-J4VV6DEE.js.map → subagent-start-N7A622F3.js.map} +0 -0
- /package/dist/{subagent-stop-JMLVEPIA.js.map → subagent-stop-SVOG5MZJ.js.map} +0 -0
- /package/dist/{task-completed-65CHMMKA.js.map → task-completed-3DL5LJXF.js.map} +0 -0
- /package/dist/{team-U2LDKIS4.js.map → team-VJ3M263F.js.map} +0 -0
- /package/dist/{version-TXPPS3L5.js.map → version-LDFEALUJ.js.map} +0 -0
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import "./chunk-LQIPXVDH.js";
|
|
9
9
|
import {
|
|
10
10
|
connectToDaemon
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-W5L5IHP5.js";
|
|
12
12
|
import "./chunk-SAKJMNSR.js";
|
|
13
13
|
import "./chunk-OTQH5KZW.js";
|
|
14
14
|
import "./chunk-X3IGT5RV.js";
|
|
@@ -16,8 +16,8 @@ import "./chunk-53RPGOEN.js";
|
|
|
16
16
|
import "./chunk-OUJSQSKE.js";
|
|
17
17
|
import "./chunk-POEPHBQK.js";
|
|
18
18
|
import "./chunk-MYX5NCRH.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-6FBLL7MD.js";
|
|
20
|
+
import "./chunk-Z55WGA2J.js";
|
|
21
21
|
import "./chunk-LPUQPDC2.js";
|
|
22
22
|
import "./chunk-6C6QZ4PM.js";
|
|
23
23
|
import "./chunk-UUHLLQXO.js";
|
|
@@ -353,4 +353,4 @@ export {
|
|
|
353
353
|
parsePhaseArg,
|
|
354
354
|
run
|
|
355
355
|
};
|
|
356
|
-
//# sourceMappingURL=agent-eval-
|
|
356
|
+
//# sourceMappingURL=agent-eval-2MQKTXX3.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
connectToDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-W5L5IHP5.js";
|
|
5
5
|
import "./chunk-SAKJMNSR.js";
|
|
6
6
|
import "./chunk-OTQH5KZW.js";
|
|
7
7
|
import "./chunk-X3IGT5RV.js";
|
|
@@ -9,8 +9,8 @@ import "./chunk-53RPGOEN.js";
|
|
|
9
9
|
import "./chunk-OUJSQSKE.js";
|
|
10
10
|
import "./chunk-POEPHBQK.js";
|
|
11
11
|
import "./chunk-MYX5NCRH.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-6FBLL7MD.js";
|
|
13
|
+
import "./chunk-Z55WGA2J.js";
|
|
14
14
|
import "./chunk-LPUQPDC2.js";
|
|
15
15
|
import "./chunk-6C6QZ4PM.js";
|
|
16
16
|
import "./chunk-UUHLLQXO.js";
|
|
@@ -38,4 +38,4 @@ async function run(args, vaultDir) {
|
|
|
38
38
|
export {
|
|
39
39
|
run
|
|
40
40
|
};
|
|
41
|
-
//# sourceMappingURL=agent-run-
|
|
41
|
+
//# sourceMappingURL=agent-run-XJBTSVJR.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
connectToDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-W5L5IHP5.js";
|
|
5
5
|
import "./chunk-SAKJMNSR.js";
|
|
6
6
|
import "./chunk-OTQH5KZW.js";
|
|
7
7
|
import "./chunk-X3IGT5RV.js";
|
|
@@ -9,8 +9,8 @@ import "./chunk-53RPGOEN.js";
|
|
|
9
9
|
import "./chunk-OUJSQSKE.js";
|
|
10
10
|
import "./chunk-POEPHBQK.js";
|
|
11
11
|
import "./chunk-MYX5NCRH.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-6FBLL7MD.js";
|
|
13
|
+
import "./chunk-Z55WGA2J.js";
|
|
14
14
|
import "./chunk-LPUQPDC2.js";
|
|
15
15
|
import "./chunk-6C6QZ4PM.js";
|
|
16
16
|
import "./chunk-UUHLLQXO.js";
|
|
@@ -184,4 +184,4 @@ async function run(args, vaultDir) {
|
|
|
184
184
|
export {
|
|
185
185
|
run
|
|
186
186
|
};
|
|
187
|
-
//# sourceMappingURL=agent-tasks-
|
|
187
|
+
//# sourceMappingURL=agent-tasks-7MWBZOC7.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
isProcessAlive
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-W5L5IHP5.js";
|
|
5
5
|
import {
|
|
6
6
|
loadMergedConfig
|
|
7
7
|
} from "./chunk-53RPGOEN.js";
|
|
@@ -187,4 +187,4 @@ export {
|
|
|
187
187
|
getEmbeddingQueueDepth,
|
|
188
188
|
gatherStats
|
|
189
189
|
};
|
|
190
|
-
//# sourceMappingURL=chunk-
|
|
190
|
+
//# sourceMappingURL=chunk-4D22KTXY.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getPluginVersion
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Z55WGA2J.js";
|
|
5
5
|
import {
|
|
6
6
|
DAEMON_CLIENT_TIMEOUT_MS,
|
|
7
7
|
DAEMON_HEALTH_CHECK_TIMEOUT_MS,
|
|
@@ -23,6 +23,11 @@ async function parseErrorBody(res) {
|
|
|
23
23
|
return void 0;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
function isIgnoredEventResponse(data) {
|
|
27
|
+
if (typeof data !== "object" || data === null) return false;
|
|
28
|
+
const ignored = data.ignored;
|
|
29
|
+
return typeof ignored === "string" && ignored.length > 0;
|
|
30
|
+
}
|
|
26
31
|
var DaemonClient = class {
|
|
27
32
|
vaultDir;
|
|
28
33
|
constructor(vaultDir) {
|
|
@@ -195,6 +200,7 @@ var DaemonClient = class {
|
|
|
195
200
|
|
|
196
201
|
export {
|
|
197
202
|
resolveCliEntryPath,
|
|
203
|
+
isIgnoredEventResponse,
|
|
198
204
|
DaemonClient
|
|
199
205
|
};
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
206
|
+
//# sourceMappingURL=chunk-6FBLL7MD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/client.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport { DAEMON_CLIENT_TIMEOUT_MS, DAEMON_HEALTH_CHECK_TIMEOUT_MS, DAEMON_HEALTH_RETRY_DELAYS, DAEMON_STALE_GRACE_PERIOD_MS } from '../constants.js';\nimport { getPluginVersion } from '../version.js';\n\ninterface DaemonInfo {\n pid: number;\n port: number;\n}\n\n/**\n * Resolve the CLI entry point for spawning daemon processes.\n * Uses process.argv[1] so the daemon restarts from the same binary\n * (myco-dev vs global myco) that launched the current process.\n */\nexport function resolveCliEntryPath(): { execPath: string; cliEntry: string } {\n return { execPath: process.execPath, cliEntry: process.argv[1] };\n}\n\ninterface HealthResponse {\n myco: boolean;\n version?: string;\n}\n\ninterface ClientResult {\n ok: boolean;\n data?: any;\n}\n\n/**\n * Attempt to parse a non-ok response body as JSON so callers can surface\n * the daemon's structured error envelope (e.g. `{error: {code, message}}`).\n * Returns `undefined` if the body is empty, not JSON, or otherwise fails to\n * parse — callers that ignore `data` on failure still work unchanged.\n */\nasync function parseErrorBody(res: Response): Promise<unknown> {\n try {\n return await res.json();\n } catch {\n return undefined;\n }\n}\n\n/**\n * True when the daemon returned 200 but its body carries `{ ignored: reason }`.\n *\n * Callers that write to the event buffer on failure also buffer on this\n * signal — otherwise a capture-rule drop discards events silently even though\n * the HTTP call \"succeeded\". reconcileBufferBatches replays on next startup.\n */\nexport function isIgnoredEventResponse(data: unknown): boolean {\n if (typeof data !== 'object' || data === null) return false;\n const ignored = (data as Record<string, unknown>).ignored;\n return typeof ignored === 'string' && ignored.length > 0;\n}\n\nexport class DaemonClient {\n private vaultDir: string;\n\n constructor(vaultDir: string) {\n this.vaultDir = vaultDir;\n }\n\n async post(endpoint: string, body: unknown): Promise<ClientResult> {\n try {\n const info = this.readDaemonJson();\n if (!info) return { ok: false };\n\n const res = await fetch(`http://127.0.0.1:${info.port}${endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n\n if (!res.ok) return { ok: false, data: await parseErrorBody(res) };\n const data = await res.json();\n return { ok: true, data };\n } catch {\n return { ok: false };\n }\n }\n\n async put(endpoint: string, body: unknown): Promise<ClientResult> {\n try {\n const info = this.readDaemonJson();\n if (!info) return { ok: false };\n\n const res = await fetch(`http://127.0.0.1:${info.port}${endpoint}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n\n if (!res.ok) return { ok: false, data: await parseErrorBody(res) };\n const data = await res.json();\n return { ok: true, data };\n } catch {\n return { ok: false };\n }\n }\n\n async get(endpoint: string): Promise<ClientResult> {\n try {\n const info = this.readDaemonJson();\n if (!info) return { ok: false };\n\n const res = await fetch(`http://127.0.0.1:${info.port}${endpoint}`, {\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n\n if (!res.ok) return { ok: false, data: await parseErrorBody(res) };\n const data = await res.json();\n return { ok: true, data };\n } catch {\n return { ok: false };\n }\n }\n\n async delete(endpoint: string, body?: unknown): Promise<ClientResult> {\n try {\n const info = this.readDaemonJson();\n if (!info) return { ok: false };\n\n const init: RequestInit = {\n method: 'DELETE',\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n };\n if (body !== undefined) {\n init.headers = { 'Content-Type': 'application/json' };\n init.body = JSON.stringify(body);\n }\n\n const res = await fetch(`http://127.0.0.1:${info.port}${endpoint}`, init);\n\n if (!res.ok) return { ok: false, data: await parseErrorBody(res) };\n const data = await res.json();\n return { ok: true, data };\n } catch {\n return { ok: false };\n }\n }\n\n async isHealthy(cachedInfo?: DaemonInfo | null): Promise<boolean> {\n try {\n const info = cachedInfo ?? this.readDaemonJson();\n if (!info) return false;\n\n const res = await fetch(`http://127.0.0.1:${info.port}/health`, {\n signal: AbortSignal.timeout(DAEMON_HEALTH_CHECK_TIMEOUT_MS),\n });\n if (!res.ok) return false;\n const data = await res.json() as HealthResponse;\n return data.myco === true;\n } catch {\n return false;\n }\n }\n\n /**\n * Check if the daemon is running a stale version.\n * Returns true if the daemon's version doesn't match the current plugin version.\n * Skips the check if daemon.json was written recently (grace period) to prevent\n * rapid restart loops from concurrent hooks or session reloads.\n */\n private async isStale(info: DaemonInfo): Promise<boolean> {\n try {\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n const stat = fs.statSync(jsonPath);\n if (Date.now() - stat.mtimeMs < DAEMON_STALE_GRACE_PERIOD_MS) {\n return false;\n }\n\n const res = await fetch(`http://127.0.0.1:${info.port}/health`, {\n signal: AbortSignal.timeout(DAEMON_HEALTH_CHECK_TIMEOUT_MS),\n });\n if (!res.ok) return false;\n const data = await res.json() as HealthResponse;\n if (!data.myco) return false;\n\n // No version in response = old daemon that predates this check\n if (!data.version) return true;\n\n return data.version !== getPluginVersion();\n } catch {\n return false;\n }\n }\n\n /**\n * Kill the running daemon process.\n */\n private killDaemon(info: DaemonInfo | null): void {\n try {\n if (!info) return;\n process.kill(info.pid, 'SIGTERM');\n } catch { /* already dead */ }\n try {\n fs.unlinkSync(path.join(this.vaultDir, 'daemon.json'));\n } catch { /* already gone */ }\n }\n\n /**\n * Ensure the daemon is running. Spawns it if unhealthy.\n * When checkStale is true (default), also restarts a healthy daemon if its\n * version doesn't match the current plugin version. Use checkStale: false\n * for hooks that just need the daemon alive (e.g., stop) without triggering\n * version-driven restarts.\n */\n async ensureRunning(opts?: { checkStale?: boolean }): Promise<boolean> {\n const checkStale = opts?.checkStale ?? true;\n const info = this.readDaemonJson();\n\n if (checkStale && info && await this.isStale(info)) {\n this.killDaemon(info);\n // Brief pause for port release\n await new Promise((r) => setTimeout(r, 200));\n } else if (await this.isHealthy(info)) {\n return true;\n }\n\n this.spawnDaemon();\n\n for (const delay of DAEMON_HEALTH_RETRY_DELAYS) {\n await new Promise((r) => setTimeout(r, delay));\n if (await this.isHealthy()) return true;\n }\n return false;\n }\n\n spawnDaemon(): void {\n const { execPath, cliEntry } = resolveCliEntryPath();\n const child = spawn(execPath, [cliEntry, 'daemon', '--vault', this.vaultDir], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n }\n\n private readDaemonJson(): DaemonInfo | null {\n try {\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n const content = fs.readFileSync(jsonPath, 'utf-8');\n const info = JSON.parse(content);\n if (typeof info.port !== 'number') return null;\n return info as DaemonInfo;\n } catch {\n return null;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
COLLECTIVE_TOOL_DEFINITIONS,
|
|
11
11
|
TOOL_DEFINITIONS,
|
|
12
12
|
getToolCortexPriority
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DMPCC7V6.js";
|
|
14
14
|
import {
|
|
15
15
|
getDatabase
|
|
16
16
|
} from "./chunk-MYX5NCRH.js";
|
|
@@ -582,13 +582,6 @@ function countSpores(options = {}) {
|
|
|
582
582
|
).get(...params);
|
|
583
583
|
return row.count;
|
|
584
584
|
}
|
|
585
|
-
function listSporeIdsSince(sinceEpoch, limit = 20) {
|
|
586
|
-
const db = getDatabase();
|
|
587
|
-
const rows = db.prepare(
|
|
588
|
-
`SELECT id FROM spores WHERE created_at > ? AND status = 'active' ORDER BY created_at DESC LIMIT ?`
|
|
589
|
-
).all(sinceEpoch, limit);
|
|
590
|
-
return rows.map((r) => r.id);
|
|
591
|
-
}
|
|
592
585
|
function updateSporeStatus(id, status, updatedAt) {
|
|
593
586
|
const db = getDatabase();
|
|
594
587
|
const info = db.prepare(
|
|
@@ -848,11 +841,10 @@ export {
|
|
|
848
841
|
getSpore,
|
|
849
842
|
listSpores,
|
|
850
843
|
countSpores,
|
|
851
|
-
listSporeIdsSince,
|
|
852
844
|
updateSporeStatus,
|
|
853
845
|
shouldInjectCortex,
|
|
854
846
|
resolveInstructionDelivery,
|
|
855
847
|
buildCortexInstructionsInput,
|
|
856
848
|
buildScheduledCortexInstruction
|
|
857
849
|
};
|
|
858
|
-
//# sourceMappingURL=chunk-
|
|
850
|
+
//# sourceMappingURL=chunk-DBBO6FHE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/queries/cortex-instructions.ts","../src/db/queries/digest-extracts.ts","../src/db/queries/plans.ts","../src/db/queries/spores.ts","../src/context/cortex-brief.ts"],"sourcesContent":["import { getDatabase } from '@myco/db/client.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\n\nconst CORTEX_INSTRUCTION_COLUMNS = [\n 'id',\n 'agent_id',\n 'content',\n 'input_hash',\n 'source_run_id',\n 'generated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = CORTEX_INSTRUCTION_COLUMNS.join(', ');\nconst DEFAULT_CORTEX_INSTRUCTIONS_ID = 'session-start';\n\nexport interface CortexInstructionsUpsert {\n agent_id: string;\n content: string;\n input_hash: string;\n generated_at: number;\n id?: string;\n machine_id?: string;\n source_run_id?: string | null;\n}\n\nexport interface CortexInstructionsRow {\n id: string;\n agent_id: string;\n content: string;\n input_hash: string;\n source_run_id: string | null;\n generated_at: number;\n machine_id: string;\n synced_at: number | null;\n}\n\nfunction toCortexInstructionsRow(row: Record<string, unknown>): CortexInstructionsRow {\n return {\n id: row.id as string,\n agent_id: row.agent_id as string,\n content: row.content as string,\n input_hash: row.input_hash as string,\n source_run_id: (row.source_run_id as string) ?? null,\n generated_at: row.generated_at as number,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\nexport function upsertCortexInstructions(input: CortexInstructionsUpsert): CortexInstructionsRow {\n const db = getDatabase();\n const id = input.id ?? `${input.agent_id}:${DEFAULT_CORTEX_INSTRUCTIONS_ID}`;\n\n const row = db.prepare(\n `INSERT INTO cortex_instructions (\n id, agent_id, content, input_hash, source_run_id, generated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?, ?, ?, ?\n )\n ON CONFLICT (id) DO UPDATE SET\n content = EXCLUDED.content,\n input_hash = EXCLUDED.input_hash,\n source_run_id = EXCLUDED.source_run_id,\n generated_at = EXCLUDED.generated_at,\n machine_id = EXCLUDED.machine_id\n RETURNING ${SELECT_COLUMNS}`,\n ).get(\n id,\n input.agent_id,\n input.content,\n input.input_hash,\n input.source_run_id ?? null,\n input.generated_at,\n input.machine_id ?? getTeamMachineId(),\n ) as Record<string, unknown>;\n\n return toCortexInstructionsRow(row);\n}\n\nexport function getCortexInstructions(agentId: string): CortexInstructionsRow | null {\n const db = getDatabase();\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM cortex_instructions\n WHERE agent_id = ?\n ORDER BY generated_at DESC\n LIMIT 1`,\n ).get(agentId) as Record<string, unknown> | undefined;\n return row ? toCortexInstructionsRow(row) : null;\n}\n","/**\n * Digest extract CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { DIGEST_TIERS, epochSeconds } from '@myco/constants.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required when upserting a digest extract. */\nexport interface DigestExtractUpsert {\n agent_id: string;\n tier: number;\n content: string;\n generated_at: number;\n machine_id?: string;\n}\n\n/**\n * Options that control whether the upsert actually writes and how the\n * revision history is recorded. Added in schema v15.\n */\nexport interface DigestExtractUpsertOptions {\n /**\n * When true, the upsert is a no-op: nothing is written, no revision is\n * recorded, and `null` is returned. Used by dry-run tooling so we can\n * preview writes without touching persistent state.\n */\n dryRun?: boolean;\n /**\n * Id of the agent_run that produced this write. Recorded on the\n * revision row so operators can roll a specific run back.\n */\n runId?: string | null;\n /**\n * Optional JSON-encoded metadata to store with the revision.\n */\n metadata?: string | null;\n}\n\n/** Row shape for entries in digest_extract_revisions. */\nexport interface DigestExtractRevisionRow {\n id: number;\n agent_id: string;\n tier: number;\n content: string;\n metadata: string | null;\n run_id: string | null;\n parent_revision_id: number | null;\n created_at: number;\n}\n\n/** Options accepted by rollbackDigestExtract. */\nexport interface RollbackDigestExtractOptions {\n revisionId: number;\n /** Id of the run performing the rollback (recorded on the new revision). */\n runId?: string | null;\n}\n\n/** Row shape returned from digest_extracts queries (all columns). */\nexport interface DigestExtractRow {\n id: number;\n agent_id: string;\n tier: number;\n content: string;\n substrate_hash: string | null;\n generated_at: number;\n machine_id: string;\n synced_at: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst EXTRACT_COLUMNS = [\n 'id',\n 'agent_id',\n 'tier',\n 'content',\n 'substrate_hash',\n 'generated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = EXTRACT_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed DigestExtractRow. */\nfunction toDigestExtractRow(row: Record<string, unknown>): DigestExtractRow {\n return {\n id: row.id as number,\n agent_id: row.agent_id as string,\n tier: row.tier as number,\n content: row.content as string,\n substrate_hash: (row.substrate_hash as string) ?? null,\n generated_at: row.generated_at as number,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Upsert a digest extract. Uses ON CONFLICT on (agent_id, tier).\n *\n * Schema v15 behaviour: when an existing row would be overwritten, the\n * prior content is copied into digest_extract_revisions (linked to the\n * previous revision if any) *before* the upsert runs. This makes the\n * revision log append-only and preserves the state the agent is replacing.\n *\n * When `options.dryRun === true`, the function is a no-op: nothing is\n * written to digest_extracts or digest_extract_revisions, and `null` is\n * returned. Call sites that care about the hydrated row should skip\n * follow-up reads when dry-running.\n */\nexport function upsertDigestExtract(\n data: DigestExtractUpsert,\n options: DigestExtractUpsertOptions = {},\n): DigestExtractRow | null {\n if (options.dryRun) return null;\n\n const db = getDatabase();\n\n // The revision snapshot and the live-row upsert MUST be atomic. Without\n // a transaction, a crash between the two writes would leave the revision\n // log out of sync with `digest_extracts` — the exact invariant this log\n // exists to guarantee. Matches the pattern used in sessions.ts /\n // skill-records.ts for multi-table writes.\n return db.transaction(() => {\n // Capture the row we're about to overwrite (if any) so we can copy it\n // into the revision history before mutating the live table.\n const existingRow = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(data.agent_id, data.tier) as Record<string, unknown> | undefined;\n\n if (existingRow) {\n const priorRevisionId = db.prepare(\n `SELECT id FROM digest_extract_revisions\n WHERE agent_id = ? AND tier = ?\n ORDER BY id DESC\n LIMIT 1`,\n ).get(data.agent_id, data.tier) as { id: number } | undefined;\n\n db.prepare(\n `INSERT INTO digest_extract_revisions\n (agent_id, tier, content, metadata, run_id, parent_revision_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n data.agent_id,\n data.tier,\n existingRow.content as string,\n options.metadata ?? null,\n options.runId ?? null,\n priorRevisionId?.id ?? null,\n epochSeconds(),\n );\n }\n\n db.prepare(\n `INSERT INTO digest_extracts (agent_id, tier, content, generated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (agent_id, tier) DO UPDATE SET\n content = EXCLUDED.content,\n generated_at = EXCLUDED.generated_at`,\n ).run(data.agent_id, data.tier, data.content, data.generated_at);\n\n // Always look up by composite unique key — works for both insert and update cases.\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(data.agent_id, data.tier);\n\n return toDigestExtractRow(row as Record<string, unknown>);\n })();\n}\n\n/**\n * Get a digest extract for a specific agent and tier.\n *\n * @returns the extract row, or null if not found.\n */\nexport function getDigestExtract(\n agentId: string,\n tier: number,\n): DigestExtractRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts\n WHERE agent_id = ? AND tier = ?`,\n ).get(agentId, tier) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toDigestExtractRow(row);\n}\n\n/**\n * List digest extracts for an agent, filtered to configured tiers, ordered by tier ASC.\n */\nexport function listDigestExtracts(\n agentId: string,\n): DigestExtractRow[] {\n const db = getDatabase();\n const tierPlaceholders = DIGEST_TIERS.map(() => '?').join(', ');\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM digest_extracts\n WHERE agent_id = ? AND tier IN (${tierPlaceholders})\n ORDER BY tier ASC`,\n ).all(agentId, ...DIGEST_TIERS) as Record<string, unknown>[];\n\n return rows.map(toDigestExtractRow);\n}\n\n// ---------------------------------------------------------------------------\n// Revision history (schema v15)\n// ---------------------------------------------------------------------------\n\nconst REVISION_COLUMNS = [\n 'id',\n 'agent_id',\n 'tier',\n 'content',\n 'metadata',\n 'run_id',\n 'parent_revision_id',\n 'created_at',\n] as const;\n\nconst REVISION_SELECT = REVISION_COLUMNS.join(', ');\n\nfunction toRevisionRow(row: Record<string, unknown>): DigestExtractRevisionRow {\n return {\n id: row.id as number,\n agent_id: row.agent_id as string,\n tier: row.tier as number,\n content: row.content as string,\n metadata: (row.metadata as string) ?? null,\n run_id: (row.run_id as string) ?? null,\n parent_revision_id: (row.parent_revision_id as number) ?? null,\n created_at: row.created_at as number,\n };\n}\n\n/**\n * List revisions for a specific (agent_id, tier) pair, newest first.\n * Used by operators who want to roll back a digest to an earlier state.\n */\nexport function listDigestRevisions(\n options: { agentId: string; tier: number; limit?: number },\n): DigestExtractRevisionRow[] {\n const db = getDatabase();\n const limit = options.limit ?? 50;\n const rows = db.prepare(\n `SELECT ${REVISION_SELECT}\n FROM digest_extract_revisions\n WHERE agent_id = ? AND tier = ?\n ORDER BY created_at DESC, id DESC\n LIMIT ?`,\n ).all(options.agentId, options.tier, limit) as Record<string, unknown>[];\n return rows.map(toRevisionRow);\n}\n\n/** Result of a successful rollback. */\nexport interface RollbackDigestExtractResult {\n /** The restored digest_extracts row (content now matches the target revision). */\n row: DigestExtractRow;\n /**\n * Id of the newly-appended revision that captures the pre-rollback live\n * content (so the rollback itself is reversible). `null` when no live row\n * existed before the rollback (nothing to preserve).\n */\n newRevisionId: number | null;\n}\n\n/**\n * Restore an earlier revision's content back into digest_extracts, and\n * append a *new* revision row so the revision history remains append-only.\n *\n * The newly-appended revision captures what was live before the rollback\n * (so the rollback itself is reversible), with its parent set to the last\n * revision for (agent_id, tier).\n *\n * Returns the restored digest_extracts row plus the newly-minted revision\n * id, or null if the revision id doesn't exist.\n */\nexport function rollbackDigestExtract(\n options: RollbackDigestExtractOptions,\n): RollbackDigestExtractResult | null {\n const db = getDatabase();\n\n const revision = db.prepare(\n `SELECT ${REVISION_SELECT}\n FROM digest_extract_revisions\n WHERE id = ?`,\n ).get(options.revisionId) as Record<string, unknown> | undefined;\n\n if (!revision) return null;\n\n const agentId = revision.agent_id as string;\n const tier = revision.tier as number;\n const targetContent = revision.content as string;\n const now = epochSeconds();\n\n // Preservation of the pre-rollback state and the live-row restore must\n // be atomic — same invariant as `upsertDigestExtract`.\n return db.transaction(() => {\n // 1) Append a new revision that preserves the *current* live content\n // (pre-rollback state) so the rollback itself is reversible.\n const currentRow = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(agentId, tier) as Record<string, unknown> | undefined;\n\n let newRevisionId: number | null = null;\n if (currentRow) {\n const priorRevisionId = db.prepare(\n `SELECT id FROM digest_extract_revisions\n WHERE agent_id = ? AND tier = ?\n ORDER BY id DESC\n LIMIT 1`,\n ).get(agentId, tier) as { id: number } | undefined;\n\n const info = db.prepare(\n `INSERT INTO digest_extract_revisions\n (agent_id, tier, content, metadata, run_id, parent_revision_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n agentId,\n tier,\n currentRow.content as string,\n JSON.stringify({ rollback_of: options.revisionId }),\n options.runId ?? null,\n priorRevisionId?.id ?? null,\n now,\n );\n newRevisionId = Number(info.lastInsertRowid);\n }\n\n // 2) Restore the target revision's content into the live row.\n db.prepare(\n `INSERT INTO digest_extracts (agent_id, tier, content, generated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (agent_id, tier) DO UPDATE SET\n content = EXCLUDED.content,\n generated_at = EXCLUDED.generated_at`,\n ).run(agentId, tier, targetContent, now);\n\n const restored = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(agentId, tier) as Record<string, unknown>;\n\n return {\n row: toDigestExtractRow(restored),\n newRevisionId,\n };\n })();\n}\n","/**\n * Plan CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { epochSeconds } from '@myco/constants.js';\nimport { getTeamMachineId, isTeamSyncEnabled } from '@myco/daemon/team-context.js';\nimport { enqueueOutbox } from '@myco/db/queries/team-outbox.js';\nimport { syncRow } from '@myco/db/queries/team-outbox.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of plans returned by listPlans when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Default plan status for new plans. */\nconst DEFAULT_STATUS = 'active';\n\n/** Default processed flag for new plans. */\nconst DEFAULT_PROCESSED = 0;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when inserting/upserting a plan. */\nexport interface PlanInsert {\n id: string;\n logical_key: string;\n created_at: number;\n status?: string;\n author?: string | null;\n title?: string | null;\n content?: string | null;\n source_path?: string | null;\n tags?: string | null;\n session_id?: string | null;\n prompt_batch_id?: number | null;\n content_hash?: string | null;\n processed?: number;\n updated_at?: number | null;\n machine_id?: string;\n}\n\n/** Row shape returned from plan queries. */\nexport interface PlanRow {\n id: string;\n logical_key: string;\n status: string;\n author: string | null;\n title: string | null;\n content: string | null;\n source_path: string | null;\n tags: string | null;\n session_id: string | null;\n prompt_batch_id: number | null;\n content_hash: string | null;\n processed: number;\n embedded: number;\n created_at: number;\n updated_at: number | null;\n machine_id: string;\n synced_at: number | null;\n}\n\n/** Filter options for `listPlans`. */\nexport interface ListPlansOptions {\n status?: string;\n limit?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst PLAN_COLUMNS = [\n 'id',\n 'logical_key',\n 'status',\n 'author',\n 'title',\n 'content',\n 'source_path',\n 'tags',\n 'session_id',\n 'prompt_batch_id',\n 'content_hash',\n 'processed',\n 'embedded',\n 'created_at',\n 'updated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = PLAN_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed PlanRow. */\nfunction toPlanRow(row: Record<string, unknown>): PlanRow {\n return {\n id: row.id as string,\n logical_key: row.logical_key as string,\n status: row.status as string,\n author: (row.author as string) ?? null,\n title: (row.title as string) ?? null,\n content: (row.content as string) ?? null,\n source_path: (row.source_path as string) ?? null,\n tags: (row.tags as string) ?? null,\n session_id: (row.session_id as string) ?? null,\n prompt_batch_id: (row.prompt_batch_id as number) ?? null,\n content_hash: (row.content_hash as string) ?? null,\n processed: row.processed as number,\n embedded: (row.embedded as number) ?? 0,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Insert a plan or update it if the id already exists.\n *\n * On conflict the row is updated with the values from `data`.\n */\nexport function upsertPlan(data: PlanInsert): PlanRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO plans (\n id, logical_key, status, author, title, content,\n source_path, tags, session_id, prompt_batch_id, content_hash,\n processed, created_at, updated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?, ?, ?\n )\n ON CONFLICT (logical_key) DO UPDATE SET\n id = EXCLUDED.id,\n status = EXCLUDED.status,\n author = EXCLUDED.author,\n title = EXCLUDED.title,\n content = EXCLUDED.content,\n source_path = EXCLUDED.source_path,\n tags = EXCLUDED.tags,\n session_id = EXCLUDED.session_id,\n prompt_batch_id = EXCLUDED.prompt_batch_id,\n content_hash = EXCLUDED.content_hash,\n processed = EXCLUDED.processed,\n updated_at = EXCLUDED.updated_at,\n embedded = CASE\n WHEN EXCLUDED.content_hash != plans.content_hash THEN 0\n ELSE plans.embedded\n END`,\n ).run(\n data.id,\n data.logical_key,\n data.status ?? DEFAULT_STATUS,\n data.author ?? null,\n data.title ?? null,\n data.content ?? null,\n data.source_path ?? null,\n data.tags ?? null,\n data.session_id ?? null,\n data.prompt_batch_id ?? null,\n data.content_hash ?? null,\n data.processed ?? DEFAULT_PROCESSED,\n data.created_at,\n data.updated_at ?? null,\n data.machine_id ?? getTeamMachineId(),\n );\n\n const row = toPlanRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM plans WHERE logical_key = ?`).get(data.logical_key) as Record<string, unknown>,\n );\n\n syncRow('plans', row);\n\n return row;\n}\n\n/**\n * Retrieve a single plan by id.\n *\n * @returns the plan row, or null if not found.\n */\nexport function getPlan(id: string): PlanRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM plans WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toPlanRow(row);\n}\n\n/**\n * Retrieve a single plan by logical key.\n *\n * @returns the plan row, or null if not found.\n */\nexport function getPlanByLogicalKey(logicalKey: string): PlanRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM plans WHERE logical_key = ?`,\n ).get(logicalKey) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toPlanRow(row);\n}\n\n/**\n * Delete a single plan by id and enqueue a team-sync tombstone when enabled.\n *\n * @returns the deleted plan row, or null if not found.\n */\nexport function deletePlan(id: string): PlanRow | null {\n const db = getDatabase();\n const row = getPlan(id);\n if (!row) return null;\n\n const info = db.prepare(`DELETE FROM plans WHERE id = ?`).run(id);\n if (info.changes === 0) return null;\n\n if (isTeamSyncEnabled()) {\n enqueueOutbox({\n table_name: 'plans',\n row_id: row.id,\n operation: 'delete',\n payload: JSON.stringify({\n id: row.id,\n logical_key: row.logical_key,\n title: row.title,\n }),\n machine_id: getTeamMachineId(),\n created_at: epochSeconds(),\n });\n }\n\n return row;\n}\n\n/**\n * List plans with optional filters, ordered by created_at DESC.\n */\nexport function listPlans(\n options: ListPlansOptions = {},\n): PlanRow[] {\n const db = getDatabase();\n\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.status !== undefined) {\n conditions.push(`status = ?`);\n params.push(options.status);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n\n params.push(limit);\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM plans\n ${where}\n ORDER BY created_at DESC\n LIMIT ?`,\n ).all(...params) as Record<string, unknown>[];\n\n return rows.map(toPlanRow);\n}\n\n/**\n * List all plans associated with a specific session, ordered by created_at DESC.\n */\nexport function listPlansBySession(sessionId: string): PlanRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM plans\n WHERE session_id = ?\n ORDER BY created_at DESC`,\n ).all(sessionId) as Record<string, unknown>[];\n\n return rows.map(toPlanRow);\n}\n","/**\n * Spore CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\nimport { syncRow } from '@myco/db/queries/team-outbox.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of spores returned by listSpores when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Default spore status for new spores. */\nconst DEFAULT_STATUS = 'active';\n\n/** Default importance score for new spores. */\nexport const DEFAULT_IMPORTANCE = 5;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when inserting a spore. */\nexport interface SporeInsert {\n id: string;\n agent_id: string;\n observation_type: string;\n content: string;\n created_at: number;\n session_id?: string | null;\n prompt_batch_id?: number | null;\n status?: string;\n context?: string | null;\n importance?: number;\n file_path?: string | null;\n tags?: string | null;\n content_hash?: string | null;\n properties?: string | null;\n updated_at?: number | null;\n machine_id?: string;\n}\n\n/** Row shape returned from spore queries (all columns). */\nexport interface SporeRow {\n id: string;\n agent_id: string;\n session_id: string | null;\n prompt_batch_id: number | null;\n observation_type: string;\n status: string;\n content: string;\n context: string | null;\n importance: number;\n file_path: string | null;\n tags: string | null;\n content_hash: string | null;\n properties: string | null;\n embedded: number;\n created_at: number;\n updated_at: number | null;\n machine_id: string;\n synced_at: number | null;\n}\n\n/** Filter options for `listSpores`. */\nexport interface ListSporesOptions {\n agent_id?: string;\n observation_type?: string;\n status?: string;\n session_id?: string;\n search?: string;\n /** Only return spores created after this epoch-seconds timestamp. */\n since?: number;\n limit?: number;\n offset?: number;\n /**\n * When explicitly `false`, exclude spores whose source session is still\n * `status = 'active'` — intelligence-task reads (agent tools, context\n * queries) should opt in to this. Defaults to permissive so UI listings\n * and prompt-time context injection keep seeing in-flight work. Explicit\n * `session_id` filters bypass this check: a direct lookup of one session's\n * spores is always permitted.\n */\n includeActive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst SPORE_COLUMNS = [\n 'id',\n 'agent_id',\n 'session_id',\n 'prompt_batch_id',\n 'observation_type',\n 'status',\n 'content',\n 'context',\n 'importance',\n 'file_path',\n 'tags',\n 'content_hash',\n 'properties',\n 'embedded',\n 'created_at',\n 'updated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = SPORE_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed SporeRow. */\nfunction toSporeRow(row: Record<string, unknown>): SporeRow {\n return {\n id: row.id as string,\n agent_id: row.agent_id as string,\n session_id: (row.session_id as string) ?? null,\n prompt_batch_id: (row.prompt_batch_id as number) ?? null,\n observation_type: row.observation_type as string,\n status: row.status as string,\n content: row.content as string,\n context: (row.context as string) ?? null,\n importance: row.importance as number,\n file_path: (row.file_path as string) ?? null,\n tags: (row.tags as string) ?? null,\n content_hash: (row.content_hash as string) ?? null,\n properties: (row.properties as string) ?? null,\n embedded: (row.embedded as number) ?? 0,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Insert a new spore.\n *\n * Requires a valid `agent_id` (foreign key to agents table).\n */\nexport function insertSpore(data: SporeInsert): SporeRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO spores (\n id, agent_id, session_id, prompt_batch_id,\n observation_type, status, content, context,\n importance, file_path, tags, content_hash,\n properties, created_at, updated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?\n )`,\n ).run(\n data.id,\n data.agent_id,\n data.session_id ?? null,\n data.prompt_batch_id ?? null,\n data.observation_type,\n data.status ?? DEFAULT_STATUS,\n data.content,\n data.context ?? null,\n data.importance ?? DEFAULT_IMPORTANCE,\n data.file_path ?? null,\n data.tags ?? null,\n data.content_hash ?? null,\n data.properties ?? null,\n data.created_at,\n data.updated_at ?? null,\n data.machine_id ?? getTeamMachineId(),\n );\n\n const row = toSporeRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(data.id) as Record<string, unknown>,\n );\n\n syncRow('spores', row);\n\n return row;\n}\n\n/**\n * Retrieve a single spore by id.\n *\n * @returns the spore row, or null if not found.\n */\nexport function getSpore(id: string): SporeRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toSporeRow(row);\n}\n\n/**\n * List spores with optional filters, ordered by created_at DESC.\n */\n/** Build WHERE clause and bound params from spore filter options. */\nfunction buildSporeWhere(\n options: Omit<ListSporesOptions, 'limit' | 'offset'>,\n): { where: string; params: unknown[] } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.agent_id !== undefined) {\n conditions.push(`agent_id = ?`);\n params.push(options.agent_id);\n }\n if (options.observation_type !== undefined) {\n conditions.push(`observation_type = ?`);\n params.push(options.observation_type);\n }\n if (options.status !== undefined) {\n conditions.push(`status = ?`);\n params.push(options.status);\n }\n if (options.session_id !== undefined) {\n conditions.push(`session_id = ?`);\n params.push(options.session_id);\n }\n if (options.search !== undefined && options.search.length > 0) {\n conditions.push(`(content LIKE ? OR observation_type LIKE ?)`);\n const pattern = `%${options.search}%`;\n params.push(pattern, pattern);\n }\n if (options.since !== undefined) {\n conditions.push('created_at > ?');\n params.push(options.since);\n }\n\n // Only exclude spores from in-flight sessions when the caller explicitly\n // asks for it (intelligence tasks). UI and hook-level context injection\n // leave this unset so they see everything. A direct session_id filter\n // bypasses the gate — that lookup is always permitted.\n if (options.includeActive === false && options.session_id === undefined) {\n conditions.push(\n `(session_id IS NULL OR EXISTS (SELECT 1 FROM sessions s WHERE s.id = spores.session_id AND s.status != 'active'))`,\n );\n }\n\n return {\n where: conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '',\n params,\n };\n}\n\n/**\n * List spores with optional filters, ordered by created_at DESC.\n */\nexport function listSpores(\n options: ListSporesOptions = {},\n): SporeRow[] {\n const db = getDatabase();\n const { where, params } = buildSporeWhere(options);\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n const offset = options.offset ?? 0;\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM spores\n ${where}\n ORDER BY created_at DESC\n LIMIT ?\n OFFSET ?`,\n ).all(...params, limit, offset) as Record<string, unknown>[];\n\n return rows.map(toSporeRow);\n}\n\n/**\n * Count spores matching optional filters (for pagination totals).\n */\nexport function countSpores(\n options: Omit<ListSporesOptions, 'limit' | 'offset'> = {},\n): number {\n const db = getDatabase();\n const { where, params } = buildSporeWhere(options);\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM spores ${where}`,\n ).get(...params) as { count: number };\n\n return row.count;\n}\n\n/**\n * Count active spores created after a given timestamp.\n * Used by skill-evolve to detect new knowledge since last assessment.\n */\nexport function countSporesSince(sinceEpoch: number): number {\n const db = getDatabase();\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM spores WHERE created_at > ? AND status = 'active'`,\n ).get(sinceEpoch) as { count: number };\n return row.count;\n}\n\n/**\n * List active spore IDs created after a given timestamp, ordered newest first.\n */\nexport function listSporeIdsSince(sinceEpoch: number, limit = 20): string[] {\n const db = getDatabase();\n const rows = db.prepare(\n `SELECT id FROM spores WHERE created_at > ? AND status = 'active' ORDER BY created_at DESC LIMIT ?`,\n ).all(sinceEpoch, limit) as Array<{ id: string }>;\n return rows.map(r => r.id);\n}\n\n/**\n * Update the status and updated_at timestamp of a spore.\n *\n * @returns the updated row, or null if the spore does not exist.\n */\nexport function updateSporeStatus(\n id: string,\n status: string,\n updatedAt: number,\n): SporeRow | null {\n const db = getDatabase();\n\n const info = db.prepare(\n `UPDATE spores\n SET status = ?, updated_at = ?\n WHERE id = ?`,\n ).run(status, updatedAt, id);\n\n if (info.changes === 0) return null;\n\n const row = toSporeRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(id) as Record<string, unknown>,\n );\n\n syncRow('spores', row);\n\n return row;\n}\n","/**\n * Cortex content assembly.\n *\n * Builds the material that the Cortex agent consumes and emits:\n * - Capability resolution (team/collective availability)\n * - Delivery-decision logic (inline vs session-start injection)\n * - Retrieval guidance derived from MCP tool definitions\n * - Instruction-input prompt for the `cortex-instructions` agent task\n *\n * Pure content layer — orchestration (agent run launch, snapshot reads,\n * prompt builder) lives in `@myco/daemon/cortex`.\n */\nimport { createHash } from 'node:crypto';\nimport type { MycoConfig } from '@myco/config/schema.js';\nimport {\n CONTENT_HASH_ALGORITHM,\n DEFAULT_AGENT_ID,\n DIGEST_FALLBACK_TIER,\n} from '@myco/constants.js';\nimport { getCortexInstructions } from '@myco/db/queries/cortex-instructions.js';\nimport { getDigestExtract } from '@myco/db/queries/digest-extracts.js';\nimport { listPlans } from '@myco/db/queries/plans.js';\nimport { listSessions } from '@myco/db/queries/sessions.js';\nimport { listSpores } from '@myco/db/queries/spores.js';\nimport type { TeamSyncClient } from '../daemon/team-sync.js';\nimport {\n TOOL_DEFINITIONS,\n COLLECTIVE_TOOL_DEFINITIONS,\n getToolCortexPriority,\n type ToolDefinition,\n} from '../mcp/tool-definitions.js';\n\nconst MAX_COLLECTIVE_CAPABILITY_LABELS = 4;\nconst ALL_CORTEX_TOOL_DEFINITIONS = [...TOOL_DEFINITIONS, ...COLLECTIVE_TOOL_DEFINITIONS];\n\nconst RECENT_SESSION_LIMIT = 5;\nconst RECENT_WISDOM_SPORE_LIMIT = 3;\nconst RECENT_DECISION_SPORE_LIMIT = 3;\nconst RECENT_DISCOVERY_SPORE_LIMIT = 3;\nconst RECENT_PLAN_LIMIT = 3;\nconst CONTENT_PREVIEW_MAX_CHARS = 360;\nconst DIGEST_EXCERPT_MAX_CHARS = 1800;\nconst JSON_INDENT = 2;\n\nexport const CORTEX_SKILLS_NOTE = 'Project and Myco skills are already registered with the agent separately. Tell the agent to use those skills directly when relevant, and do not instruct it to call `myco_skills`.';\n\n// ---------------------------------------------------------------------------\n// Capability resolution\n// ---------------------------------------------------------------------------\n\nexport interface CortexCapabilities {\n teamEnabled: boolean;\n collectiveConnected: boolean;\n collectiveCapabilities: string[];\n}\n\nexport interface CortexToolGuidance {\n tool: string;\n guidance: string;\n requiresTeam?: boolean;\n requiresCollective?: boolean;\n priority: number;\n}\n\nexport interface DeliveryDecision {\n inlineInstructions: boolean;\n reason: 'missing-symbiont' | 'session-start-supported' | 'session-start-disabled' | 'no-session-start';\n}\n\nfunction toCortexToolGuidance(\n tool: Pick<ToolDefinition, 'name' | 'cortex'>,\n): CortexToolGuidance | null {\n const cortex = tool.cortex;\n if (!cortex) return null;\n return {\n tool: tool.name,\n guidance: cortex.guidance,\n requiresTeam: cortex.requiresTeam,\n requiresCollective: cortex.requiresCollective,\n priority: getToolCortexPriority(tool),\n };\n}\n\nexport const RETRIEVAL_GUIDANCE: CortexToolGuidance[] = ALL_CORTEX_TOOL_DEFINITIONS\n .map(toCortexToolGuidance)\n .filter((entry): entry is CortexToolGuidance => entry !== null)\n .sort((left, right) => left.priority - right.priority);\n\nexport async function resolveCortexCapabilities(\n config: Pick<MycoConfig, 'team'>,\n getTeamClient?: () => TeamSyncClient | null,\n): Promise<CortexCapabilities> {\n const teamClient = getTeamClient?.() ?? null;\n const teamEnabled = Boolean(config.team.enabled && teamClient);\n let collectiveConnected = false;\n let collectiveCapabilities: string[] = [];\n\n if (teamEnabled && teamClient) {\n try {\n const status = await teamClient.getCollectiveStatus();\n collectiveConnected = Boolean(status?.connected);\n collectiveCapabilities = status?.capabilities ?? [];\n } catch {\n collectiveConnected = false;\n collectiveCapabilities = [];\n }\n }\n\n return {\n teamEnabled,\n collectiveConnected,\n collectiveCapabilities,\n };\n}\n\nexport function shouldInjectCortex(\n config: MycoConfig['context'],\n): boolean {\n return config.cortex_enabled;\n}\n\nexport function resolveInstructionDelivery(\n config: MycoConfig['context'],\n symbiont: {\n supportsSessionStartInjection: boolean;\n } | null,\n): DeliveryDecision {\n if (!symbiont) {\n return { inlineInstructions: true, reason: 'missing-symbiont' };\n }\n if (!config.cortex_enabled) {\n return { inlineInstructions: true, reason: 'session-start-disabled' };\n }\n if (symbiont.supportsSessionStartInjection) {\n return { inlineInstructions: false, reason: 'session-start-supported' };\n }\n return { inlineInstructions: true, reason: 'no-session-start' };\n}\n\nexport function buildCapabilitySummary(capabilities: CortexCapabilities): string[] {\n const summary = [\n capabilities.collectiveConnected\n ? 'Myco can retrieve local, team, and collective knowledge in this project.'\n : capabilities.teamEnabled\n ? 'Myco can retrieve local and shared team knowledge in this project.'\n : 'Myco can retrieve local project knowledge in this project.',\n 'Use only the currently available Myco MCP tools described below, and omit any surfaces that are offline.',\n ];\n\n if (capabilities.collectiveConnected && capabilities.collectiveCapabilities.length > 0) {\n const labels = capabilities.collectiveCapabilities.slice(0, MAX_COLLECTIVE_CAPABILITY_LABELS);\n const remaining = Math.max(\n 0,\n capabilities.collectiveCapabilities.length - MAX_COLLECTIVE_CAPABILITY_LABELS,\n );\n const suffix = remaining > 0 ? ` (+${remaining} more)` : '';\n summary.push(`Collective capabilities online: ${labels.join(', ')}${suffix}.`);\n }\n\n return summary;\n}\n\nexport function buildRetrievalGuidanceLines(capabilities: CortexCapabilities): string[] {\n const lines: string[] = [];\n\n for (const entry of RETRIEVAL_GUIDANCE) {\n if (entry.requiresTeam && !capabilities.teamEnabled) continue;\n if (entry.requiresCollective && !capabilities.collectiveConnected) continue;\n lines.push(`- \\`${entry.tool}\\`: ${entry.guidance}`);\n }\n\n return lines;\n}\n\n// ---------------------------------------------------------------------------\n// Instruction-input prompt assembly (for the `cortex-instructions` task)\n// ---------------------------------------------------------------------------\n\nfunction hashInput(value: unknown): string {\n return createHash(CONTENT_HASH_ALGORITHM)\n .update(JSON.stringify(value))\n .digest('hex');\n}\n\nfunction truncatePreview(text: string | null, maxChars: number = CONTENT_PREVIEW_MAX_CHARS): string | null {\n if (!text) return null;\n return text.length > maxChars\n ? `${text.slice(0, maxChars)}...`\n : text;\n}\n\nfunction formatRecentSessions(): string {\n const sessions = listSessions({\n includeActive: false,\n limit: RECENT_SESSION_LIMIT,\n });\n if (sessions.length === 0) return 'No recent sessions are available.';\n\n return sessions.map((session) => {\n const head = `- ${session.title ?? session.id}${session.branch ? ` (branch=${session.branch})` : ''}`;\n const body = truncatePreview(session.summary);\n return body ? `${head}\\n ${body}` : head;\n }).join('\\n');\n}\n\nfunction formatSporesOfType(\n observationType: 'wisdom' | 'decision' | 'discovery',\n limit: number,\n): string {\n const spores = listSpores({\n observation_type: observationType,\n includeActive: false,\n status: 'active',\n limit,\n });\n if (spores.length === 0) return `No recent ${observationType} spores are available.`;\n\n return spores.map((spore) => {\n const parts = [\n `- ${truncatePreview(spore.content)}`,\n spore.session_id ? `session=${spore.session_id}` : null,\n ].filter(Boolean);\n return parts.join(' — ');\n }).join('\\n');\n}\n\nfunction formatRecentPlans(): string {\n const plans = listPlans({\n status: 'active',\n limit: RECENT_PLAN_LIMIT,\n });\n if (plans.length === 0) return 'No active plans are available.';\n\n return plans.map((plan) => {\n const parts = [\n `- ${plan.title ?? plan.id}`,\n `status=${plan.status}`,\n truncatePreview(plan.content),\n ].filter(Boolean);\n return parts.join(' — ');\n }).join('\\n');\n}\n\nfunction formatDigestExcerpt(config: MycoConfig): string {\n const preferredTier = config.context.digest_tier;\n const extract =\n getDigestExtract(DEFAULT_AGENT_ID, preferredTier) ??\n getDigestExtract(DEFAULT_AGENT_ID, DIGEST_FALLBACK_TIER);\n if (!extract) return 'No current digest extract is available.';\n\n const excerpt = truncatePreview(extract.content, DIGEST_EXCERPT_MAX_CHARS) ?? '';\n return excerpt\n ? `Tier ${extract.tier} digest excerpt:\\n${excerpt}`\n : `Tier ${extract.tier} digest extract is empty.`;\n}\n\nexport interface CortexInstructionPayload {\n inputHash: string;\n instruction: string;\n}\n\nexport async function buildCortexInstructionsInput(\n config: MycoConfig,\n getTeamClient?: () => TeamSyncClient | null,\n): Promise<CortexInstructionPayload> {\n const capabilities = await resolveCortexCapabilities(config, getTeamClient);\n const capabilitySummary = buildCapabilitySummary(capabilities);\n const retrievalGuidance = buildRetrievalGuidanceLines(capabilities);\n const recentSessions = formatRecentSessions();\n const recentWisdomSpores = formatSporesOfType('wisdom', RECENT_WISDOM_SPORE_LIMIT);\n const recentDecisionSpores = formatSporesOfType('decision', RECENT_DECISION_SPORE_LIMIT);\n const recentDiscoverySpores = formatSporesOfType('discovery', RECENT_DISCOVERY_SPORE_LIMIT);\n const recentPlans = formatRecentPlans();\n const digestExcerpt = formatDigestExcerpt(config);\n const input = {\n context: {\n digest_tier: config.context.digest_tier,\n cortex_enabled: config.context.cortex_enabled,\n prompt_search: config.context.prompt_search,\n prompt_max_spores: config.context.prompt_max_spores,\n },\n capabilities,\n digestExcerpt,\n recentSessions,\n recentWisdomSpores,\n recentDecisionSpores,\n recentDiscoverySpores,\n recentPlans,\n skillsNote: CORTEX_SKILLS_NOTE,\n };\n\n return {\n inputHash: hashInput(input),\n instruction: [\n 'Author compact session-start instructions for another coding agent.',\n 'Focus on teaching how to use the highest-signal Myco tools correctly, especially retrieval and plan persistence.',\n 'Do not restate AGENTS.md or static installation details.',\n '',\n '## Runtime config',\n JSON.stringify(input.context, null, JSON_INDENT),\n '',\n '## Authoring requirements',\n '- Start with the heading `## Myco-Enabled Project`.',\n '- Follow the heading with one brief sentence explaining that Myco provides project memory, prior decisions, plans, and retrieval tools for this repository.',\n '- Teach the most useful current Myco MCP tool behavior, especially retrieval and plan persistence.',\n '- Use the recent vault activity below to mention live project hotspots when that improves usefulness.',\n `- ${CORTEX_SKILLS_NOTE}`,\n '- Keep the heading and description brief so most of the budget goes to retrieval guidance.',\n '- Keep the output compact and ready for direct injection.',\n '',\n '## Capability summary',\n ...capabilitySummary,\n '',\n '## Tool guidance to encode',\n ...retrievalGuidance,\n '',\n '## Current digest excerpt',\n digestExcerpt,\n '',\n '## Recent sessions',\n recentSessions,\n '',\n '## Recent wisdom spores',\n recentWisdomSpores,\n '',\n '## Recent decision spores',\n recentDecisionSpores,\n '',\n '## Recent discovery spores',\n recentDiscoverySpores,\n '',\n '## Active plans',\n recentPlans,\n ].join('\\n'),\n };\n}\n\nexport async function buildScheduledCortexInstruction(\n config: MycoConfig,\n getTeamClient?: () => TeamSyncClient | null,\n): Promise<CortexInstructionPayload | undefined> {\n const built = await buildCortexInstructionsInput(config, getTeamClient);\n const existing = getCortexInstructions(DEFAULT_AGENT_ID);\n if (existing?.input_hash === built.inputHash) {\n return undefined;\n }\n return built;\n}\n"],"mappings":"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","names":["SELECT_COLUMNS","SELECT_COLUMNS","DEFAULT_LIST_LIMIT","DEFAULT_STATUS","SELECT_COLUMNS","SELECT_COLUMNS"]}
|
|
1
|
+
{"version":3,"sources":["../src/db/queries/cortex-instructions.ts","../src/db/queries/digest-extracts.ts","../src/db/queries/plans.ts","../src/db/queries/spores.ts","../src/context/cortex-brief.ts"],"sourcesContent":["import { getDatabase } from '@myco/db/client.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\n\nconst CORTEX_INSTRUCTION_COLUMNS = [\n 'id',\n 'agent_id',\n 'content',\n 'input_hash',\n 'source_run_id',\n 'generated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = CORTEX_INSTRUCTION_COLUMNS.join(', ');\nconst DEFAULT_CORTEX_INSTRUCTIONS_ID = 'session-start';\n\nexport interface CortexInstructionsUpsert {\n agent_id: string;\n content: string;\n input_hash: string;\n generated_at: number;\n id?: string;\n machine_id?: string;\n source_run_id?: string | null;\n}\n\nexport interface CortexInstructionsRow {\n id: string;\n agent_id: string;\n content: string;\n input_hash: string;\n source_run_id: string | null;\n generated_at: number;\n machine_id: string;\n synced_at: number | null;\n}\n\nfunction toCortexInstructionsRow(row: Record<string, unknown>): CortexInstructionsRow {\n return {\n id: row.id as string,\n agent_id: row.agent_id as string,\n content: row.content as string,\n input_hash: row.input_hash as string,\n source_run_id: (row.source_run_id as string) ?? null,\n generated_at: row.generated_at as number,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\nexport function upsertCortexInstructions(input: CortexInstructionsUpsert): CortexInstructionsRow {\n const db = getDatabase();\n const id = input.id ?? `${input.agent_id}:${DEFAULT_CORTEX_INSTRUCTIONS_ID}`;\n\n const row = db.prepare(\n `INSERT INTO cortex_instructions (\n id, agent_id, content, input_hash, source_run_id, generated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?, ?, ?, ?\n )\n ON CONFLICT (id) DO UPDATE SET\n content = EXCLUDED.content,\n input_hash = EXCLUDED.input_hash,\n source_run_id = EXCLUDED.source_run_id,\n generated_at = EXCLUDED.generated_at,\n machine_id = EXCLUDED.machine_id\n RETURNING ${SELECT_COLUMNS}`,\n ).get(\n id,\n input.agent_id,\n input.content,\n input.input_hash,\n input.source_run_id ?? null,\n input.generated_at,\n input.machine_id ?? getTeamMachineId(),\n ) as Record<string, unknown>;\n\n return toCortexInstructionsRow(row);\n}\n\nexport function getCortexInstructions(agentId: string): CortexInstructionsRow | null {\n const db = getDatabase();\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM cortex_instructions\n WHERE agent_id = ?\n ORDER BY generated_at DESC\n LIMIT 1`,\n ).get(agentId) as Record<string, unknown> | undefined;\n return row ? toCortexInstructionsRow(row) : null;\n}\n","/**\n * Digest extract CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { DIGEST_TIERS, epochSeconds } from '@myco/constants.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required when upserting a digest extract. */\nexport interface DigestExtractUpsert {\n agent_id: string;\n tier: number;\n content: string;\n generated_at: number;\n machine_id?: string;\n}\n\n/**\n * Options that control whether the upsert actually writes and how the\n * revision history is recorded. Added in schema v15.\n */\nexport interface DigestExtractUpsertOptions {\n /**\n * When true, the upsert is a no-op: nothing is written, no revision is\n * recorded, and `null` is returned. Used by dry-run tooling so we can\n * preview writes without touching persistent state.\n */\n dryRun?: boolean;\n /**\n * Id of the agent_run that produced this write. Recorded on the\n * revision row so operators can roll a specific run back.\n */\n runId?: string | null;\n /**\n * Optional JSON-encoded metadata to store with the revision.\n */\n metadata?: string | null;\n}\n\n/** Row shape for entries in digest_extract_revisions. */\nexport interface DigestExtractRevisionRow {\n id: number;\n agent_id: string;\n tier: number;\n content: string;\n metadata: string | null;\n run_id: string | null;\n parent_revision_id: number | null;\n created_at: number;\n}\n\n/** Options accepted by rollbackDigestExtract. */\nexport interface RollbackDigestExtractOptions {\n revisionId: number;\n /** Id of the run performing the rollback (recorded on the new revision). */\n runId?: string | null;\n}\n\n/** Row shape returned from digest_extracts queries (all columns). */\nexport interface DigestExtractRow {\n id: number;\n agent_id: string;\n tier: number;\n content: string;\n substrate_hash: string | null;\n generated_at: number;\n machine_id: string;\n synced_at: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst EXTRACT_COLUMNS = [\n 'id',\n 'agent_id',\n 'tier',\n 'content',\n 'substrate_hash',\n 'generated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = EXTRACT_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed DigestExtractRow. */\nfunction toDigestExtractRow(row: Record<string, unknown>): DigestExtractRow {\n return {\n id: row.id as number,\n agent_id: row.agent_id as string,\n tier: row.tier as number,\n content: row.content as string,\n substrate_hash: (row.substrate_hash as string) ?? null,\n generated_at: row.generated_at as number,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Upsert a digest extract. Uses ON CONFLICT on (agent_id, tier).\n *\n * Schema v15 behaviour: when an existing row would be overwritten, the\n * prior content is copied into digest_extract_revisions (linked to the\n * previous revision if any) *before* the upsert runs. This makes the\n * revision log append-only and preserves the state the agent is replacing.\n *\n * When `options.dryRun === true`, the function is a no-op: nothing is\n * written to digest_extracts or digest_extract_revisions, and `null` is\n * returned. Call sites that care about the hydrated row should skip\n * follow-up reads when dry-running.\n */\nexport function upsertDigestExtract(\n data: DigestExtractUpsert,\n options: DigestExtractUpsertOptions = {},\n): DigestExtractRow | null {\n if (options.dryRun) return null;\n\n const db = getDatabase();\n\n // The revision snapshot and the live-row upsert MUST be atomic. Without\n // a transaction, a crash between the two writes would leave the revision\n // log out of sync with `digest_extracts` — the exact invariant this log\n // exists to guarantee. Matches the pattern used in sessions.ts /\n // skill-records.ts for multi-table writes.\n return db.transaction(() => {\n // Capture the row we're about to overwrite (if any) so we can copy it\n // into the revision history before mutating the live table.\n const existingRow = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(data.agent_id, data.tier) as Record<string, unknown> | undefined;\n\n if (existingRow) {\n const priorRevisionId = db.prepare(\n `SELECT id FROM digest_extract_revisions\n WHERE agent_id = ? AND tier = ?\n ORDER BY id DESC\n LIMIT 1`,\n ).get(data.agent_id, data.tier) as { id: number } | undefined;\n\n db.prepare(\n `INSERT INTO digest_extract_revisions\n (agent_id, tier, content, metadata, run_id, parent_revision_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n data.agent_id,\n data.tier,\n existingRow.content as string,\n options.metadata ?? null,\n options.runId ?? null,\n priorRevisionId?.id ?? null,\n epochSeconds(),\n );\n }\n\n db.prepare(\n `INSERT INTO digest_extracts (agent_id, tier, content, generated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (agent_id, tier) DO UPDATE SET\n content = EXCLUDED.content,\n generated_at = EXCLUDED.generated_at`,\n ).run(data.agent_id, data.tier, data.content, data.generated_at);\n\n // Always look up by composite unique key — works for both insert and update cases.\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(data.agent_id, data.tier);\n\n return toDigestExtractRow(row as Record<string, unknown>);\n })();\n}\n\n/**\n * Get a digest extract for a specific agent and tier.\n *\n * @returns the extract row, or null if not found.\n */\nexport function getDigestExtract(\n agentId: string,\n tier: number,\n): DigestExtractRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts\n WHERE agent_id = ? AND tier = ?`,\n ).get(agentId, tier) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toDigestExtractRow(row);\n}\n\n/**\n * List digest extracts for an agent, filtered to configured tiers, ordered by tier ASC.\n */\nexport function listDigestExtracts(\n agentId: string,\n): DigestExtractRow[] {\n const db = getDatabase();\n const tierPlaceholders = DIGEST_TIERS.map(() => '?').join(', ');\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM digest_extracts\n WHERE agent_id = ? AND tier IN (${tierPlaceholders})\n ORDER BY tier ASC`,\n ).all(agentId, ...DIGEST_TIERS) as Record<string, unknown>[];\n\n return rows.map(toDigestExtractRow);\n}\n\n// ---------------------------------------------------------------------------\n// Revision history (schema v15)\n// ---------------------------------------------------------------------------\n\nconst REVISION_COLUMNS = [\n 'id',\n 'agent_id',\n 'tier',\n 'content',\n 'metadata',\n 'run_id',\n 'parent_revision_id',\n 'created_at',\n] as const;\n\nconst REVISION_SELECT = REVISION_COLUMNS.join(', ');\n\nfunction toRevisionRow(row: Record<string, unknown>): DigestExtractRevisionRow {\n return {\n id: row.id as number,\n agent_id: row.agent_id as string,\n tier: row.tier as number,\n content: row.content as string,\n metadata: (row.metadata as string) ?? null,\n run_id: (row.run_id as string) ?? null,\n parent_revision_id: (row.parent_revision_id as number) ?? null,\n created_at: row.created_at as number,\n };\n}\n\n/**\n * List revisions for a specific (agent_id, tier) pair, newest first.\n * Used by operators who want to roll back a digest to an earlier state.\n */\nexport function listDigestRevisions(\n options: { agentId: string; tier: number; limit?: number },\n): DigestExtractRevisionRow[] {\n const db = getDatabase();\n const limit = options.limit ?? 50;\n const rows = db.prepare(\n `SELECT ${REVISION_SELECT}\n FROM digest_extract_revisions\n WHERE agent_id = ? AND tier = ?\n ORDER BY created_at DESC, id DESC\n LIMIT ?`,\n ).all(options.agentId, options.tier, limit) as Record<string, unknown>[];\n return rows.map(toRevisionRow);\n}\n\n/** Result of a successful rollback. */\nexport interface RollbackDigestExtractResult {\n /** The restored digest_extracts row (content now matches the target revision). */\n row: DigestExtractRow;\n /**\n * Id of the newly-appended revision that captures the pre-rollback live\n * content (so the rollback itself is reversible). `null` when no live row\n * existed before the rollback (nothing to preserve).\n */\n newRevisionId: number | null;\n}\n\n/**\n * Restore an earlier revision's content back into digest_extracts, and\n * append a *new* revision row so the revision history remains append-only.\n *\n * The newly-appended revision captures what was live before the rollback\n * (so the rollback itself is reversible), with its parent set to the last\n * revision for (agent_id, tier).\n *\n * Returns the restored digest_extracts row plus the newly-minted revision\n * id, or null if the revision id doesn't exist.\n */\nexport function rollbackDigestExtract(\n options: RollbackDigestExtractOptions,\n): RollbackDigestExtractResult | null {\n const db = getDatabase();\n\n const revision = db.prepare(\n `SELECT ${REVISION_SELECT}\n FROM digest_extract_revisions\n WHERE id = ?`,\n ).get(options.revisionId) as Record<string, unknown> | undefined;\n\n if (!revision) return null;\n\n const agentId = revision.agent_id as string;\n const tier = revision.tier as number;\n const targetContent = revision.content as string;\n const now = epochSeconds();\n\n // Preservation of the pre-rollback state and the live-row restore must\n // be atomic — same invariant as `upsertDigestExtract`.\n return db.transaction(() => {\n // 1) Append a new revision that preserves the *current* live content\n // (pre-rollback state) so the rollback itself is reversible.\n const currentRow = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(agentId, tier) as Record<string, unknown> | undefined;\n\n let newRevisionId: number | null = null;\n if (currentRow) {\n const priorRevisionId = db.prepare(\n `SELECT id FROM digest_extract_revisions\n WHERE agent_id = ? AND tier = ?\n ORDER BY id DESC\n LIMIT 1`,\n ).get(agentId, tier) as { id: number } | undefined;\n\n const info = db.prepare(\n `INSERT INTO digest_extract_revisions\n (agent_id, tier, content, metadata, run_id, parent_revision_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n agentId,\n tier,\n currentRow.content as string,\n JSON.stringify({ rollback_of: options.revisionId }),\n options.runId ?? null,\n priorRevisionId?.id ?? null,\n now,\n );\n newRevisionId = Number(info.lastInsertRowid);\n }\n\n // 2) Restore the target revision's content into the live row.\n db.prepare(\n `INSERT INTO digest_extracts (agent_id, tier, content, generated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (agent_id, tier) DO UPDATE SET\n content = EXCLUDED.content,\n generated_at = EXCLUDED.generated_at`,\n ).run(agentId, tier, targetContent, now);\n\n const restored = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM digest_extracts WHERE agent_id = ? AND tier = ?`,\n ).get(agentId, tier) as Record<string, unknown>;\n\n return {\n row: toDigestExtractRow(restored),\n newRevisionId,\n };\n })();\n}\n","/**\n * Plan CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { epochSeconds } from '@myco/constants.js';\nimport { getTeamMachineId, isTeamSyncEnabled } from '@myco/daemon/team-context.js';\nimport { enqueueOutbox } from '@myco/db/queries/team-outbox.js';\nimport { syncRow } from '@myco/db/queries/team-outbox.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of plans returned by listPlans when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Default plan status for new plans. */\nconst DEFAULT_STATUS = 'active';\n\n/** Default processed flag for new plans. */\nconst DEFAULT_PROCESSED = 0;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when inserting/upserting a plan. */\nexport interface PlanInsert {\n id: string;\n logical_key: string;\n created_at: number;\n status?: string;\n author?: string | null;\n title?: string | null;\n content?: string | null;\n source_path?: string | null;\n tags?: string | null;\n session_id?: string | null;\n prompt_batch_id?: number | null;\n content_hash?: string | null;\n processed?: number;\n updated_at?: number | null;\n machine_id?: string;\n}\n\n/** Row shape returned from plan queries. */\nexport interface PlanRow {\n id: string;\n logical_key: string;\n status: string;\n author: string | null;\n title: string | null;\n content: string | null;\n source_path: string | null;\n tags: string | null;\n session_id: string | null;\n prompt_batch_id: number | null;\n content_hash: string | null;\n processed: number;\n embedded: number;\n created_at: number;\n updated_at: number | null;\n machine_id: string;\n synced_at: number | null;\n}\n\n/** Filter options for `listPlans`. */\nexport interface ListPlansOptions {\n status?: string;\n limit?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst PLAN_COLUMNS = [\n 'id',\n 'logical_key',\n 'status',\n 'author',\n 'title',\n 'content',\n 'source_path',\n 'tags',\n 'session_id',\n 'prompt_batch_id',\n 'content_hash',\n 'processed',\n 'embedded',\n 'created_at',\n 'updated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = PLAN_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed PlanRow. */\nfunction toPlanRow(row: Record<string, unknown>): PlanRow {\n return {\n id: row.id as string,\n logical_key: row.logical_key as string,\n status: row.status as string,\n author: (row.author as string) ?? null,\n title: (row.title as string) ?? null,\n content: (row.content as string) ?? null,\n source_path: (row.source_path as string) ?? null,\n tags: (row.tags as string) ?? null,\n session_id: (row.session_id as string) ?? null,\n prompt_batch_id: (row.prompt_batch_id as number) ?? null,\n content_hash: (row.content_hash as string) ?? null,\n processed: row.processed as number,\n embedded: (row.embedded as number) ?? 0,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Insert a plan or update it if the id already exists.\n *\n * On conflict the row is updated with the values from `data`.\n */\nexport function upsertPlan(data: PlanInsert): PlanRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO plans (\n id, logical_key, status, author, title, content,\n source_path, tags, session_id, prompt_batch_id, content_hash,\n processed, created_at, updated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?, ?, ?\n )\n ON CONFLICT (logical_key) DO UPDATE SET\n id = EXCLUDED.id,\n status = EXCLUDED.status,\n author = EXCLUDED.author,\n title = EXCLUDED.title,\n content = EXCLUDED.content,\n source_path = EXCLUDED.source_path,\n tags = EXCLUDED.tags,\n session_id = EXCLUDED.session_id,\n prompt_batch_id = EXCLUDED.prompt_batch_id,\n content_hash = EXCLUDED.content_hash,\n processed = EXCLUDED.processed,\n updated_at = EXCLUDED.updated_at,\n embedded = CASE\n WHEN EXCLUDED.content_hash != plans.content_hash THEN 0\n ELSE plans.embedded\n END`,\n ).run(\n data.id,\n data.logical_key,\n data.status ?? DEFAULT_STATUS,\n data.author ?? null,\n data.title ?? null,\n data.content ?? null,\n data.source_path ?? null,\n data.tags ?? null,\n data.session_id ?? null,\n data.prompt_batch_id ?? null,\n data.content_hash ?? null,\n data.processed ?? DEFAULT_PROCESSED,\n data.created_at,\n data.updated_at ?? null,\n data.machine_id ?? getTeamMachineId(),\n );\n\n const row = toPlanRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM plans WHERE logical_key = ?`).get(data.logical_key) as Record<string, unknown>,\n );\n\n syncRow('plans', row);\n\n return row;\n}\n\n/**\n * Retrieve a single plan by id.\n *\n * @returns the plan row, or null if not found.\n */\nexport function getPlan(id: string): PlanRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM plans WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toPlanRow(row);\n}\n\n/**\n * Retrieve a single plan by logical key.\n *\n * @returns the plan row, or null if not found.\n */\nexport function getPlanByLogicalKey(logicalKey: string): PlanRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM plans WHERE logical_key = ?`,\n ).get(logicalKey) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toPlanRow(row);\n}\n\n/**\n * Delete a single plan by id and enqueue a team-sync tombstone when enabled.\n *\n * @returns the deleted plan row, or null if not found.\n */\nexport function deletePlan(id: string): PlanRow | null {\n const db = getDatabase();\n const row = getPlan(id);\n if (!row) return null;\n\n const info = db.prepare(`DELETE FROM plans WHERE id = ?`).run(id);\n if (info.changes === 0) return null;\n\n if (isTeamSyncEnabled()) {\n enqueueOutbox({\n table_name: 'plans',\n row_id: row.id,\n operation: 'delete',\n payload: JSON.stringify({\n id: row.id,\n logical_key: row.logical_key,\n title: row.title,\n }),\n machine_id: getTeamMachineId(),\n created_at: epochSeconds(),\n });\n }\n\n return row;\n}\n\n/**\n * List plans with optional filters, ordered by created_at DESC.\n */\nexport function listPlans(\n options: ListPlansOptions = {},\n): PlanRow[] {\n const db = getDatabase();\n\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.status !== undefined) {\n conditions.push(`status = ?`);\n params.push(options.status);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n\n params.push(limit);\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM plans\n ${where}\n ORDER BY created_at DESC\n LIMIT ?`,\n ).all(...params) as Record<string, unknown>[];\n\n return rows.map(toPlanRow);\n}\n\n/**\n * List all plans associated with a specific session, ordered by created_at DESC.\n */\nexport function listPlansBySession(sessionId: string): PlanRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM plans\n WHERE session_id = ?\n ORDER BY created_at DESC`,\n ).all(sessionId) as Record<string, unknown>[];\n\n return rows.map(toPlanRow);\n}\n","/**\n * Spore CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\nimport { syncRow } from '@myco/db/queries/team-outbox.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of spores returned by listSpores when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Default spore status for new spores. */\nconst DEFAULT_STATUS = 'active';\n\n/** Default importance score for new spores. */\nexport const DEFAULT_IMPORTANCE = 5;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when inserting a spore. */\nexport interface SporeInsert {\n id: string;\n agent_id: string;\n observation_type: string;\n content: string;\n created_at: number;\n session_id?: string | null;\n prompt_batch_id?: number | null;\n status?: string;\n context?: string | null;\n importance?: number;\n file_path?: string | null;\n tags?: string | null;\n content_hash?: string | null;\n properties?: string | null;\n updated_at?: number | null;\n machine_id?: string;\n}\n\n/** Row shape returned from spore queries (all columns). */\nexport interface SporeRow {\n id: string;\n agent_id: string;\n session_id: string | null;\n prompt_batch_id: number | null;\n observation_type: string;\n status: string;\n content: string;\n context: string | null;\n importance: number;\n file_path: string | null;\n tags: string | null;\n content_hash: string | null;\n properties: string | null;\n embedded: number;\n created_at: number;\n updated_at: number | null;\n machine_id: string;\n synced_at: number | null;\n}\n\n/** Filter options for `listSpores`. */\nexport interface ListSporesOptions {\n agent_id?: string;\n observation_type?: string;\n status?: string;\n session_id?: string;\n search?: string;\n /** Only return spores created after this epoch-seconds timestamp. */\n since?: number;\n limit?: number;\n offset?: number;\n /**\n * When explicitly `false`, exclude spores whose source session is still\n * `status = 'active'` — intelligence-task reads (agent tools, context\n * queries) should opt in to this. Defaults to permissive so UI listings\n * and prompt-time context injection keep seeing in-flight work. Explicit\n * `session_id` filters bypass this check: a direct lookup of one session's\n * spores is always permitted.\n */\n includeActive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst SPORE_COLUMNS = [\n 'id',\n 'agent_id',\n 'session_id',\n 'prompt_batch_id',\n 'observation_type',\n 'status',\n 'content',\n 'context',\n 'importance',\n 'file_path',\n 'tags',\n 'content_hash',\n 'properties',\n 'embedded',\n 'created_at',\n 'updated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = SPORE_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed SporeRow. */\nfunction toSporeRow(row: Record<string, unknown>): SporeRow {\n return {\n id: row.id as string,\n agent_id: row.agent_id as string,\n session_id: (row.session_id as string) ?? null,\n prompt_batch_id: (row.prompt_batch_id as number) ?? null,\n observation_type: row.observation_type as string,\n status: row.status as string,\n content: row.content as string,\n context: (row.context as string) ?? null,\n importance: row.importance as number,\n file_path: (row.file_path as string) ?? null,\n tags: (row.tags as string) ?? null,\n content_hash: (row.content_hash as string) ?? null,\n properties: (row.properties as string) ?? null,\n embedded: (row.embedded as number) ?? 0,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Insert a new spore.\n *\n * Requires a valid `agent_id` (foreign key to agents table).\n */\nexport function insertSpore(data: SporeInsert): SporeRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO spores (\n id, agent_id, session_id, prompt_batch_id,\n observation_type, status, content, context,\n importance, file_path, tags, content_hash,\n properties, created_at, updated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?\n )`,\n ).run(\n data.id,\n data.agent_id,\n data.session_id ?? null,\n data.prompt_batch_id ?? null,\n data.observation_type,\n data.status ?? DEFAULT_STATUS,\n data.content,\n data.context ?? null,\n data.importance ?? DEFAULT_IMPORTANCE,\n data.file_path ?? null,\n data.tags ?? null,\n data.content_hash ?? null,\n data.properties ?? null,\n data.created_at,\n data.updated_at ?? null,\n data.machine_id ?? getTeamMachineId(),\n );\n\n const row = toSporeRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(data.id) as Record<string, unknown>,\n );\n\n syncRow('spores', row);\n\n return row;\n}\n\n/**\n * Retrieve a single spore by id.\n *\n * @returns the spore row, or null if not found.\n */\nexport function getSpore(id: string): SporeRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toSporeRow(row);\n}\n\n/**\n * List spores with optional filters, ordered by created_at DESC.\n */\n/** Build WHERE clause and bound params from spore filter options. */\nfunction buildSporeWhere(\n options: Omit<ListSporesOptions, 'limit' | 'offset'>,\n): { where: string; params: unknown[] } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.agent_id !== undefined) {\n conditions.push(`agent_id = ?`);\n params.push(options.agent_id);\n }\n if (options.observation_type !== undefined) {\n conditions.push(`observation_type = ?`);\n params.push(options.observation_type);\n }\n if (options.status !== undefined) {\n conditions.push(`status = ?`);\n params.push(options.status);\n }\n if (options.session_id !== undefined) {\n conditions.push(`session_id = ?`);\n params.push(options.session_id);\n }\n if (options.search !== undefined && options.search.length > 0) {\n conditions.push(`(content LIKE ? OR observation_type LIKE ?)`);\n const pattern = `%${options.search}%`;\n params.push(pattern, pattern);\n }\n if (options.since !== undefined) {\n conditions.push('created_at > ?');\n params.push(options.since);\n }\n\n // Only exclude spores from in-flight sessions when the caller explicitly\n // asks for it (intelligence tasks). UI and hook-level context injection\n // leave this unset so they see everything. A direct session_id filter\n // bypasses the gate — that lookup is always permitted.\n if (options.includeActive === false && options.session_id === undefined) {\n conditions.push(\n `(session_id IS NULL OR EXISTS (SELECT 1 FROM sessions s WHERE s.id = spores.session_id AND s.status != 'active'))`,\n );\n }\n\n return {\n where: conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '',\n params,\n };\n}\n\n/**\n * List spores with optional filters, ordered by created_at DESC.\n */\nexport function listSpores(\n options: ListSporesOptions = {},\n): SporeRow[] {\n const db = getDatabase();\n const { where, params } = buildSporeWhere(options);\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n const offset = options.offset ?? 0;\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM spores\n ${where}\n ORDER BY created_at DESC\n LIMIT ?\n OFFSET ?`,\n ).all(...params, limit, offset) as Record<string, unknown>[];\n\n return rows.map(toSporeRow);\n}\n\n/**\n * Count spores matching optional filters (for pagination totals).\n */\nexport function countSpores(\n options: Omit<ListSporesOptions, 'limit' | 'offset'> = {},\n): number {\n const db = getDatabase();\n const { where, params } = buildSporeWhere(options);\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM spores ${where}`,\n ).get(...params) as { count: number };\n\n return row.count;\n}\n\n/**\n * Count active spores created after a given timestamp.\n * Used by skill-evolve to detect new knowledge since last assessment.\n */\nexport function countSporesSince(sinceEpoch: number): number {\n const db = getDatabase();\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM spores WHERE created_at > ? AND status = 'active'`,\n ).get(sinceEpoch) as { count: number };\n return row.count;\n}\n\n/**\n * List active spore IDs created after a given timestamp, ordered newest first.\n */\nexport function listSporeIdsSince(sinceEpoch: number, limit = 20): string[] {\n const db = getDatabase();\n const rows = db.prepare(\n `SELECT id FROM spores WHERE created_at > ? AND status = 'active' ORDER BY created_at DESC LIMIT ?`,\n ).all(sinceEpoch, limit) as Array<{ id: string }>;\n return rows.map(r => r.id);\n}\n\n/**\n * Update the status and updated_at timestamp of a spore.\n *\n * @returns the updated row, or null if the spore does not exist.\n */\nexport function updateSporeStatus(\n id: string,\n status: string,\n updatedAt: number,\n): SporeRow | null {\n const db = getDatabase();\n\n const info = db.prepare(\n `UPDATE spores\n SET status = ?, updated_at = ?\n WHERE id = ?`,\n ).run(status, updatedAt, id);\n\n if (info.changes === 0) return null;\n\n const row = toSporeRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(id) as Record<string, unknown>,\n );\n\n syncRow('spores', row);\n\n return row;\n}\n","/**\n * Cortex content assembly.\n *\n * Builds the material that the Cortex agent consumes and emits:\n * - Capability resolution (team/collective availability)\n * - Delivery-decision logic (inline vs session-start injection)\n * - Retrieval guidance derived from MCP tool definitions\n * - Instruction-input prompt for the `cortex-instructions` agent task\n *\n * Pure content layer — orchestration (agent run launch, snapshot reads,\n * prompt builder) lives in `@myco/daemon/cortex`.\n */\nimport { createHash } from 'node:crypto';\nimport type { MycoConfig } from '@myco/config/schema.js';\nimport {\n CONTENT_HASH_ALGORITHM,\n DEFAULT_AGENT_ID,\n DIGEST_FALLBACK_TIER,\n} from '@myco/constants.js';\nimport { getCortexInstructions } from '@myco/db/queries/cortex-instructions.js';\nimport { getDigestExtract } from '@myco/db/queries/digest-extracts.js';\nimport { listPlans } from '@myco/db/queries/plans.js';\nimport { listSessions } from '@myco/db/queries/sessions.js';\nimport { listSpores } from '@myco/db/queries/spores.js';\nimport type { TeamSyncClient } from '../daemon/team-sync.js';\nimport {\n TOOL_DEFINITIONS,\n COLLECTIVE_TOOL_DEFINITIONS,\n getToolCortexPriority,\n type ToolDefinition,\n} from '../mcp/tool-definitions.js';\n\nconst MAX_COLLECTIVE_CAPABILITY_LABELS = 4;\nconst ALL_CORTEX_TOOL_DEFINITIONS = [...TOOL_DEFINITIONS, ...COLLECTIVE_TOOL_DEFINITIONS];\n\nconst RECENT_SESSION_LIMIT = 5;\nconst RECENT_WISDOM_SPORE_LIMIT = 3;\nconst RECENT_DECISION_SPORE_LIMIT = 3;\nconst RECENT_DISCOVERY_SPORE_LIMIT = 3;\nconst RECENT_PLAN_LIMIT = 3;\nconst CONTENT_PREVIEW_MAX_CHARS = 360;\nconst DIGEST_EXCERPT_MAX_CHARS = 1800;\nconst JSON_INDENT = 2;\n\nexport const CORTEX_SKILLS_NOTE = 'Project and Myco skills are already registered with the agent separately. Tell the agent to use those skills directly when relevant, and do not instruct it to call `myco_skills`.';\n\n// ---------------------------------------------------------------------------\n// Capability resolution\n// ---------------------------------------------------------------------------\n\nexport interface CortexCapabilities {\n teamEnabled: boolean;\n collectiveConnected: boolean;\n collectiveCapabilities: string[];\n}\n\nexport interface CortexToolGuidance {\n tool: string;\n guidance: string;\n requiresTeam?: boolean;\n requiresCollective?: boolean;\n priority: number;\n}\n\nexport interface DeliveryDecision {\n inlineInstructions: boolean;\n reason: 'missing-symbiont' | 'session-start-supported' | 'session-start-disabled' | 'no-session-start';\n}\n\nfunction toCortexToolGuidance(\n tool: Pick<ToolDefinition, 'name' | 'cortex'>,\n): CortexToolGuidance | null {\n const cortex = tool.cortex;\n if (!cortex) return null;\n return {\n tool: tool.name,\n guidance: cortex.guidance,\n requiresTeam: cortex.requiresTeam,\n requiresCollective: cortex.requiresCollective,\n priority: getToolCortexPriority(tool),\n };\n}\n\nexport const RETRIEVAL_GUIDANCE: CortexToolGuidance[] = ALL_CORTEX_TOOL_DEFINITIONS\n .map(toCortexToolGuidance)\n .filter((entry): entry is CortexToolGuidance => entry !== null)\n .sort((left, right) => left.priority - right.priority);\n\nexport async function resolveCortexCapabilities(\n config: Pick<MycoConfig, 'team'>,\n getTeamClient?: () => TeamSyncClient | null,\n): Promise<CortexCapabilities> {\n const teamClient = getTeamClient?.() ?? null;\n const teamEnabled = Boolean(config.team.enabled && teamClient);\n let collectiveConnected = false;\n let collectiveCapabilities: string[] = [];\n\n if (teamEnabled && teamClient) {\n try {\n const status = await teamClient.getCollectiveStatus();\n collectiveConnected = Boolean(status?.connected);\n collectiveCapabilities = status?.capabilities ?? [];\n } catch {\n collectiveConnected = false;\n collectiveCapabilities = [];\n }\n }\n\n return {\n teamEnabled,\n collectiveConnected,\n collectiveCapabilities,\n };\n}\n\nexport function shouldInjectCortex(\n config: MycoConfig['context'],\n): boolean {\n return config.cortex_enabled;\n}\n\nexport function resolveInstructionDelivery(\n config: MycoConfig['context'],\n symbiont: {\n supportsSessionStartInjection: boolean;\n } | null,\n): DeliveryDecision {\n if (!symbiont) {\n return { inlineInstructions: true, reason: 'missing-symbiont' };\n }\n if (!config.cortex_enabled) {\n return { inlineInstructions: true, reason: 'session-start-disabled' };\n }\n if (symbiont.supportsSessionStartInjection) {\n return { inlineInstructions: false, reason: 'session-start-supported' };\n }\n return { inlineInstructions: true, reason: 'no-session-start' };\n}\n\nexport function buildCapabilitySummary(capabilities: CortexCapabilities): string[] {\n const summary = [\n capabilities.collectiveConnected\n ? 'Myco can retrieve local, team, and collective knowledge in this project.'\n : capabilities.teamEnabled\n ? 'Myco can retrieve local and shared team knowledge in this project.'\n : 'Myco can retrieve local project knowledge in this project.',\n 'Use only the currently available Myco MCP tools described below, and omit any surfaces that are offline.',\n ];\n\n if (capabilities.collectiveConnected && capabilities.collectiveCapabilities.length > 0) {\n const labels = capabilities.collectiveCapabilities.slice(0, MAX_COLLECTIVE_CAPABILITY_LABELS);\n const remaining = Math.max(\n 0,\n capabilities.collectiveCapabilities.length - MAX_COLLECTIVE_CAPABILITY_LABELS,\n );\n const suffix = remaining > 0 ? ` (+${remaining} more)` : '';\n summary.push(`Collective capabilities online: ${labels.join(', ')}${suffix}.`);\n }\n\n return summary;\n}\n\nexport function buildRetrievalGuidanceLines(capabilities: CortexCapabilities): string[] {\n const lines: string[] = [];\n\n for (const entry of RETRIEVAL_GUIDANCE) {\n if (entry.requiresTeam && !capabilities.teamEnabled) continue;\n if (entry.requiresCollective && !capabilities.collectiveConnected) continue;\n lines.push(`- \\`${entry.tool}\\`: ${entry.guidance}`);\n }\n\n return lines;\n}\n\n// ---------------------------------------------------------------------------\n// Instruction-input prompt assembly (for the `cortex-instructions` task)\n// ---------------------------------------------------------------------------\n\nfunction hashInput(value: unknown): string {\n return createHash(CONTENT_HASH_ALGORITHM)\n .update(JSON.stringify(value))\n .digest('hex');\n}\n\nfunction truncatePreview(text: string | null, maxChars: number = CONTENT_PREVIEW_MAX_CHARS): string | null {\n if (!text) return null;\n return text.length > maxChars\n ? `${text.slice(0, maxChars)}...`\n : text;\n}\n\nfunction formatRecentSessions(): string {\n const sessions = listSessions({\n includeActive: false,\n limit: RECENT_SESSION_LIMIT,\n });\n if (sessions.length === 0) return 'No recent sessions are available.';\n\n return sessions.map((session) => {\n const head = `- ${session.title ?? session.id}${session.branch ? ` (branch=${session.branch})` : ''}`;\n const body = truncatePreview(session.summary);\n return body ? `${head}\\n ${body}` : head;\n }).join('\\n');\n}\n\nfunction formatSporesOfType(\n observationType: 'wisdom' | 'decision' | 'discovery',\n limit: number,\n): string {\n const spores = listSpores({\n observation_type: observationType,\n includeActive: false,\n status: 'active',\n limit,\n });\n if (spores.length === 0) return `No recent ${observationType} spores are available.`;\n\n return spores.map((spore) => {\n const parts = [\n `- ${truncatePreview(spore.content)}`,\n spore.session_id ? `session=${spore.session_id}` : null,\n ].filter(Boolean);\n return parts.join(' — ');\n }).join('\\n');\n}\n\nfunction formatRecentPlans(): string {\n const plans = listPlans({\n status: 'active',\n limit: RECENT_PLAN_LIMIT,\n });\n if (plans.length === 0) return 'No active plans are available.';\n\n return plans.map((plan) => {\n const parts = [\n `- ${plan.title ?? plan.id}`,\n `status=${plan.status}`,\n truncatePreview(plan.content),\n ].filter(Boolean);\n return parts.join(' — ');\n }).join('\\n');\n}\n\nfunction formatDigestExcerpt(config: MycoConfig): string {\n const preferredTier = config.context.digest_tier;\n const extract =\n getDigestExtract(DEFAULT_AGENT_ID, preferredTier) ??\n getDigestExtract(DEFAULT_AGENT_ID, DIGEST_FALLBACK_TIER);\n if (!extract) return 'No current digest extract is available.';\n\n const excerpt = truncatePreview(extract.content, DIGEST_EXCERPT_MAX_CHARS) ?? '';\n return excerpt\n ? `Tier ${extract.tier} digest excerpt:\\n${excerpt}`\n : `Tier ${extract.tier} digest extract is empty.`;\n}\n\nexport interface CortexInstructionPayload {\n inputHash: string;\n instruction: string;\n}\n\nexport async function buildCortexInstructionsInput(\n config: MycoConfig,\n getTeamClient?: () => TeamSyncClient | null,\n): Promise<CortexInstructionPayload> {\n const capabilities = await resolveCortexCapabilities(config, getTeamClient);\n const capabilitySummary = buildCapabilitySummary(capabilities);\n const retrievalGuidance = buildRetrievalGuidanceLines(capabilities);\n const recentSessions = formatRecentSessions();\n const recentWisdomSpores = formatSporesOfType('wisdom', RECENT_WISDOM_SPORE_LIMIT);\n const recentDecisionSpores = formatSporesOfType('decision', RECENT_DECISION_SPORE_LIMIT);\n const recentDiscoverySpores = formatSporesOfType('discovery', RECENT_DISCOVERY_SPORE_LIMIT);\n const recentPlans = formatRecentPlans();\n const digestExcerpt = formatDigestExcerpt(config);\n const input = {\n context: {\n digest_tier: config.context.digest_tier,\n cortex_enabled: config.context.cortex_enabled,\n prompt_search: config.context.prompt_search,\n prompt_max_spores: config.context.prompt_max_spores,\n },\n capabilities,\n digestExcerpt,\n recentSessions,\n recentWisdomSpores,\n recentDecisionSpores,\n recentDiscoverySpores,\n recentPlans,\n skillsNote: CORTEX_SKILLS_NOTE,\n };\n\n return {\n inputHash: hashInput(input),\n instruction: [\n 'Author compact session-start instructions for another coding agent.',\n 'Focus on teaching how to use the highest-signal Myco tools correctly, especially retrieval and plan persistence.',\n 'Do not restate AGENTS.md or static installation details.',\n '',\n '## Runtime config',\n JSON.stringify(input.context, null, JSON_INDENT),\n '',\n '## Authoring requirements',\n '- Start with the heading `## Myco-Enabled Project`.',\n '- Follow the heading with one brief sentence explaining that Myco provides project memory, prior decisions, plans, and retrieval tools for this repository.',\n '- Teach the most useful current Myco MCP tool behavior, especially retrieval and plan persistence.',\n '- Use the recent vault activity below to mention live project hotspots when that improves usefulness.',\n `- ${CORTEX_SKILLS_NOTE}`,\n '- Keep the heading and description brief so most of the budget goes to retrieval guidance.',\n '- Keep the output compact and ready for direct injection.',\n '',\n '## Capability summary',\n ...capabilitySummary,\n '',\n '## Tool guidance to encode',\n ...retrievalGuidance,\n '',\n '## Current digest excerpt',\n digestExcerpt,\n '',\n '## Recent sessions',\n recentSessions,\n '',\n '## Recent wisdom spores',\n recentWisdomSpores,\n '',\n '## Recent decision spores',\n recentDecisionSpores,\n '',\n '## Recent discovery spores',\n recentDiscoverySpores,\n '',\n '## Active plans',\n recentPlans,\n ].join('\\n'),\n };\n}\n\nexport async function buildScheduledCortexInstruction(\n config: MycoConfig,\n getTeamClient?: () => TeamSyncClient | null,\n): Promise<CortexInstructionPayload | undefined> {\n const built = await buildCortexInstructionsInput(config, getTeamClient);\n const existing = getCortexInstructions(DEFAULT_AGENT_ID);\n if (existing?.input_hash === built.inputHash) {\n return undefined;\n }\n return built;\n}\n"],"mappings":"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","names":["SELECT_COLUMNS","SELECT_COLUMNS","DEFAULT_LIST_LIMIT","DEFAULT_STATUS","SELECT_COLUMNS","SELECT_COLUMNS"]}
|
|
@@ -115,7 +115,11 @@ var TOOL_DEFINITIONS = [
|
|
|
115
115
|
properties: {
|
|
116
116
|
query: { type: "string", description: "Natural language search query \u2014 describe what you are looking for" },
|
|
117
117
|
type: { type: "string", enum: ["session", "plan", "spore", "all"], description: "Filter by note type (default: all)" },
|
|
118
|
-
limit: { type: "number", description: `Max results (default: ${MCP_SEARCH_DEFAULT_LIMIT})` }
|
|
118
|
+
limit: { type: "number", description: `Max results (default: ${MCP_SEARCH_DEFAULT_LIMIT})` },
|
|
119
|
+
observation_type: { type: "string", description: "Optional semantic filter for spore observation type (decision, gotcha, discovery, etc.)" },
|
|
120
|
+
status: { type: "string", description: "Optional semantic filter for record status (for example active)" },
|
|
121
|
+
since: { type: "number", description: "Optional created_at lower bound in epoch seconds" },
|
|
122
|
+
until: { type: "number", description: "Optional created_at upper bound in epoch seconds" }
|
|
119
123
|
},
|
|
120
124
|
required: ["query"]
|
|
121
125
|
}
|
|
@@ -513,7 +517,15 @@ var COLLECTIVE_TOOL_DEFINITIONS = [
|
|
|
513
517
|
properties: {
|
|
514
518
|
query: { type: "string", description: "Natural language search query across the connected Collective projects" },
|
|
515
519
|
project: { type: "string", description: "Optional project id or project name filter" },
|
|
516
|
-
limit: { type: "number", description: `Max results (default: ${MCP_SEARCH_DEFAULT_LIMIT})` }
|
|
520
|
+
limit: { type: "number", description: `Max results (default: ${MCP_SEARCH_DEFAULT_LIMIT})` },
|
|
521
|
+
types: { type: "array", items: { type: "string" }, description: "Optional content type filter for remote semantic search" },
|
|
522
|
+
observation_type: { type: "string", description: "Optional spore observation type filter for remote semantic search" },
|
|
523
|
+
status: { type: "string", description: "Optional record status filter for remote semantic search" },
|
|
524
|
+
since: { type: "number", description: "Optional created_at lower bound in epoch seconds" },
|
|
525
|
+
until: { type: "number", description: "Optional created_at upper bound in epoch seconds" },
|
|
526
|
+
session_id: { type: "string", description: "Optional session id metadata filter" },
|
|
527
|
+
source_path: { type: "string", description: "Optional source path metadata filter" },
|
|
528
|
+
name: { type: "string", description: "Optional name metadata filter" }
|
|
517
529
|
},
|
|
518
530
|
required: ["query"]
|
|
519
531
|
}
|
|
@@ -579,4 +591,4 @@ export {
|
|
|
579
591
|
TOOL_DEFINITIONS,
|
|
580
592
|
COLLECTIVE_TOOL_DEFINITIONS
|
|
581
593
|
};
|
|
582
|
-
//# sourceMappingURL=chunk-
|
|
594
|
+
//# sourceMappingURL=chunk-DMPCC7V6.js.map
|