@goondocks/myco 0.21.0 → 0.21.1

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.
Files changed (145) hide show
  1. package/bin/myco-run +68 -7
  2. package/dist/{agent-eval-RJSQI5S2.js → agent-eval-YK2VP2S4.js} +7 -6
  3. package/dist/{agent-eval-RJSQI5S2.js.map → agent-eval-YK2VP2S4.js.map} +1 -1
  4. package/dist/{agent-run-2JSYFOKU.js → agent-run-GEJBD2YD.js} +5 -5
  5. package/dist/{agent-tasks-APFJIM2T.js → agent-tasks-5XSRGTRX.js} +5 -5
  6. package/dist/{chunk-R2JIJBCL.js → chunk-6ALVMIB4.js} +3 -3
  7. package/dist/{chunk-JZS6GZ6T.js → chunk-AUIXX33A.js} +10 -3
  8. package/dist/chunk-AUIXX33A.js.map +1 -0
  9. package/dist/{chunk-RL5R4CQU.js → chunk-DTWUHHFI.js} +39 -2
  10. package/dist/{chunk-RL5R4CQU.js.map → chunk-DTWUHHFI.js.map} +1 -1
  11. package/dist/{chunk-CESKJD44.js → chunk-EEOJWLMP.js} +5 -9
  12. package/dist/chunk-EEOJWLMP.js.map +1 -0
  13. package/dist/{chunk-BUTL6IFS.js → chunk-ENZR5NG7.js} +2 -2
  14. package/dist/{chunk-P66DLD6G.js → chunk-KTTSXYEK.js} +2 -2
  15. package/dist/chunk-LQIPXVDH.js +17 -0
  16. package/dist/chunk-LQIPXVDH.js.map +1 -0
  17. package/dist/{chunk-5ZG4RMUH.js → chunk-N2DGFACQ.js} +2 -2
  18. package/dist/{chunk-F3OEQYLS.js → chunk-N7Z3LUEZ.js} +33 -22
  19. package/dist/{chunk-F3OEQYLS.js.map → chunk-N7Z3LUEZ.js.map} +1 -1
  20. package/dist/{chunk-G6QIBNZM.js → chunk-NFO7BRCO.js} +4 -4
  21. package/dist/{chunk-VHNRMM4O.js → chunk-OTQH5KZW.js} +87 -37
  22. package/dist/chunk-OTQH5KZW.js.map +1 -0
  23. package/dist/{chunk-DJ3IHNYO.js → chunk-OZ3FBAK5.js} +2 -2
  24. package/dist/{chunk-6LB7XELY.js → chunk-QATYARI5.js} +15 -13
  25. package/dist/chunk-QATYARI5.js.map +1 -0
  26. package/dist/{chunk-JR54LTPP.js → chunk-QDLVIW2O.js} +3 -3
  27. package/dist/{chunk-LVIY7P35.js → chunk-QLLBJEM7.js} +5 -1
  28. package/dist/chunk-QLLBJEM7.js.map +1 -0
  29. package/dist/chunk-TSM6VESW.js +25 -0
  30. package/dist/chunk-TSM6VESW.js.map +1 -0
  31. package/dist/{chunk-ILJPRYES.js → chunk-USVFEWYL.js} +2 -2
  32. package/dist/{chunk-75Z7UKDY.js → chunk-VRI56337.js} +2 -2
  33. package/dist/{chunk-NGH7U6A3.js → chunk-X2IRGXGF.js} +336 -77
  34. package/dist/chunk-X2IRGXGF.js.map +1 -0
  35. package/dist/{chunk-NGROSFOH.js → chunk-Z66IT5KL.js} +14 -9
  36. package/dist/chunk-Z66IT5KL.js.map +1 -0
  37. package/dist/{cli-LNYSTDQM.js → cli-HSLIG7EX.js} +37 -37
  38. package/dist/{client-NWE4TCNO.js → client-Z43DNLJH.js} +3 -3
  39. package/dist/{detect-PXNM6TA7.js → detect-7NUD5B5R.js} +2 -2
  40. package/dist/{doctor-TI7EZ3RW.js → doctor-HJCWHAU4.js} +6 -6
  41. package/dist/{executor-F2YU7HXJ.js → executor-DO6QFC6G.js} +11 -10
  42. package/dist/{init-KG3TYVGE.js → init-4KVK7W2E.js} +9 -9
  43. package/dist/{installer-UMH7OJ5A.js → installer-N4UTEACX.js} +2 -2
  44. package/dist/{loader-NAVVZK63.js → loader-UDNUMEDA.js} +3 -2
  45. package/dist/{main-5PRQNEEE.js → main-4J4QZZTZ.js} +121 -62
  46. package/dist/main-4J4QZZTZ.js.map +1 -0
  47. package/dist/{open-5A27BCSB.js → open-7TXJQM3H.js} +5 -5
  48. package/dist/{post-compact-USAODKPQ.js → post-compact-7AEFVCZS.js} +7 -7
  49. package/dist/{post-tool-use-GMMSYBII.js → post-tool-use-TZINWWDH.js} +6 -6
  50. package/dist/{post-tool-use-failure-NZVSL2PO.js → post-tool-use-failure-TCFEU2GI.js} +7 -7
  51. package/dist/{pre-compact-LZ57DLUS.js → pre-compact-LO2VZCGR.js} +7 -7
  52. package/dist/{registry-M2Z5QBWH.js → registry-F3THYC5M.js} +4 -3
  53. package/dist/{remove-T3KE6C5N.js → remove-F77AAALE.js} +7 -7
  54. package/dist/{restart-YWDEVZUJ.js → restart-UEFDPMLT.js} +6 -6
  55. package/dist/{search-GKFDGELR.js → search-NHNVUAQQ.js} +6 -6
  56. package/dist/{server-AHUR6CWF.js → server-AZJSTQEK.js} +5 -5
  57. package/dist/{session-2ZEPLWW6.js → session-3HLC5KOD.js} +5 -5
  58. package/dist/{session-end-LWJYQAXX.js → session-end-FS46UARX.js} +6 -6
  59. package/dist/{session-start-WTA6GCOQ.js → session-start-46KPFV2H.js} +10 -10
  60. package/dist/{setup-llm-E7UU5IO7.js → setup-llm-JMWSNQ2C.js} +5 -5
  61. package/dist/src/agent/definitions/tasks/cortex-instructions.yaml +63 -41
  62. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +177 -21
  63. package/dist/src/agent/definitions/tasks/skill-generate.yaml +20 -6
  64. package/dist/src/agent/definitions/tasks/vault-evolve.yaml +65 -55
  65. package/dist/src/cli.js +1 -1
  66. package/dist/src/daemon/main.js +1 -1
  67. package/dist/src/hooks/post-tool-use.js +1 -1
  68. package/dist/src/hooks/session-end.js +1 -1
  69. package/dist/src/hooks/session-start.js +1 -1
  70. package/dist/src/hooks/stop.js +1 -1
  71. package/dist/src/hooks/user-prompt-submit.js +1 -1
  72. package/dist/src/mcp/server.js +1 -1
  73. package/dist/src/symbionts/manifests/opencode.yaml +7 -0
  74. package/dist/src/symbionts/templates/agents-starter.md +1 -1
  75. package/dist/{stats-DFG6S23S.js → stats-MKMETHMA.js} +6 -6
  76. package/dist/{stop-WRBTXEVT.js → stop-OUEX6KA4.js} +6 -6
  77. package/dist/{stop-failure-32MGIG2Q.js → stop-failure-2BWVNZEG.js} +7 -7
  78. package/dist/{subagent-start-VFGHQFVL.js → subagent-start-J4VV6DEE.js} +7 -7
  79. package/dist/{subagent-stop-663FXG3P.js → subagent-stop-JMLVEPIA.js} +7 -7
  80. package/dist/{task-completed-ZCQYEFMZ.js → task-completed-65CHMMKA.js} +7 -7
  81. package/dist/{team-JTI5CDUO.js → team-U2LDKIS4.js} +3 -3
  82. package/dist/ui/assets/{index-DGf1h-Ha.js → index-BUGor9dk.js} +1 -1
  83. package/dist/ui/index.html +1 -1
  84. package/dist/{update-3NBQTG32.js → update-ZSHVXWSQ.js} +7 -7
  85. package/dist/{user-prompt-submit-ME2TBKOS.js → user-prompt-submit-APMO6FVU.js} +6 -6
  86. package/dist/{version-GQAFBBPX.js → version-TXPPS3L5.js} +2 -2
  87. package/package.json +1 -1
  88. package/skills/myco-rules/SKILL.md +94 -0
  89. package/skills/{rules → myco-rules}/references/rules-bad-example.md +1 -1
  90. package/skills/{rules → myco-rules}/references/rules-good-example.md +1 -1
  91. package/dist/chunk-6LB7XELY.js.map +0 -1
  92. package/dist/chunk-CESKJD44.js.map +0 -1
  93. package/dist/chunk-CUDIZJY7.js +0 -36
  94. package/dist/chunk-CUDIZJY7.js.map +0 -1
  95. package/dist/chunk-JZS6GZ6T.js.map +0 -1
  96. package/dist/chunk-LVIY7P35.js.map +0 -1
  97. package/dist/chunk-NGH7U6A3.js.map +0 -1
  98. package/dist/chunk-NGROSFOH.js.map +0 -1
  99. package/dist/chunk-VHNRMM4O.js.map +0 -1
  100. package/dist/main-5PRQNEEE.js.map +0 -1
  101. package/skills/myco-curate/SKILL.md +0 -86
  102. package/skills/rules/SKILL.md +0 -214
  103. /package/dist/{agent-run-2JSYFOKU.js.map → agent-run-GEJBD2YD.js.map} +0 -0
  104. /package/dist/{agent-tasks-APFJIM2T.js.map → agent-tasks-5XSRGTRX.js.map} +0 -0
  105. /package/dist/{chunk-R2JIJBCL.js.map → chunk-6ALVMIB4.js.map} +0 -0
  106. /package/dist/{chunk-BUTL6IFS.js.map → chunk-ENZR5NG7.js.map} +0 -0
  107. /package/dist/{chunk-P66DLD6G.js.map → chunk-KTTSXYEK.js.map} +0 -0
  108. /package/dist/{chunk-5ZG4RMUH.js.map → chunk-N2DGFACQ.js.map} +0 -0
  109. /package/dist/{chunk-G6QIBNZM.js.map → chunk-NFO7BRCO.js.map} +0 -0
  110. /package/dist/{chunk-DJ3IHNYO.js.map → chunk-OZ3FBAK5.js.map} +0 -0
  111. /package/dist/{chunk-JR54LTPP.js.map → chunk-QDLVIW2O.js.map} +0 -0
  112. /package/dist/{chunk-ILJPRYES.js.map → chunk-USVFEWYL.js.map} +0 -0
  113. /package/dist/{chunk-75Z7UKDY.js.map → chunk-VRI56337.js.map} +0 -0
  114. /package/dist/{cli-LNYSTDQM.js.map → cli-HSLIG7EX.js.map} +0 -0
  115. /package/dist/{client-NWE4TCNO.js.map → client-Z43DNLJH.js.map} +0 -0
  116. /package/dist/{detect-PXNM6TA7.js.map → detect-7NUD5B5R.js.map} +0 -0
  117. /package/dist/{doctor-TI7EZ3RW.js.map → doctor-HJCWHAU4.js.map} +0 -0
  118. /package/dist/{executor-F2YU7HXJ.js.map → executor-DO6QFC6G.js.map} +0 -0
  119. /package/dist/{init-KG3TYVGE.js.map → init-4KVK7W2E.js.map} +0 -0
  120. /package/dist/{installer-UMH7OJ5A.js.map → installer-N4UTEACX.js.map} +0 -0
  121. /package/dist/{loader-NAVVZK63.js.map → loader-UDNUMEDA.js.map} +0 -0
  122. /package/dist/{open-5A27BCSB.js.map → open-7TXJQM3H.js.map} +0 -0
  123. /package/dist/{post-compact-USAODKPQ.js.map → post-compact-7AEFVCZS.js.map} +0 -0
  124. /package/dist/{post-tool-use-GMMSYBII.js.map → post-tool-use-TZINWWDH.js.map} +0 -0
  125. /package/dist/{post-tool-use-failure-NZVSL2PO.js.map → post-tool-use-failure-TCFEU2GI.js.map} +0 -0
  126. /package/dist/{pre-compact-LZ57DLUS.js.map → pre-compact-LO2VZCGR.js.map} +0 -0
  127. /package/dist/{registry-M2Z5QBWH.js.map → registry-F3THYC5M.js.map} +0 -0
  128. /package/dist/{remove-T3KE6C5N.js.map → remove-F77AAALE.js.map} +0 -0
  129. /package/dist/{restart-YWDEVZUJ.js.map → restart-UEFDPMLT.js.map} +0 -0
  130. /package/dist/{search-GKFDGELR.js.map → search-NHNVUAQQ.js.map} +0 -0
  131. /package/dist/{server-AHUR6CWF.js.map → server-AZJSTQEK.js.map} +0 -0
  132. /package/dist/{session-2ZEPLWW6.js.map → session-3HLC5KOD.js.map} +0 -0
  133. /package/dist/{session-end-LWJYQAXX.js.map → session-end-FS46UARX.js.map} +0 -0
  134. /package/dist/{session-start-WTA6GCOQ.js.map → session-start-46KPFV2H.js.map} +0 -0
  135. /package/dist/{setup-llm-E7UU5IO7.js.map → setup-llm-JMWSNQ2C.js.map} +0 -0
  136. /package/dist/{stats-DFG6S23S.js.map → stats-MKMETHMA.js.map} +0 -0
  137. /package/dist/{stop-WRBTXEVT.js.map → stop-OUEX6KA4.js.map} +0 -0
  138. /package/dist/{stop-failure-32MGIG2Q.js.map → stop-failure-2BWVNZEG.js.map} +0 -0
  139. /package/dist/{subagent-start-VFGHQFVL.js.map → subagent-start-J4VV6DEE.js.map} +0 -0
  140. /package/dist/{subagent-stop-663FXG3P.js.map → subagent-stop-JMLVEPIA.js.map} +0 -0
  141. /package/dist/{task-completed-ZCQYEFMZ.js.map → task-completed-65CHMMKA.js.map} +0 -0
  142. /package/dist/{team-JTI5CDUO.js.map → team-U2LDKIS4.js.map} +0 -0
  143. /package/dist/{update-3NBQTG32.js.map → update-ZSHVXWSQ.js.map} +0 -0
  144. /package/dist/{user-prompt-submit-ME2TBKOS.js.map → user-prompt-submit-APMO6FVU.js.map} +0 -0
  145. /package/dist/{version-GQAFBBPX.js.map → version-TXPPS3L5.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vault/types.ts","../src/mcp/tool-definitions.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const SessionFrontmatterSchema = z.object({\n type: z.literal('session'),\n id: z.string(),\n agent: z.string(),\n user: z.string(),\n started: z.string(),\n ended: z.string().optional(),\n parent: z.string().optional(),\n parent_reason: z.string().optional(),\n plan: z.string().optional(), // backward compat read path\n plans: z.array(z.string()).optional(), // new: multiple plans\n branch: z.string().optional(),\n tags: z.array(z.string()).default([]),\n tools_used: z.number().int().optional(),\n files_changed: z.number().int().optional(),\n});\n\nexport const PLAN_STATUSES = ['active', 'in_progress', 'completed', 'abandoned'] as const;\n\nexport const PlanFrontmatterSchema = z.object({\n type: z.literal('plan'),\n id: z.string(),\n status: z.enum(PLAN_STATUSES).default('active'),\n created: z.string(),\n author: z.string().optional(),\n tags: z.array(z.string()).default([]),\n});\n\nexport const OBSERVATION_TYPES = ['gotcha', 'bug_fix', 'decision', 'discovery', 'trade_off', 'cross-cutting'] as const;\n\nexport const SPORE_STATUSES = ['active', 'superseded', 'archived'] as const;\nexport type SporeStatus = (typeof SPORE_STATUSES)[number];\n\nexport const SporeFrontmatterSchema = z.object({\n type: z.literal('spore'),\n id: z.string(),\n observation_type: z.string(),\n status: z.enum(SPORE_STATUSES).default('active'),\n session: z.string().optional(),\n plan: z.string().optional(),\n superseded_by: z.string().optional(),\n consolidated_from: z.array(z.string()).optional(),\n created: z.string(),\n tags: z.array(z.string()).default([]),\n});\n\nexport const ARTIFACT_TYPES = ['spec', 'plan', 'rfc', 'doc', 'other'] as const;\nexport type ArtifactType = (typeof ARTIFACT_TYPES)[number];\n\nexport const ArtifactFrontmatterSchema = z.object({\n type: z.literal('artifact'),\n id: z.string(),\n artifact_type: z.enum(ARTIFACT_TYPES).default('other'),\n source_path: z.string(),\n title: z.string(),\n last_captured_by: z.string(),\n created: z.string(),\n updated: z.string(),\n tags: z.array(z.string()).default([]),\n});\n\nexport const TeamMemberFrontmatterSchema = z.object({\n type: z.literal('team-member'),\n user: z.string(),\n joined: z.string(),\n role: z.string().optional(),\n tags: z.array(z.string()).default([]),\n});\n\nexport type SessionFrontmatter = z.infer<typeof SessionFrontmatterSchema>;\nexport type PlanFrontmatter = z.infer<typeof PlanFrontmatterSchema>;\nexport type SporeFrontmatter = z.infer<typeof SporeFrontmatterSchema>;\nexport type ObservationType = SporeFrontmatter['observation_type'];\nexport type ArtifactFrontmatter = z.infer<typeof ArtifactFrontmatterSchema>;\nexport type TeamMemberFrontmatter = z.infer<typeof TeamMemberFrontmatterSchema>;\n\nexport type NoteFrontmatter =\n | SessionFrontmatter\n | PlanFrontmatter\n | SporeFrontmatter\n | ArtifactFrontmatter\n | TeamMemberFrontmatter;\n\nexport interface VaultNote<T extends NoteFrontmatter = NoteFrontmatter> {\n path: string;\n frontmatter: T;\n content: string;\n}\n\nconst schemasByType: Record<string, z.ZodSchema> = {\n session: SessionFrontmatterSchema,\n plan: PlanFrontmatterSchema,\n spore: SporeFrontmatterSchema,\n artifact: ArtifactFrontmatterSchema,\n 'team-member': TeamMemberFrontmatterSchema,\n};\n\nexport function parseNoteFrontmatter(data: Record<string, unknown>): NoteFrontmatter {\n const type = data.type as string;\n const schema = schemasByType[type];\n if (!schema) {\n throw new Error(`Unknown note type: ${type}. Known types: ${Object.keys(schemasByType).join(', ')}`);\n }\n // gray-matter and YAML.parse return Date objects for ISO date strings.\n // Coerce them to strings before Zod validation.\n const coerced = coerceDatesToStrings(data);\n return schema.parse(coerced) as NoteFrontmatter;\n}\n\nfunction coerceDatesToStrings(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value instanceof Date) {\n result[key] = value.toISOString();\n } else if (Array.isArray(value)) {\n result[key] = value.map((item) => item instanceof Date ? item.toISOString() : item);\n } else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n result[key] = coerceDatesToStrings(value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n","/**\n * MCP tool names, descriptions, and schema definitions.\n * Single source of truth for all tool metadata — referenced by the MCP server\n * and available to tests, logging, and documentation generators.\n */\nimport { OBSERVATION_TYPES, PLAN_STATUSES } from '../vault/types.js';\nimport { MCP_SEARCH_DEFAULT_LIMIT, MCP_SESSIONS_DEFAULT_LIMIT, MCP_SKILLS_DEFAULT_LIMIT } from '../constants.js';\n\n/** Plan statuses plus 'all' for filtering. */\nconst PLAN_STATUS_FILTER = [...PLAN_STATUSES, 'all'] as const;\nconst DEFAULT_CORTEX_PRIORITY = 100;\n\ninterface ToolInputSchema {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n}\n\nexport interface ToolCortexMetadata {\n guidance: string;\n priority?: number;\n requiresTeam?: boolean;\n requiresCollective?: boolean;\n}\n\n/**\n * MCP tool annotations. These follow the MCP spec's `annotations` envelope\n * so clients can show the right UI affordances (confirm-before-run for\n * destructive tools, quiet auto-run for read-only ones, etc.). Bundle D\n * makes these mandatory for every Myco-registered tool.\n */\nexport interface ToolAnnotations {\n /** True if the tool never mutates state. */\n readOnlyHint: boolean;\n /**\n * True if the tool can destroy data or start work that's hard to undo.\n * For multi-op tools, set true if ANY op is destructive and describe\n * the op matrix in the tool description.\n */\n destructiveHint: boolean;\n /** True if calling the tool twice with the same input is safe. */\n idempotentHint: boolean;\n /** True if the tool reaches outside the local vault (network, other machines). */\n openWorldHint: boolean;\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n inputSchema: ToolInputSchema;\n annotations?: ToolAnnotations;\n cortex?: ToolCortexMetadata;\n}\n\nexport function getToolCortexPriority(tool: Pick<ToolDefinition, 'cortex'>): number {\n return tool.cortex?.priority ?? DEFAULT_CORTEX_PRIORITY;\n}\n\n// --- Tool names ---\nexport const TOOL_SEARCH = 'myco_search';\nexport const TOOL_RECALL = 'myco_recall';\nexport const TOOL_REMEMBER = 'myco_remember';\nexport const TOOL_PLANS = 'myco_plans';\nexport const TOOL_SAVE_PLAN = 'myco_save_plan';\nexport const TOOL_SESSIONS = 'myco_sessions';\nexport const TOOL_TEAM = 'myco_team';\nexport const TOOL_GRAPH = 'myco_graph';\nexport const TOOL_SUPERSEDE = 'myco_supersede';\nexport const TOOL_CONSOLIDATE = 'myco_consolidate';\nexport const TOOL_CONTEXT = 'myco_context';\nexport const TOOL_SKILLS = 'myco_skills';\nexport const TOOL_SKILL_CANDIDATES = 'myco_skill_candidates';\nexport const TOOL_COLLECTIVE_SEARCH = 'collective_search';\nexport const TOOL_COLLECTIVE_PROJECTS = 'collective_projects';\nexport const TOOL_COLLECTIVE_PROJECT = 'collective_project';\nexport const TOOL_CORTEX = 'myco_cortex';\nexport const TOOL_RUNS = 'myco_runs';\nexport const TOOL_EVALUATIONS = 'myco_evaluations';\nexport const TOOL_WRITE_INTENTS = 'myco_write_intents';\nexport const TOOL_PHASE_AUDIT = 'myco_phase_audit';\nexport const TOOL_RESUME_RUN = 'myco_resume_run';\nexport const TOOL_DIGEST_REVISIONS = 'myco_digest_revisions';\n\n// --- Shared property descriptions (used by multiple tools) ---\nconst PROP_BRANCH = 'Git branch name to find related sessions and plans';\nconst PROP_SINCE = 'ISO timestamp — entries after this date';\nconst PROP_TAGS = 'Tags for discoverability — component names, technologies, concepts';\n\n// --- Tool definitions ---\nexport const TOOL_DEFINITIONS: ToolDefinition[] = [\n {\n name: TOOL_SEARCH,\n description: 'Search the vault for prior sessions, spores, plans, and artifacts. Use before making design decisions, when debugging non-obvious issues, or when wondering why code is structured a certain way.',\n cortex: {\n guidance: 'Use for prior decisions, bugs, and rationale when you know the topic but not the exact note.',\n priority: 20,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: { type: 'string', description: 'Natural language search query — describe what you are looking for' },\n type: { type: 'string', enum: ['session', 'plan', 'spore', 'all'], description: 'Filter by note type (default: all)' },\n limit: { type: 'number', description: `Max results (default: ${MCP_SEARCH_DEFAULT_LIMIT})` },\n },\n required: ['query'],\n },\n },\n {\n name: TOOL_RECALL,\n description: 'Look up a specific vault note by ID — returns the full content of a session, spore, or plan. Use when you have a note ID from search results or graph traversal and need the complete details.',\n cortex: {\n guidance: 'Use after search finds a promising result and you need the full note.',\n priority: 30,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n note_id: { type: 'string', description: 'Note ID to look up (e.g., \"session-abc123\", \"decision-xyz789\", \"plan-feature-x\")' },\n },\n required: ['note_id'],\n },\n },\n {\n name: TOOL_REMEMBER,\n description: 'Save a decision, gotcha, bug fix, discovery, or trade-off as a permanent spore. Use after making a key decision, fixing a tricky bug, discovering something non-obvious, or encountering a gotcha. Session association is derived by the daemon — the MCP client does not pass it.',\n cortex: {\n guidance: 'Use to save durable decisions, gotchas, discoveries, or bug fixes from this work.',\n priority: 90,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n content: { type: 'string', description: 'The observation — include context, reasoning, and what someone encountering this in the future needs to know' },\n type: { type: 'string', enum: OBSERVATION_TYPES, description: `Observation type: ${OBSERVATION_TYPES.join(', ')}` },\n tags: { type: 'array', items: { type: 'string' }, description: PROP_TAGS },\n },\n required: ['content', 'type'],\n },\n },\n {\n name: TOOL_PLANS,\n description: 'List or delete implementation plans. op: \"list\" (default) returns plan summaries — filter by status, session, or a single id. op: \"delete\" removes a plan by id; cross-machine rows require force_remote: true. Use list to check what work is in flight before starting new tasks; use delete when retiring obsolete plans.',\n annotations: {\n // Destructive because op: \"delete\" removes a plan and enqueues a tombstone.\n // Consumers should confirm before running this tool with op: \"delete\".\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use op: \"list\" before implementation when approved plans or specs may already exist; pass session to scope to the current work, or id to fetch a single plan with content.',\n priority: 50,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n op: { type: 'string', enum: ['list', 'delete'], description: 'Operation (default: \"list\")' },\n status: { type: 'string', enum: PLAN_STATUS_FILTER, description: 'Filter by status (default: all statuses); ignored for op: \"delete\"' },\n id: { type: 'string', description: 'Plan id. Required for op: \"delete\". For op: \"list\" returns that plan with content.' },\n session: { type: 'string', description: 'Filter list to plans belonging to this session; mutually exclusive with id.' },\n limit: { type: 'number', description: 'Max results for op: \"list\"' },\n force_remote: { type: 'boolean', description: 'Allow op: \"delete\" to remove a plan belonging to another machine. Enqueues a tombstone for team sync.' },\n },\n },\n },\n {\n name: TOOL_SAVE_PLAN,\n description: 'Persist a plan directly into Myco for a session. Use this when you generated or revised a plan and want it captured reliably. Pass exactly one of `source_path` or `plan_key` — `source_path` when the plan is also written to disk (so direct persistence and file capture reconcile to one logical plan), or `plan_key` for non-file-backed plans. The daemon rejects requests that set neither or both. Note: plan_key creates a stable namespace (session:<id>:key:<name>) distinct from transcript <tag> capture (session:<id>:tag:<name>) — the two do not merge. Dropping the transcript tag while also calling myco_save_plan with plan_key=tag will produce two separate rows.',\n cortex: {\n guidance: 'Use when you create or materially revise a plan and want it persisted to Myco. Pass `source_path` when the plan is also written to disk; otherwise use a stable `plan_key`. Note: `plan_key` rows are a separate namespace from transcript `<tag>` capture — reusing the same name in both channels creates two rows, not one.',\n priority: 60,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n session_id: { type: 'string', description: 'Session id the plan belongs to' },\n content: { type: 'string', description: 'Markdown plan content to persist' },\n source_path: { type: 'string', description: 'Path to the plan file when the plan is also written to disk. Pass this OR plan_key, never both.' },\n plan_key: { type: 'string', description: 'Stable key for non-file-backed plans (for example: primary). Pass this OR source_path, never both.' },\n title: { type: 'string', description: 'Optional explicit title. Defaults to the first Markdown H1, then file name or humanized plan_key.' },\n status: { type: 'string', enum: PLAN_STATUSES, description: `Plan status: ${PLAN_STATUSES.join(', ')}` },\n tags: { type: 'array', items: { type: 'string' }, description: PROP_TAGS },\n },\n required: ['session_id', 'content'],\n },\n },\n {\n name: TOOL_SESSIONS,\n description: 'Browse past coding sessions with summaries, tools used, and linked spores. Use to understand what work has been done on a feature or branch.',\n cortex: {\n guidance: 'Use when continuing related work or recovering recent implementation context.',\n priority: 40,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n plan: { type: 'string', description: 'Filter to the session linked to this plan id' },\n branch: { type: 'string', description: PROP_BRANCH },\n user: { type: 'string', description: 'Filter sessions by user' },\n since: { type: 'string', description: PROP_SINCE },\n status: { type: 'string', description: 'Filter by session status (e.g., active, completed)' },\n limit: { type: 'number', description: `Max results (default: ${MCP_SESSIONS_DEFAULT_LIMIT})` },\n },\n },\n },\n {\n name: TOOL_TEAM,\n description: 'List team members registered in the vault. Returns id, user, role, joined, and tags per member. Phase-1 scope: no filters.',\n cortex: {\n guidance: 'Use for current team topology and shared project context.',\n priority: 70,\n requiresTeam: true,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {},\n },\n },\n {\n name: TOOL_GRAPH,\n description: 'Traverse connections between records via graph edges — explore how sessions, spores, and plans relate to each other.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n note_id: { type: 'string', description: 'Note ID to start from (e.g., \"session-abc123\" or \"decision-xyz789\")' },\n direction: { type: 'string', enum: ['incoming', 'outgoing', 'both'], description: 'Link direction to follow (default: both)' },\n depth: { type: 'number', description: 'How many hops to traverse, 1-3 (default: 1)' },\n },\n required: ['note_id'],\n },\n },\n {\n name: TOOL_SUPERSEDE,\n description: 'Mark a spore as outdated and replaced by a newer one. Use when a decision was reversed, a gotcha was fixed, a discovery was wrong, or the codebase changed and an observation no longer applies. The old spore is preserved but marked superseded.',\n cortex: {\n guidance: 'Use when existing knowledge is outdated and should stop guiding future runs.',\n priority: 100,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n old_spore_id: { type: 'string', description: 'ID of the outdated spore (e.g., \"decision-abc123\")' },\n new_spore_id: { type: 'string', description: 'ID of the replacement spore' },\n reason: { type: 'string', description: 'Why the old spore is being superseded' },\n },\n required: ['old_spore_id', 'new_spore_id'],\n },\n },\n {\n name: TOOL_CONSOLIDATE,\n description: 'Merge 2+ related spores into a single comprehensive wisdom note. Inserts a new spore with the consolidated content; each source spore is marked superseded with a resolution_events row linking it to the new wisdom spore. Use when multiple observations describe aspects of the same insight, share a root cause, or would be more useful as one reference.',\n cortex: {\n guidance: 'Use when several related learnings should become one durable wisdom artifact.',\n priority: 110,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n source_spore_ids: { type: 'array', items: { type: 'string' }, description: 'IDs of the spores to merge (minimum 2)' },\n consolidated_content: { type: 'string', description: 'The merged, comprehensive content — synthesize, do not just concatenate' },\n observation_type: { type: 'string', enum: OBSERVATION_TYPES, description: `Type for the consolidated wisdom note: ${OBSERVATION_TYPES.join(', ')}` },\n tags: { type: 'array', items: { type: 'string' }, description: PROP_TAGS },\n reason: { type: 'string', description: 'Optional reason recorded on each resolution event' },\n },\n required: ['source_spore_ids', 'consolidated_content', 'observation_type'],\n },\n },\n {\n name: TOOL_CONTEXT,\n description: \"Retrieve Myco's pre-computed project digest — a rich, always-current synthesis of project history, decisions, patterns, active work, and institutional knowledge. Call this at the start of a new task or session to orient yourself on the project before taking action; call it again after long interruptions or when switching contexts. This is NOT a search — it's the project's accumulated understanding, served instantly. Available tiers: 1500 (executive briefing, one-screen overview), 5000 (deep onboarding, default), 10000 (comprehensive institutional knowledge). Prefer this over myco_search when you need broad project orientation; use myco_search when you need to find specific prior decisions or bug fixes.\",\n cortex: {\n guidance: 'Use for broad project orientation or when you want the current digest before planning changes.',\n priority: 10,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n tier: {\n type: 'number',\n enum: [1500, 5000, 10000],\n description: 'Token budget tier. Larger tiers include more detail. Default: 5000.',\n },\n },\n },\n },\n {\n name: TOOL_SKILLS,\n description: 'List and inspect skills generated by Myco. Use to see what skills are active, check skill details, or find skills by status.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: { type: 'string', description: 'Get a specific skill by ID or name' },\n status: { type: 'string', description: 'Filter by status: active, stale, retired' },\n limit: { type: 'number', description: `Max results (default: ${MCP_SKILLS_DEFAULT_LIMIT})` },\n },\n },\n },\n {\n name: TOOL_SKILL_CANDIDATES,\n description: 'List and manage skill candidates — observations identified as potential skills. Use to see pending candidates, approve, or dismiss them.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: { type: 'string', description: 'Get a specific candidate by ID' },\n action: { type: 'string', enum: ['list', 'approve', 'dismiss'], description: \"Action to perform (default: 'list')\" },\n status: { type: 'string', description: 'Filter by status: identified, approved, generated, dismissed' },\n limit: { type: 'number', description: `Max results (default: ${MCP_SKILLS_DEFAULT_LIMIT})` },\n },\n },\n },\n {\n name: TOOL_CORTEX,\n description: 'Cortex instruction + prompt-builder surface. op: \"get\" returns the current session-start instructions snapshot. op: \"refresh\" triggers the cortex-instructions task to regenerate them. op: \"build_prompt\" starts the cortex-prompt-builder task for a goal (required) and optional symbiont. op: \"get_prompt_result\" polls a prompt-builder run by run_id. Refresh and build_prompt are not read-only — they start background runs.',\n annotations: {\n // Mixed: get/get_prompt_result are read-only, refresh/build_prompt kick\n // off background work. Mark conservatively — consumers should not silently\n // auto-run this tool.\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use op: \"get\" to read your own session-start Cortex instructions; use op: \"build_prompt\" + \"get_prompt_result\" when you need the prompt-builder to draft a prompt for a specific goal.',\n priority: 95,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n op: { type: 'string', enum: ['get', 'refresh', 'build_prompt', 'get_prompt_result'], description: 'Cortex operation' },\n run_id: { type: 'string', description: 'Required for op: \"get_prompt_result\"' },\n goal: { type: 'string', description: 'Required for op: \"build_prompt\" — the task the prompt will be built for' },\n symbiont: { type: 'string', description: 'Optional symbiont/agent name the prompt should be tuned for; defaults to the first enabled symbiont' },\n },\n required: ['op'],\n },\n },\n {\n name: TOOL_RUNS,\n description: 'Read agent run history. op: \"list\" (default) returns recent runs with runtime/provider/model/token/cost/reasoning fields — filter by task, agent_id, limit. op: \"get\" with id returns a single run including write_intents totals and duration_ms. Use after a run completes to check your own token budget, cost, and reasoning level — particularly useful when debugging a run that exhausted context.',\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use op: \"get\" with your run id to check your own token budget, cost, and reasoning level — especially after a run that exhausted context or failed. Use op: \"list\" to browse recent runs for a task.',\n priority: 85,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n op: { type: 'string', enum: ['list', 'get'], description: 'Operation (default: \"list\")' },\n id: { type: 'string', description: 'Required for op: \"get\" — the run id' },\n task: { type: 'string', description: 'Filter op: \"list\" by task name' },\n agent_id: { type: 'string', description: 'Filter op: \"list\" by agent id' },\n limit: { type: 'number', description: 'Max results for op: \"list\" (default: 50)' },\n },\n },\n },\n {\n name: TOOL_EVALUATIONS,\n description: 'Create, list, or fetch agent evaluations. An evaluation fans out a single task across a cartesian product of (runtime × reasoning × model) cells so outputs can be compared side by side. op: \"list\" (default) returns newest-first summaries with an optional limit. op: \"get\" with id returns the evaluation + child runs + aggregate stats. op: \"create\" requires task_id and matrix; cells execute sequentially in the background — the response returns the evaluationId + cellCount. op: \"create\" is NOT read-only; it starts background runs.',\n annotations: {\n // Mixed ops: list/get are read-only, create kicks off background runs.\n // Mark conservatively so clients confirm before auto-running with op: \"create\".\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use op: \"list\" to see recent matrix evaluations, op: \"get\" to inspect cells + aggregate stats, and op: \"create\" to fan a task out across runtime/reasoning/model cells for side-by-side comparison.',\n priority: 88,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n op: { type: 'string', enum: ['list', 'get', 'create'], description: 'Operation (default: \"list\")' },\n status: { type: 'string', description: 'Filter op: \"list\" by status (reserved; currently ignored by the route)' },\n limit: { type: 'number', description: 'Max results for op: \"list\" (default: 50)' },\n id: { type: 'string', description: 'Required for op: \"get\" — the evaluation id' },\n task_id: { type: 'string', description: 'Required for op: \"create\" — id of the agent task to evaluate' },\n matrix: {\n type: 'object',\n description: 'Required for op: \"create\". Matrix payload: { runtimes?, reasoningLevels?, models?, dryRun?, notes?, phases? }. Empty arrays expand to defaults. See /api/agent/evaluations POST body for full shape.',\n },\n notes: { type: 'string', description: 'Optional notes stored alongside the evaluation row (op: \"create\" only)' },\n },\n },\n },\n {\n name: TOOL_WRITE_INTENTS,\n description: 'Inspect the write-intents recorded during a dry-run — what the agent would have done (tool_name, tool_input, synthetic_output) without actually writing. Paginated via limit (default 500, max 5000) and offset. Use with myco_runs to verify safety before re-running the same task without dry_run.',\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use after a dry-run to inspect what writes the agent would have performed — close the \"dry-run → verify → real-run\" loop before repeating the task without dry_run.',\n priority: 86,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n run_id: { type: 'string', description: 'The run id whose write-intents you want to inspect' },\n limit: { type: 'number', description: 'Max results (default: 500, max: 5000)' },\n offset: { type: 'number', description: 'Pagination offset (default: 0)' },\n },\n required: ['run_id'],\n },\n },\n {\n name: TOOL_PHASE_AUDIT,\n description: 'Read the per-phase audit trail for an agent run — what each phase did, its cost, tool-call counts, reasoning level, and any write intents. Returns a joined view over agent_runs, agent_reports, agent_turns, usage_data, checkpoints, and (for dry runs) agent_run_write_intents. Essential for debugging a failed or mis-executing run.',\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use when debugging a failed or mis-executing run — returns the per-phase cost, tool counts, reasoning level, and write intents in one payload.',\n priority: 87,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n run_id: { type: 'string', description: 'The run id whose phase audit you want to inspect' },\n },\n required: ['run_id'],\n },\n },\n {\n name: TOOL_RESUME_RUN,\n description: 'Resume a paused or interrupted agent run. The run must be in a resumable state (resumable=1 AND status=\"failed\" per the route) — check status via myco_runs first. The resume starts a new background phase and returns immediately with {ok, message, runId}. NOT idempotent: each successful call starts a fresh phase.',\n annotations: {\n // Starts a new background phase; mark as mutating + non-idempotent so\n // clients confirm before repeating. Not \"destructive\" (no data is\n // removed) but also not \"read-only\".\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use to resume a paused or interrupted agent run after verifying (via myco_runs) that its resumable flag is set and its status is \"failed\".',\n priority: 89,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: { type: 'string', description: 'The run id to resume' },\n mode: { type: 'string', enum: ['manual', 'scheduled'], description: 'Resume mode (default: \"manual\"). Scheduled is reserved for the daemon scheduler.' },\n },\n required: ['id'],\n },\n },\n {\n name: TOOL_DIGEST_REVISIONS,\n description: 'List historical digest revisions for the given (agent_id, tier). Revisions are append-only, so this surface shows how the project\\'s digest has evolved over time. tier is required; agent_id defaults to the primary agent on the daemon side. Restore (rolling a past revision back into the live digest) is intentionally UI-only and is NOT exposed via MCP.',\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n cortex: {\n guidance: 'Use to see how the project digest has evolved for a given tier — restore is UI-only.',\n priority: 92,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent_id: { type: 'string', description: 'Optional — defaults to the primary agent on the daemon side' },\n tier: { type: 'number', description: 'Required — the digest tier (for example 1500, 5000, 10000)' },\n limit: { type: 'number', description: 'Max results (default: 50)' },\n },\n required: ['tier'],\n },\n },\n];\n\nexport const COLLECTIVE_TOOL_DEFINITIONS: ToolDefinition[] = [\n {\n name: TOOL_COLLECTIVE_SEARCH,\n description: 'Search across connected projects in the active Myco Collective. Results include project attribution.',\n cortex: {\n guidance: 'Use for cross-project knowledge across the connected collective.',\n priority: 80,\n requiresCollective: true,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: { type: 'string', description: 'Natural language search query across the connected Collective projects' },\n project: { type: 'string', description: 'Optional project id or project name filter' },\n limit: { type: 'number', description: `Max results (default: ${MCP_SEARCH_DEFAULT_LIMIT})` },\n },\n required: ['query'],\n },\n },\n {\n name: TOOL_COLLECTIVE_PROJECTS,\n description: 'List the projects connected to the active Myco Collective.',\n cortex: {\n guidance: 'Use to discover relevant collective projects before drilling deeper.',\n priority: 81,\n requiresCollective: true,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {},\n },\n },\n {\n name: TOOL_COLLECTIVE_PROJECT,\n description: 'Get metadata for a single project connected to the active Myco Collective.',\n cortex: {\n guidance: 'Use when you know the collective project and need its focused context.',\n priority: 82,\n requiresCollective: true,\n },\n inputSchema: {\n type: 'object' as const,\n properties: {\n project: { type: 'string', description: 'Project id or project name' },\n include_digest: { type: 'boolean', description: 'Request digest information when available' },\n },\n required: ['project'],\n },\n },\n] as const;\n"],"mappings":"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","names":[]}
@@ -11,7 +11,7 @@ var cached;
11
11
  function getPluginVersion() {
12
12
  if (cached) return cached;
13
13
  if (true) {
14
- cached = "0.21.0";
14
+ cached = "0.21.1";
15
15
  return cached;
16
16
  }
17
17
  const root = findPackageRoot(path.dirname(fileURLToPath(import.meta.url)));
@@ -32,4 +32,4 @@ function getPluginVersion() {
32
32
  export {
33
33
  getPluginVersion
34
34
  };
35
- //# sourceMappingURL=chunk-BUTL6IFS.js.map
35
+ //# sourceMappingURL=chunk-ENZR5NG7.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-BUTL6IFS.js";
4
+ } from "./chunk-ENZR5NG7.js";
5
5
  import {
6
6
  DAEMON_CLIENT_TIMEOUT_MS,
7
7
  DAEMON_HEALTH_CHECK_TIMEOUT_MS,
@@ -197,4 +197,4 @@ export {
197
197
  resolveCliEntryPath,
198
198
  DaemonClient
199
199
  };
200
- //# sourceMappingURL=chunk-P66DLD6G.js.map
200
+ //# sourceMappingURL=chunk-KTTSXYEK.js.map
@@ -0,0 +1,17 @@
1
+ import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
+
3
+ // src/utils/error-message.ts
4
+ function errorMessage(err) {
5
+ if (err instanceof Error) return err.message || err.constructor.name || "Error";
6
+ if (typeof err === "string") return err || "Empty string error";
7
+ try {
8
+ return JSON.stringify(err);
9
+ } catch {
10
+ return "Unserializable error";
11
+ }
12
+ }
13
+
14
+ export {
15
+ errorMessage
16
+ };
17
+ //# sourceMappingURL=chunk-LQIPXVDH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/error-message.ts"],"sourcesContent":["/**\n * Extract a human-readable error message from an unknown thrown value.\n *\n * Handles Error instances, strings, and arbitrary objects. Never throws.\n */\nexport function errorMessage(err: unknown): string {\n if (err instanceof Error) return err.message || err.constructor.name || 'Error';\n if (typeof err === 'string') return err || 'Empty string error';\n try { return JSON.stringify(err); } catch { return 'Unserializable error'; }\n}\n"],"mappings":";;;AAKO,SAAS,aAAa,KAAsB;AACjD,MAAI,eAAe,MAAO,QAAO,IAAI,WAAW,IAAI,YAAY,QAAQ;AACxE,MAAI,OAAO,QAAQ,SAAU,QAAO,OAAO;AAC3C,MAAI;AAAE,WAAO,KAAK,UAAU,GAAG;AAAA,EAAG,QAAQ;AAAE,WAAO;AAAA,EAAwB;AAC7E;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-ZXZPJJN3.js";
5
5
  import {
6
6
  loadManifests
7
- } from "./chunk-NGROSFOH.js";
7
+ } from "./chunk-Z66IT5KL.js";
8
8
  import {
9
9
  STDIN_TIMEOUT_MS
10
10
  } from "./chunk-6C6QZ4PM.js";
@@ -108,4 +108,4 @@ export {
108
108
  readStdin,
109
109
  normalizeHookInput
110
110
  };
111
- //# sourceMappingURL=chunk-5ZG4RMUH.js.map
111
+ //# sourceMappingURL=chunk-N2DGFACQ.js.map
@@ -10,7 +10,7 @@ import {
10
10
  COLLECTIVE_TOOL_DEFINITIONS,
11
11
  TOOL_DEFINITIONS,
12
12
  getToolCortexPriority
13
- } from "./chunk-CESKJD44.js";
13
+ } from "./chunk-EEOJWLMP.js";
14
14
  import {
15
15
  getDatabase
16
16
  } from "./chunk-MYX5NCRH.js";
@@ -608,11 +608,13 @@ function updateSporeStatus(id, status, updatedAt) {
608
608
  import { createHash } from "crypto";
609
609
  var MAX_COLLECTIVE_CAPABILITY_LABELS = 4;
610
610
  var ALL_CORTEX_TOOL_DEFINITIONS = [...TOOL_DEFINITIONS, ...COLLECTIVE_TOOL_DEFINITIONS];
611
- var RECENT_SESSION_LIMIT = 3;
612
- var RECENT_SPORE_LIMIT = 4;
611
+ var RECENT_SESSION_LIMIT = 5;
612
+ var RECENT_WISDOM_SPORE_LIMIT = 3;
613
+ var RECENT_DECISION_SPORE_LIMIT = 3;
614
+ var RECENT_DISCOVERY_SPORE_LIMIT = 3;
613
615
  var RECENT_PLAN_LIMIT = 3;
614
- var CONTENT_PREVIEW_MAX_CHARS = 240;
615
- var DIGEST_EXCERPT_MAX_CHARS = 900;
616
+ var CONTENT_PREVIEW_MAX_CHARS = 360;
617
+ var DIGEST_EXCERPT_MAX_CHARS = 1800;
616
618
  var JSON_INDENT = 2;
617
619
  var 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`.";
618
620
  function toCortexToolGuidance(tool) {
@@ -697,29 +699,28 @@ function truncatePreview(text, maxChars = CONTENT_PREVIEW_MAX_CHARS) {
697
699
  }
698
700
  function formatRecentSessions() {
699
701
  const sessions = listSessions({
700
- includeActive: true,
702
+ includeActive: false,
701
703
  limit: RECENT_SESSION_LIMIT
702
704
  });
703
705
  if (sessions.length === 0) return "No recent sessions are available.";
704
706
  return sessions.map((session) => {
705
- const parts = [
706
- `- ${session.title ?? session.id}`,
707
- session.branch ? `branch=${session.branch}` : null,
708
- truncatePreview(session.summary)
709
- ].filter(Boolean);
710
- return parts.join(" \u2014 ");
707
+ const head = `- ${session.title ?? session.id}${session.branch ? ` (branch=${session.branch})` : ""}`;
708
+ const body = truncatePreview(session.summary);
709
+ return body ? `${head}
710
+ ${body}` : head;
711
711
  }).join("\n");
712
712
  }
713
- function formatRecentSpores() {
713
+ function formatSporesOfType(observationType, limit) {
714
714
  const spores = listSpores({
715
- includeActive: true,
715
+ observation_type: observationType,
716
+ includeActive: false,
716
717
  status: "active",
717
- limit: RECENT_SPORE_LIMIT
718
+ limit
718
719
  });
719
- if (spores.length === 0) return "No recent spores are available.";
720
+ if (spores.length === 0) return `No recent ${observationType} spores are available.`;
720
721
  return spores.map((spore) => {
721
722
  const parts = [
722
- `- [${spore.observation_type}] ${truncatePreview(spore.content)}`,
723
+ `- ${truncatePreview(spore.content)}`,
723
724
  spore.session_id ? `session=${spore.session_id}` : null
724
725
  ].filter(Boolean);
725
726
  return parts.join(" \u2014 ");
@@ -753,7 +754,9 @@ async function buildCortexInstructionsInput(config, getTeamClient) {
753
754
  const capabilitySummary = buildCapabilitySummary(capabilities);
754
755
  const retrievalGuidance = buildRetrievalGuidanceLines(capabilities);
755
756
  const recentSessions = formatRecentSessions();
756
- const recentSpores = formatRecentSpores();
757
+ const recentWisdomSpores = formatSporesOfType("wisdom", RECENT_WISDOM_SPORE_LIMIT);
758
+ const recentDecisionSpores = formatSporesOfType("decision", RECENT_DECISION_SPORE_LIMIT);
759
+ const recentDiscoverySpores = formatSporesOfType("discovery", RECENT_DISCOVERY_SPORE_LIMIT);
757
760
  const recentPlans = formatRecentPlans();
758
761
  const digestExcerpt = formatDigestExcerpt(config);
759
762
  const input = {
@@ -766,7 +769,9 @@ async function buildCortexInstructionsInput(config, getTeamClient) {
766
769
  capabilities,
767
770
  digestExcerpt,
768
771
  recentSessions,
769
- recentSpores,
772
+ recentWisdomSpores,
773
+ recentDecisionSpores,
774
+ recentDiscoverySpores,
770
775
  recentPlans,
771
776
  skillsNote: CORTEX_SKILLS_NOTE
772
777
  };
@@ -801,8 +806,14 @@ async function buildCortexInstructionsInput(config, getTeamClient) {
801
806
  "## Recent sessions",
802
807
  recentSessions,
803
808
  "",
804
- "## Recent spores",
805
- recentSpores,
809
+ "## Recent wisdom spores",
810
+ recentWisdomSpores,
811
+ "",
812
+ "## Recent decision spores",
813
+ recentDecisionSpores,
814
+ "",
815
+ "## Recent discovery spores",
816
+ recentDiscoverySpores,
806
817
  "",
807
818
  "## Active plans",
808
819
  recentPlans
@@ -844,4 +855,4 @@ export {
844
855
  buildCortexInstructionsInput,
845
856
  buildScheduledCortexInstruction
846
857
  };
847
- //# sourceMappingURL=chunk-F3OEQYLS.js.map
858
+ //# sourceMappingURL=chunk-N7Z3LUEZ.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 = 3;\nconst RECENT_SPORE_LIMIT = 4;\nconst RECENT_PLAN_LIMIT = 3;\nconst CONTENT_PREVIEW_MAX_CHARS = 240;\nconst DIGEST_EXCERPT_MAX_CHARS = 900;\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: true,\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 parts = [\n `- ${session.title ?? session.id}`,\n session.branch ? `branch=${session.branch}` : null,\n truncatePreview(session.summary),\n ].filter(Boolean);\n return parts.join(' — ');\n }).join('\\n');\n}\n\nfunction formatRecentSpores(): string {\n const spores = listSpores({\n includeActive: true,\n status: 'active',\n limit: RECENT_SPORE_LIMIT,\n });\n if (spores.length === 0) return 'No recent spores are available.';\n\n return spores.map((spore) => {\n const parts = [\n `- [${spore.observation_type}] ${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 recentSpores = formatRecentSpores();\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 recentSpores,\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 spores',\n recentSpores,\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":";;;;;;;;;;;;;;;;;;;;;;;;;AAGA,IAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,2BAA2B,KAAK,IAAI;AAC3D,IAAM,iCAAiC;AAuBvC,SAAS,wBAAwB,KAAqD;AACpF,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,SAAS,IAAI;AAAA,IACb,YAAY,IAAI;AAAA,IAChB,eAAgB,IAAI,iBAA4B;AAAA,IAChD,cAAc,IAAI;AAAA,IAClB,YAAa,IAAI,cAAyB;AAAA,IAC1C,WAAY,IAAI,aAAwB;AAAA,EAC1C;AACF;AAEO,SAAS,yBAAyB,OAAwD;AAC/F,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,MAAM,MAAM,GAAG,MAAM,QAAQ,IAAI,8BAA8B;AAE1E,QAAM,MAAM,GAAG;AAAA,IACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAWa,cAAc;AAAA,EAC7B,EAAE;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM,iBAAiB;AAAA,IACvB,MAAM;AAAA,IACN,MAAM,cAAc,iBAAiB;AAAA,EACvC;AAEA,SAAO,wBAAwB,GAAG;AACpC;AAEO,SAAS,sBAAsB,SAA+C;AACnF,QAAM,KAAK,YAAY;AACvB,QAAM,MAAM,GAAG;AAAA,IACb,UAAU,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1B,EAAE,IAAI,OAAO;AACb,SAAO,MAAM,wBAAwB,GAAG,IAAI;AAC9C;;;ACVA,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAMA,kBAAiB,gBAAgB,KAAK,IAAI;AAOhD,SAAS,mBAAmB,KAAgD;AAC1E,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,IACb,gBAAiB,IAAI,kBAA6B;AAAA,IAClD,cAAc,IAAI;AAAA,IAClB,YAAa,IAAI,cAAyB;AAAA,IAC1C,WAAY,IAAI,aAAwB;AAAA,EAC1C;AACF;AAmBO,SAAS,oBACd,MACA,UAAsC,CAAC,GACd;AACzB,MAAI,QAAQ,OAAQ,QAAO;AAE3B,QAAM,KAAK,YAAY;AAOvB,SAAO,GAAG,YAAY,MAAM;AAG1B,UAAM,cAAc,GAAG;AAAA,MACrB,UAAUA,eAAc;AAAA,IAC1B,EAAE,IAAI,KAAK,UAAU,KAAK,IAAI;AAE9B,QAAI,aAAa;AACf,YAAM,kBAAkB,GAAG;AAAA,QACzB;AAAA;AAAA;AAAA;AAAA,MAIF,EAAE,IAAI,KAAK,UAAU,KAAK,IAAI;AAE9B,SAAG;AAAA,QACD;AAAA;AAAA;AAAA,MAGF,EAAE;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,QAAQ,YAAY;AAAA,QACpB,QAAQ,SAAS;AAAA,QACjB,iBAAiB,MAAM;AAAA,QACvB,aAAa;AAAA,MACf;AAAA,IACF;AAEA,OAAG;AAAA,MACD;AAAA;AAAA;AAAA;AAAA;AAAA,IAKF,EAAE,IAAI,KAAK,UAAU,KAAK,MAAM,KAAK,SAAS,KAAK,YAAY;AAG/D,UAAM,MAAM,GAAG;AAAA,MACb,UAAUA,eAAc;AAAA,IAC1B,EAAE,IAAI,KAAK,UAAU,KAAK,IAAI;AAE9B,WAAO,mBAAmB,GAA8B;AAAA,EAC1D,CAAC,EAAE;AACL;AAOO,SAAS,iBACd,SACA,MACyB;AACzB,QAAM,KAAK,YAAY;AAEvB,QAAM,MAAM,GAAG;AAAA,IACb,UAAUA,eAAc;AAAA;AAAA,EAE1B,EAAE,IAAI,SAAS,IAAI;AAEnB,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,mBAAmB,GAAG;AAC/B;AAKO,SAAS,mBACd,SACoB;AACpB,QAAM,KAAK,YAAY;AACvB,QAAM,mBAAmB,aAAa,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAE9D,QAAM,OAAO,GAAG;AAAA,IACd,UAAUA,eAAc;AAAA;AAAA,uCAEW,gBAAgB;AAAA;AAAA,EAErD,EAAE,IAAI,SAAS,GAAG,YAAY;AAE9B,SAAO,KAAK,IAAI,kBAAkB;AACpC;AAMA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,kBAAkB,iBAAiB,KAAK,IAAI;AAElD,SAAS,cAAc,KAAwD;AAC7E,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,IACb,UAAW,IAAI,YAAuB;AAAA,IACtC,QAAS,IAAI,UAAqB;AAAA,IAClC,oBAAqB,IAAI,sBAAiC;AAAA,IAC1D,YAAY,IAAI;AAAA,EAClB;AACF;AAMO,SAAS,oBACd,SAC4B;AAC5B,QAAM,KAAK,YAAY;AACvB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,OAAO,GAAG;AAAA,IACd,UAAU,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3B,EAAE,IAAI,QAAQ,SAAS,QAAQ,MAAM,KAAK;AAC1C,SAAO,KAAK,IAAI,aAAa;AAC/B;AAyBO,SAAS,sBACd,SACoC;AACpC,QAAM,KAAK,YAAY;AAEvB,QAAM,WAAW,GAAG;AAAA,IAClB,UAAU,eAAe;AAAA;AAAA;AAAA,EAG3B,EAAE,IAAI,QAAQ,UAAU;AAExB,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,UAAU,SAAS;AACzB,QAAM,OAAO,SAAS;AACtB,QAAM,gBAAgB,SAAS;AAC/B,QAAM,MAAM,aAAa;AAIzB,SAAO,GAAG,YAAY,MAAM;AAG1B,UAAM,aAAa,GAAG;AAAA,MACpB,UAAUA,eAAc;AAAA,IAC1B,EAAE,IAAI,SAAS,IAAI;AAEnB,QAAI,gBAA+B;AACnC,QAAI,YAAY;AACd,YAAM,kBAAkB,GAAG;AAAA,QACzB;AAAA;AAAA;AAAA;AAAA,MAIF,EAAE,IAAI,SAAS,IAAI;AAEnB,YAAM,OAAO,GAAG;AAAA,QACd;AAAA;AAAA;AAAA,MAGF,EAAE;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,KAAK,UAAU,EAAE,aAAa,QAAQ,WAAW,CAAC;AAAA,QAClD,QAAQ,SAAS;AAAA,QACjB,iBAAiB,MAAM;AAAA,QACvB;AAAA,MACF;AACA,sBAAgB,OAAO,KAAK,eAAe;AAAA,IAC7C;AAGA,OAAG;AAAA,MACD;AAAA;AAAA;AAAA;AAAA;AAAA,IAKF,EAAE,IAAI,SAAS,MAAM,eAAe,GAAG;AAEvC,UAAM,WAAW,GAAG;AAAA,MAClB,UAAUA,eAAc;AAAA,IAC1B,EAAE,IAAI,SAAS,IAAI;AAEnB,WAAO;AAAA,MACL,KAAK,mBAAmB,QAAQ;AAAA,MAChC;AAAA,IACF;AAAA,EACF,CAAC,EAAE;AACL;;;AChWA,IAAM,qBAAqB;AAG3B,IAAM,iBAAiB;AAGvB,IAAM,oBAAoB;AAwD1B,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAMC,kBAAiB,aAAa,KAAK,IAAI;AAO7C,SAAS,UAAU,KAAuC;AACxD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,aAAa,IAAI;AAAA,IACjB,QAAQ,IAAI;AAAA,IACZ,QAAS,IAAI,UAAqB;AAAA,IAClC,OAAQ,IAAI,SAAoB;AAAA,IAChC,SAAU,IAAI,WAAsB;AAAA,IACpC,aAAc,IAAI,eAA0B;AAAA,IAC5C,MAAO,IAAI,QAAmB;AAAA,IAC9B,YAAa,IAAI,cAAyB;AAAA,IAC1C,iBAAkB,IAAI,mBAA8B;AAAA,IACpD,cAAe,IAAI,gBAA2B;AAAA,IAC9C,WAAW,IAAI;AAAA,IACf,UAAW,IAAI,YAAuB;AAAA,IACtC,YAAY,IAAI;AAAA,IAChB,YAAa,IAAI,cAAyB;AAAA,IAC1C,YAAa,IAAI,cAAyB;AAAA,IAC1C,WAAY,IAAI,aAAwB;AAAA,EAC1C;AACF;AAWO,SAAS,WAAW,MAA2B;AACpD,QAAM,KAAK,YAAY;AAEvB,KAAG;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BF,EAAE;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,UAAU;AAAA,IACf,KAAK,UAAU;AAAA,IACf,KAAK,SAAS;AAAA,IACd,KAAK,WAAW;AAAA,IAChB,KAAK,eAAe;AAAA,IACpB,KAAK,QAAQ;AAAA,IACb,KAAK,cAAc;AAAA,IACnB,KAAK,mBAAmB;AAAA,IACxB,KAAK,gBAAgB;AAAA,IACrB,KAAK,aAAa;AAAA,IAClB,KAAK;AAAA,IACL,KAAK,cAAc;AAAA,IACnB,KAAK,cAAc,iBAAiB;AAAA,EACtC;AAEA,QAAM,MAAM;AAAA,IACV,GAAG,QAAQ,UAAUA,eAAc,mCAAmC,EAAE,IAAI,KAAK,WAAW;AAAA,EAC9F;AAEA,UAAQ,SAAS,GAAG;AAEpB,SAAO;AACT;AAOO,SAAS,QAAQ,IAA4B;AAClD,QAAM,KAAK,YAAY;AAEvB,QAAM,MAAM,GAAG;AAAA,IACb,UAAUA,eAAc;AAAA,EAC1B,EAAE,IAAI,EAAE;AAER,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,UAAU,GAAG;AACtB;AAOO,SAAS,oBAAoB,YAAoC;AACtE,QAAM,KAAK,YAAY;AAEvB,QAAM,MAAM,GAAG;AAAA,IACb,UAAUA,eAAc;AAAA,EAC1B,EAAE,IAAI,UAAU;AAEhB,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,UAAU,GAAG;AACtB;AAOO,SAAS,WAAW,IAA4B;AACrD,QAAM,KAAK,YAAY;AACvB,QAAM,MAAM,QAAQ,EAAE;AACtB,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,OAAO,GAAG,QAAQ,gCAAgC,EAAE,IAAI,EAAE;AAChE,MAAI,KAAK,YAAY,EAAG,QAAO;AAE/B,MAAI,kBAAkB,GAAG;AACvB,kBAAc;AAAA,MACZ,YAAY;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,WAAW;AAAA,MACX,SAAS,KAAK,UAAU;AAAA,QACtB,IAAI,IAAI;AAAA,QACR,aAAa,IAAI;AAAA,QACjB,OAAO,IAAI;AAAA,MACb,CAAC;AAAA,MACD,YAAY,iBAAiB;AAAA,MAC7B,YAAY,aAAa;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKO,SAAS,UACd,UAA4B,CAAC,GAClB;AACX,QAAM,KAAK,YAAY;AAEvB,QAAM,aAAuB,CAAC;AAC9B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,WAAW,QAAW;AAChC,eAAW,KAAK,YAAY;AAC5B,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAEA,QAAM,QAAQ,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAC5E,QAAM,QAAQ,QAAQ,SAAS;AAE/B,SAAO,KAAK,KAAK;AAEjB,QAAM,OAAO,GAAG;AAAA,IACd,UAAUA,eAAc;AAAA;AAAA,OAErB,KAAK;AAAA;AAAA;AAAA,EAGV,EAAE,IAAI,GAAG,MAAM;AAEf,SAAO,KAAK,IAAI,SAAS;AAC3B;AAKO,SAAS,mBAAmB,WAA8B;AAC/D,QAAM,KAAK,YAAY;AAEvB,QAAM,OAAO,GAAG;AAAA,IACd,UAAUA,eAAc;AAAA;AAAA;AAAA;AAAA,EAI1B,EAAE,IAAI,SAAS;AAEf,SAAO,KAAK,IAAI,SAAS;AAC3B;;;AChSA,IAAMC,sBAAqB;AAG3B,IAAMC,kBAAiB;AAGhB,IAAM,qBAAqB;AA0ElC,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAMC,kBAAiB,cAAc,KAAK,IAAI;AAO9C,SAAS,WAAW,KAAwC;AAC1D,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,YAAa,IAAI,cAAyB;AAAA,IAC1C,iBAAkB,IAAI,mBAA8B;AAAA,IACpD,kBAAkB,IAAI;AAAA,IACtB,QAAQ,IAAI;AAAA,IACZ,SAAS,IAAI;AAAA,IACb,SAAU,IAAI,WAAsB;AAAA,IACpC,YAAY,IAAI;AAAA,IAChB,WAAY,IAAI,aAAwB;AAAA,IACxC,MAAO,IAAI,QAAmB;AAAA,IAC9B,cAAe,IAAI,gBAA2B;AAAA,IAC9C,YAAa,IAAI,cAAyB;AAAA,IAC1C,UAAW,IAAI,YAAuB;AAAA,IACtC,YAAY,IAAI;AAAA,IAChB,YAAa,IAAI,cAAyB;AAAA,IAC1C,YAAa,IAAI,cAAyB;AAAA,IAC1C,WAAY,IAAI,aAAwB;AAAA,EAC1C;AACF;AAWO,SAAS,YAAY,MAA6B;AACvD,QAAM,KAAK,YAAY;AAEvB,KAAG;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWF,EAAE;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,cAAc;AAAA,IACnB,KAAK,mBAAmB;AAAA,IACxB,KAAK;AAAA,IACL,KAAK,UAAUD;AAAA,IACf,KAAK;AAAA,IACL,KAAK,WAAW;AAAA,IAChB,KAAK,cAAc;AAAA,IACnB,KAAK,aAAa;AAAA,IAClB,KAAK,QAAQ;AAAA,IACb,KAAK,gBAAgB;AAAA,IACrB,KAAK,cAAc;AAAA,IACnB,KAAK;AAAA,IACL,KAAK,cAAc;AAAA,IACnB,KAAK,cAAc,iBAAiB;AAAA,EACtC;AAEA,QAAM,MAAM;AAAA,IACV,GAAG,QAAQ,UAAUC,eAAc,2BAA2B,EAAE,IAAI,KAAK,EAAE;AAAA,EAC7E;AAEA,UAAQ,UAAU,GAAG;AAErB,SAAO;AACT;AAOO,SAAS,SAAS,IAA6B;AACpD,QAAM,KAAK,YAAY;AAEvB,QAAM,MAAM,GAAG;AAAA,IACb,UAAUA,eAAc;AAAA,EAC1B,EAAE,IAAI,EAAE;AAER,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,WAAW,GAAG;AACvB;AAMA,SAAS,gBACP,SACsC;AACtC,QAAM,aAAuB,CAAC;AAC9B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,aAAa,QAAW;AAClC,eAAW,KAAK,cAAc;AAC9B,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAC9B;AACA,MAAI,QAAQ,qBAAqB,QAAW;AAC1C,eAAW,KAAK,sBAAsB;AACtC,WAAO,KAAK,QAAQ,gBAAgB;AAAA,EACtC;AACA,MAAI,QAAQ,WAAW,QAAW;AAChC,eAAW,KAAK,YAAY;AAC5B,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AACA,MAAI,QAAQ,eAAe,QAAW;AACpC,eAAW,KAAK,gBAAgB;AAChC,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AACA,MAAI,QAAQ,WAAW,UAAa,QAAQ,OAAO,SAAS,GAAG;AAC7D,eAAW,KAAK,6CAA6C;AAC7D,UAAM,UAAU,IAAI,QAAQ,MAAM;AAClC,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B;AACA,MAAI,QAAQ,UAAU,QAAW;AAC/B,eAAW,KAAK,gBAAgB;AAChC,WAAO,KAAK,QAAQ,KAAK;AAAA,EAC3B;AAMA,MAAI,QAAQ,kBAAkB,SAAS,QAAQ,eAAe,QAAW;AACvE,eAAW;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAAA,IACrE;AAAA,EACF;AACF;AAKO,SAAS,WACd,UAA6B,CAAC,GAClB;AACZ,QAAM,KAAK,YAAY;AACvB,QAAM,EAAE,OAAO,OAAO,IAAI,gBAAgB,OAAO;AACjD,QAAM,QAAQ,QAAQ,SAASF;AAC/B,QAAM,SAAS,QAAQ,UAAU;AAEjC,QAAM,OAAO,GAAG;AAAA,IACd,UAAUE,eAAc;AAAA;AAAA,OAErB,KAAK;AAAA;AAAA;AAAA;AAAA,EAIV,EAAE,IAAI,GAAG,QAAQ,OAAO,MAAM;AAE9B,SAAO,KAAK,IAAI,UAAU;AAC5B;AAKO,SAAS,YACd,UAAuD,CAAC,GAChD;AACR,QAAM,KAAK,YAAY;AACvB,QAAM,EAAE,OAAO,OAAO,IAAI,gBAAgB,OAAO;AAEjD,QAAM,MAAM,GAAG;AAAA,IACb,wCAAwC,KAAK;AAAA,EAC/C,EAAE,IAAI,GAAG,MAAM;AAEf,SAAO,IAAI;AACb;AAiBO,SAAS,kBAAkB,YAAoB,QAAQ,IAAc;AAC1E,QAAM,KAAK,YAAY;AACvB,QAAM,OAAO,GAAG;AAAA,IACd;AAAA,EACF,EAAE,IAAI,YAAY,KAAK;AACvB,SAAO,KAAK,IAAI,OAAK,EAAE,EAAE;AAC3B;AAOO,SAAS,kBACd,IACA,QACA,WACiB;AACjB,QAAM,KAAK,YAAY;AAEvB,QAAM,OAAO,GAAG;AAAA,IACd;AAAA;AAAA;AAAA,EAGF,EAAE,IAAI,QAAQ,WAAW,EAAE;AAE3B,MAAI,KAAK,YAAY,EAAG,QAAO;AAE/B,QAAM,MAAM;AAAA,IACV,GAAG,QAAQ,UAAUC,eAAc,2BAA2B,EAAE,IAAI,EAAE;AAAA,EACxE;AAEA,UAAQ,UAAU,GAAG;AAErB,SAAO;AACT;;;ACxVA,SAAS,kBAAkB;AAoB3B,IAAM,mCAAmC;AACzC,IAAM,8BAA8B,CAAC,GAAG,kBAAkB,GAAG,2BAA2B;AAExF,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAC1B,IAAM,4BAA4B;AAClC,IAAM,2BAA2B;AACjC,IAAM,cAAc;AAEb,IAAM,qBAAqB;AAyBlC,SAAS,qBACP,MAC2B;AAC3B,QAAM,SAAS,KAAK;AACpB,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,UAAU,OAAO;AAAA,IACjB,cAAc,OAAO;AAAA,IACrB,oBAAoB,OAAO;AAAA,IAC3B,UAAU,sBAAsB,IAAI;AAAA,EACtC;AACF;AAEO,IAAM,qBAA2C,4BACrD,IAAI,oBAAoB,EACxB,OAAO,CAAC,UAAuC,UAAU,IAAI,EAC7D,KAAK,CAAC,MAAM,UAAU,KAAK,WAAW,MAAM,QAAQ;AAEvD,eAAsB,0BACpB,QACA,eAC6B;AAC7B,QAAM,aAAa,gBAAgB,KAAK;AACxC,QAAM,cAAc,QAAQ,OAAO,KAAK,WAAW,UAAU;AAC7D,MAAI,sBAAsB;AAC1B,MAAI,yBAAmC,CAAC;AAExC,MAAI,eAAe,YAAY;AAC7B,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,oBAAoB;AACpD,4BAAsB,QAAQ,QAAQ,SAAS;AAC/C,+BAAyB,QAAQ,gBAAgB,CAAC;AAAA,IACpD,QAAQ;AACN,4BAAsB;AACtB,+BAAyB,CAAC;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,mBACd,QACS;AACT,SAAO,OAAO;AAChB;AAEO,SAAS,2BACd,QACA,UAGkB;AAClB,MAAI,CAAC,UAAU;AACb,WAAO,EAAE,oBAAoB,MAAM,QAAQ,mBAAmB;AAAA,EAChE;AACA,MAAI,CAAC,OAAO,gBAAgB;AAC1B,WAAO,EAAE,oBAAoB,MAAM,QAAQ,yBAAyB;AAAA,EACtE;AACA,MAAI,SAAS,+BAA+B;AAC1C,WAAO,EAAE,oBAAoB,OAAO,QAAQ,0BAA0B;AAAA,EACxE;AACA,SAAO,EAAE,oBAAoB,MAAM,QAAQ,mBAAmB;AAChE;AAEO,SAAS,uBAAuB,cAA4C;AACjF,QAAM,UAAU;AAAA,IACd,aAAa,sBACT,6EACA,aAAa,cACX,uEACA;AAAA,IACN;AAAA,EACF;AAEA,MAAI,aAAa,uBAAuB,aAAa,uBAAuB,SAAS,GAAG;AACtF,UAAM,SAAS,aAAa,uBAAuB,MAAM,GAAG,gCAAgC;AAC5F,UAAM,YAAY,KAAK;AAAA,MACrB;AAAA,MACA,aAAa,uBAAuB,SAAS;AAAA,IAC/C;AACA,UAAM,SAAS,YAAY,IAAI,MAAM,SAAS,WAAW;AACzD,YAAQ,KAAK,mCAAmC,OAAO,KAAK,IAAI,CAAC,GAAG,MAAM,GAAG;AAAA,EAC/E;AAEA,SAAO;AACT;AAEO,SAAS,4BAA4B,cAA4C;AACtF,QAAM,QAAkB,CAAC;AAEzB,aAAW,SAAS,oBAAoB;AACtC,QAAI,MAAM,gBAAgB,CAAC,aAAa,YAAa;AACrD,QAAI,MAAM,sBAAsB,CAAC,aAAa,oBAAqB;AACnE,UAAM,KAAK,OAAO,MAAM,IAAI,OAAO,MAAM,QAAQ,EAAE;AAAA,EACrD;AAEA,SAAO;AACT;AAMA,SAAS,UAAU,OAAwB;AACzC,SAAO,WAAW,sBAAsB,EACrC,OAAO,KAAK,UAAU,KAAK,CAAC,EAC5B,OAAO,KAAK;AACjB;AAEA,SAAS,gBAAgB,MAAqB,WAAmB,2BAA0C;AACzG,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KAAK,SAAS,WACjB,GAAG,KAAK,MAAM,GAAG,QAAQ,CAAC,QAC1B;AACN;AAEA,SAAS,uBAA+B;AACtC,QAAM,WAAW,aAAa;AAAA,IAC5B,eAAe;AAAA,IACf,OAAO;AAAA,EACT,CAAC;AACD,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,UAAM,QAAQ;AAAA,MACZ,KAAK,QAAQ,SAAS,QAAQ,EAAE;AAAA,MAChC,QAAQ,SAAS,UAAU,QAAQ,MAAM,KAAK;AAAA,MAC9C,gBAAgB,QAAQ,OAAO;AAAA,IACjC,EAAE,OAAO,OAAO;AAChB,WAAO,MAAM,KAAK,UAAK;AAAA,EACzB,CAAC,EAAE,KAAK,IAAI;AACd;AAEA,SAAS,qBAA6B;AACpC,QAAM,SAAS,WAAW;AAAA,IACxB,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,CAAC;AACD,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,OAAO,IAAI,CAAC,UAAU;AAC3B,UAAM,QAAQ;AAAA,MACZ,MAAM,MAAM,gBAAgB,KAAK,gBAAgB,MAAM,OAAO,CAAC;AAAA,MAC/D,MAAM,aAAa,WAAW,MAAM,UAAU,KAAK;AAAA,IACrD,EAAE,OAAO,OAAO;AAChB,WAAO,MAAM,KAAK,UAAK;AAAA,EACzB,CAAC,EAAE,KAAK,IAAI;AACd;AAEA,SAAS,oBAA4B;AACnC,QAAM,QAAQ,UAAU;AAAA,IACtB,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,CAAC;AACD,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,QAAQ;AAAA,MACZ,KAAK,KAAK,SAAS,KAAK,EAAE;AAAA,MAC1B,UAAU,KAAK,MAAM;AAAA,MACrB,gBAAgB,KAAK,OAAO;AAAA,IAC9B,EAAE,OAAO,OAAO;AAChB,WAAO,MAAM,KAAK,UAAK;AAAA,EACzB,CAAC,EAAE,KAAK,IAAI;AACd;AAEA,SAAS,oBAAoB,QAA4B;AACvD,QAAM,gBAAgB,OAAO,QAAQ;AACrC,QAAM,UACJ,iBAAiB,kBAAkB,aAAa,KAChD,iBAAiB,kBAAkB,oBAAoB;AACzD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,UAAU,gBAAgB,QAAQ,SAAS,wBAAwB,KAAK;AAC9E,SAAO,UACH,QAAQ,QAAQ,IAAI;AAAA,EAAqB,OAAO,KAChD,QAAQ,QAAQ,IAAI;AAC1B;AAOA,eAAsB,6BACpB,QACA,eACmC;AACnC,QAAM,eAAe,MAAM,0BAA0B,QAAQ,aAAa;AAC1E,QAAM,oBAAoB,uBAAuB,YAAY;AAC7D,QAAM,oBAAoB,4BAA4B,YAAY;AAClE,QAAM,iBAAiB,qBAAqB;AAC5C,QAAM,eAAe,mBAAmB;AACxC,QAAM,cAAc,kBAAkB;AACtC,QAAM,gBAAgB,oBAAoB,MAAM;AAChD,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,MACP,aAAa,OAAO,QAAQ;AAAA,MAC5B,gBAAgB,OAAO,QAAQ;AAAA,MAC/B,eAAe,OAAO,QAAQ;AAAA,MAC9B,mBAAmB,OAAO,QAAQ;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,EACd;AAEA,SAAO;AAAA,IACL,WAAW,UAAU,KAAK;AAAA,IAC1B,aAAa;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,UAAU,MAAM,SAAS,MAAM,WAAW;AAAA,MAC/C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,kBAAkB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAEA,eAAsB,gCACpB,QACA,eAC+C;AAC/C,QAAM,QAAQ,MAAM,6BAA6B,QAAQ,aAAa;AACtE,QAAM,WAAW,sBAAsB,gBAAgB;AACvD,MAAI,UAAU,eAAe,MAAM,WAAW;AAC5C,WAAO;AAAA,EACT;AACA,SAAO;AACT;","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"]}