@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
@@ -8,6 +8,9 @@ import {
8
8
  } from "./chunk-6C6QZ4PM.js";
9
9
 
10
10
  // src/db/queries/search.ts
11
+ function sanitizeFtsQuery(query) {
12
+ return query.split(/\s+/).filter((tok) => tok.length > 0).map((tok) => /^[\w]+$/.test(tok) ? tok : `"${tok.replace(/"/g, '""')}"`).join(" ");
13
+ }
11
14
  function fullTextSearch(query, options = {}) {
12
15
  const db = getDatabase();
13
16
  const limit = options.limit ?? SEARCH_RESULTS_DEFAULT_LIMIT;
@@ -225,7 +228,8 @@ function hydrateSearchResults(vectorResults) {
225
228
  }
226
229
 
227
230
  export {
231
+ sanitizeFtsQuery,
228
232
  fullTextSearch,
229
233
  hydrateSearchResults
230
234
  };
231
- //# sourceMappingURL=chunk-LVIY7P35.js.map
235
+ //# sourceMappingURL=chunk-QLLBJEM7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db/queries/search.ts"],"sourcesContent":["/**\n * Full-text search using SQLite FTS5.\n *\n * Searches prompt_batches and activities via their FTS5 virtual tables.\n * Semantic search (vector similarity) is handled by the external VectorStore —\n * this module covers text-based retrieval only.\n *\n * All queries use parameterized placeholders throughout.\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport {\n SEARCH_RESULTS_DEFAULT_LIMIT,\n SEARCH_PREVIEW_CHARS,\n} from '@myco/constants.js';\nimport type { VectorSearchResult } from '@myco/daemon/embedding/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All result types that can appear in search results. */\nexport type SearchResultType =\n | 'session'\n | 'spore'\n | 'plan'\n | 'artifact'\n | 'prompt_batch'\n | 'activity'\n | 'skill';\n\n/** A single result returned from full-text or semantic search. */\nexport interface SearchResult {\n id: string;\n type: SearchResultType;\n title: string;\n preview: string;\n score: number;\n session_id?: string;\n}\n\n/** Options for fullTextSearch. */\nexport interface SearchOptions {\n /** Restrict results to a single type. */\n type?: string;\n /** Maximum number of results to return (default: SEARCH_RESULTS_DEFAULT_LIMIT). */\n limit?: number;\n /**\n * When explicitly `false`, hide results belonging to sessions still in\n * `status = 'active'` (and active sessions themselves). Intelligence-task\n * reads opt in to this; UI/CLI callers leave it unset.\n */\n includeActive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Query sanitization\n// ---------------------------------------------------------------------------\n\n/**\n * Sanitize a free-form search string for FTS5 MATCH.\n *\n * FTS5 MATCH treats several characters as operators: `-` means NOT, `:` is\n * a column filter, `\"...\"` is a literal phrase, `+` means must-match, `(`/`)`\n * group, `*` is a prefix wildcard, and unquoted hyphens in identifiers\n * (`skill-evolve-inventory`) or slashes in paths (`packages/myco/src/loader.ts`)\n * are routinely rejected as syntax errors.\n *\n * Natural-language callers (agents querying the vault, users typing in a UI\n * search box) don't know or care about FTS5 syntax — they expect their\n * string to \"just work.\" This helper tokenizes on whitespace and wraps any\n * token containing non-word characters in double quotes, turning it into\n * a literal phrase search. Plain alphanumeric/underscore tokens are left\n * unquoted so they AND together with their neighbours normally.\n *\n * Examples:\n * \"packages/myco/src/loader.ts tools\" → \"\\\"packages/myco/src/loader.ts\\\" tools\"\n * \"skill-evolve merge_candidates\" → \"\\\"skill-evolve\\\" merge_candidates\"\n * \"plain words\" → \"plain words\"\n *\n * Callers that DO want FTS5 operator semantics should skip this helper\n * and pass their own pre-formed MATCH expression to `fullTextSearch`.\n */\nexport function sanitizeFtsQuery(query: string): string {\n return query\n .split(/\\s+/)\n .filter((tok) => tok.length > 0)\n .map((tok) => /^[\\w]+$/.test(tok) ? tok : `\"${tok.replace(/\"/g, '\"\"')}\"`)\n .join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Full-text search across capture tables using SQLite FTS5.\n *\n * Searches prompt_batches (indexed on user_prompt) and activities (indexed\n * on tool_name, tool_input, file_path). The raw query string is passed\n * directly to FTS5 MATCH — callers should sanitize if needed.\n *\n * FTS5 `rank` values are negative (lower = better match). This function\n * converts them to positive scores via `Math.abs()` so higher = better\n * in the returned results.\n *\n * When `options.type` is specified, only the matching table branch is queried.\n *\n * @param query — search string (FTS5 MATCH syntax)\n * @param options — optional type filter and result limit\n * @returns SearchResult[] ordered by score DESC\n */\nexport function fullTextSearch(\n query: string,\n options: SearchOptions = {},\n): SearchResult[] {\n const db = getDatabase();\n const limit = options.limit ?? SEARCH_RESULTS_DEFAULT_LIMIT;\n const typeFilter = options.type;\n const excludeActive = options.includeActive === false;\n\n const results: SearchResult[] = [];\n\n // -- prompt_batches branch ------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'prompt_batch') {\n const activeGate = excludeActive\n ? ` AND EXISTS (SELECT 1 FROM sessions s WHERE s.id = pb.session_id AND s.status != 'active')`\n : '';\n const batchRows = db.prepare(\n `SELECT pb.id, pb.prompt_number, pb.session_id,\n substr(COALESCE(pb.user_prompt, '') || ' ' || COALESCE(pb.response_summary, ''), 1, ?) AS preview,\n fts.rank\n FROM prompt_batches_fts fts\n JOIN prompt_batches pb ON pb.id = fts.rowid\n WHERE prompt_batches_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(SEARCH_PREVIEW_CHARS, query, limit) as Array<{\n id: number;\n prompt_number: number | null;\n session_id: string | null;\n preview: string;\n rank: number;\n }>;\n\n for (const row of batchRows) {\n results.push({\n id: String(row.id),\n type: 'prompt_batch',\n title: row.prompt_number != null\n ? `Batch #${row.prompt_number}`\n : `Batch ${row.id}`,\n preview: row.preview,\n score: Math.abs(row.rank),\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // -- activities branch ----------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'activity') {\n const activeGate = excludeActive\n ? ` AND EXISTS (SELECT 1 FROM sessions s WHERE s.id = a.session_id AND s.status != 'active')`\n : '';\n const activityRows = db.prepare(\n `SELECT a.id, a.tool_name, a.tool_input, a.file_path, a.session_id,\n fts.rank\n FROM activities_fts fts\n JOIN activities a ON a.id = fts.rowid\n WHERE activities_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(query, limit) as Array<{\n id: number;\n tool_name: string;\n tool_input: string | null;\n file_path: string | null;\n session_id: string | null;\n rank: number;\n }>;\n\n for (const row of activityRows) {\n const preview = (row.tool_input ?? row.file_path ?? '').slice(0, SEARCH_PREVIEW_CHARS);\n results.push({\n id: String(row.id),\n type: 'activity',\n title: row.tool_name,\n preview,\n score: Math.abs(row.rank),\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // -- spores branch --------------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'spore') {\n // Spores may have a NULL session_id (agent-authored, no source session),\n // which are always kept; only spores attached to still-active sessions\n // are excluded when the gate is on.\n const activeGate = excludeActive\n ? ` AND (s.session_id IS NULL OR EXISTS (SELECT 1 FROM sessions ss WHERE ss.id = s.session_id AND ss.status != 'active'))`\n : '';\n const sporeRows = db.prepare(\n `SELECT s.id, s.observation_type, s.session_id,\n substr(COALESCE(s.content, ''), 1, ?) AS preview,\n fts.rank\n FROM spores_fts fts\n JOIN spores s ON s.rowid = fts.rowid\n WHERE spores_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(SEARCH_PREVIEW_CHARS, query, limit) as Array<{\n id: string;\n observation_type: string;\n session_id: string | null;\n preview: string;\n rank: number;\n }>;\n\n for (const row of sporeRows) {\n results.push({\n id: String(row.id),\n type: 'spore',\n title: row.observation_type,\n preview: row.preview,\n score: Math.abs(row.rank),\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // -- sessions branch ------------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'session') {\n const activeGate = excludeActive ? ` AND s.status != 'active'` : '';\n const sessionRows = db.prepare(\n `SELECT s.id, s.title,\n substr(COALESCE(s.summary, s.title, ''), 1, ?) AS preview,\n fts.rank\n FROM sessions_fts fts\n JOIN sessions s ON s.rowid = fts.rowid\n WHERE sessions_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(SEARCH_PREVIEW_CHARS, query, limit) as Array<{\n id: string;\n title: string | null;\n preview: string;\n rank: number;\n }>;\n\n for (const row of sessionRows) {\n results.push({\n id: String(row.id),\n type: 'session',\n title: row.title ?? `Session ${row.id.slice(-6)}`,\n preview: row.preview,\n score: Math.abs(row.rank),\n });\n }\n }\n\n // Sort combined results by score DESC and apply limit.\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, limit);\n}\n\n// ---------------------------------------------------------------------------\n// Hydration — convert VectorSearchResults into SearchResults\n// ---------------------------------------------------------------------------\n\n/** Row shape returned from sessions table for hydration. */\ninterface SessionRow {\n id: string;\n title: string | null;\n summary: string | null;\n session_id?: undefined;\n}\n\n/** Row shape returned from spores table for hydration. */\ninterface SporeRow {\n id: string;\n observation_type: string;\n content: string;\n session_id: string | null;\n}\n\n/** Row shape returned from plans table for hydration. */\ninterface PlanRow {\n id: string;\n title: string | null;\n content: string | null;\n session_id: string | null;\n}\n\n/** Row shape returned from artifacts table for hydration. */\ninterface ArtifactRow {\n id: string;\n title: string;\n content: string | null;\n}\n\n/**\n * Hydrate vector search results into SearchResults by fetching full records\n * from the record store.\n *\n * Groups results by namespace, queries each table for the relevant IDs, then\n * maps them into SearchResult format with titles and previews.\n */\nexport function hydrateSearchResults(\n vectorResults: VectorSearchResult[],\n): SearchResult[] {\n if (vectorResults.length === 0) return [];\n\n const db = getDatabase();\n const results: SearchResult[] = [];\n\n // Group result IDs by namespace\n const byNamespace = new Map<string, VectorSearchResult[]>();\n for (const vr of vectorResults) {\n const group = byNamespace.get(vr.namespace) ?? [];\n group.push(vr);\n byNamespace.set(vr.namespace, group);\n }\n\n // Use json_each so the statement text is stable and SQLite can cache the plan.\n const sessionStmt = db.prepare(\n `SELECT id, title, summary FROM sessions WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const sporeStmt = db.prepare(\n `SELECT id, observation_type, content, session_id FROM spores WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const planStmt = db.prepare(\n `SELECT id, title, content, session_id FROM plans WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const artifactStmt = db.prepare(\n `SELECT id, title, content FROM artifacts WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const skillStmt = db.prepare(\n `SELECT id, name, display_name, description FROM skill_records WHERE id IN (SELECT value FROM json_each(?))`,\n );\n\n // --- sessions ---\n const sessionResults = byNamespace.get('sessions');\n if (sessionResults && sessionResults.length > 0) {\n const ids = sessionResults.map((r) => r.id);\n const rows = sessionStmt.all(JSON.stringify(ids)) as SessionRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of sessionResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'session',\n title: row.title ?? `Session ${row.id.slice(-6)}`,\n preview: (row.summary ?? '').slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n });\n }\n }\n\n // --- spores ---\n const sporeResults = byNamespace.get('spores');\n if (sporeResults && sporeResults.length > 0) {\n const ids = sporeResults.map((r) => r.id);\n const rows = sporeStmt.all(JSON.stringify(ids)) as SporeRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of sporeResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'spore',\n title: row.observation_type,\n preview: row.content.slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // --- plans ---\n const planResults = byNamespace.get('plans');\n if (planResults && planResults.length > 0) {\n const ids = planResults.map((r) => r.id);\n const rows = planStmt.all(JSON.stringify(ids)) as PlanRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of planResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'plan',\n title: row.title ?? `Plan ${row.id.slice(-6)}`,\n preview: (row.content ?? '').slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // --- artifacts ---\n const artifactResults = byNamespace.get('artifacts');\n if (artifactResults && artifactResults.length > 0) {\n const ids = artifactResults.map((r) => r.id);\n const rows = artifactStmt.all(JSON.stringify(ids)) as ArtifactRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of artifactResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'artifact',\n title: row.title,\n preview: (row.content ?? '').slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n });\n }\n }\n\n // --- skill_records ---\n const skillResults = byNamespace.get('skill_records');\n if (skillResults && skillResults.length > 0) {\n const ids = skillResults.map((r) => r.id);\n const rows = skillStmt.all(JSON.stringify(ids)) as Array<{ id: string; name: string; display_name: string; description: string }>;\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of skillResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'skill',\n title: row.display_name || row.name,\n preview: row.description.slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n });\n }\n }\n\n // Preserve the original similarity-based ordering from vector search\n results.sort((a, b) => b.score - a.score);\n return results;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,25 @@
1
+ import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
+
3
+ // src/vault/resolve.ts
4
+ import path from "path";
5
+ import { execFileSync } from "child_process";
6
+ function resolveVaultDir(cwd = process.cwd()) {
7
+ return path.join(resolveRepoRoot(cwd), ".myco");
8
+ }
9
+ function resolveRepoRoot(cwd) {
10
+ try {
11
+ const gitCommon = execFileSync(
12
+ "git",
13
+ ["rev-parse", "--git-common-dir"],
14
+ { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
15
+ ).trim();
16
+ return path.resolve(cwd, gitCommon, "..");
17
+ } catch {
18
+ return cwd;
19
+ }
20
+ }
21
+
22
+ export {
23
+ resolveVaultDir
24
+ };
25
+ //# sourceMappingURL=chunk-TSM6VESW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vault/resolve.ts"],"sourcesContent":["import path from 'node:path';\nimport { execFileSync } from 'node:child_process';\n\n/**\n * Resolve the vault directory.\n *\n * Always `.myco/` in the project root. The vault is a SQLite database\n * that lives with the project — there is no escape hatch.\n *\n * Uses git to find the repo root so this works correctly in\n * git worktrees — worktree agents resolve to the same vault\n * as the main working tree.\n */\nexport function resolveVaultDir(cwd: string = process.cwd()): string {\n return path.join(resolveRepoRoot(cwd), '.myco');\n}\n\n/**\n * Find the main repo root, even from a git worktree.\n *\n * `git rev-parse --git-common-dir` returns the shared .git directory:\n * - In a normal repo: \".git\" (relative)\n * - In a worktree: \"/abs/path/to/main-repo/.git\" (absolute)\n *\n * The repo root is the parent of that path.\n * Falls back to cwd if not in a git repo.\n */\nfunction resolveRepoRoot(cwd: string): string {\n try {\n const gitCommon = execFileSync(\n 'git', ['rev-parse', '--git-common-dir'],\n { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n ).trim();\n return path.resolve(cwd, gitCommon, '..');\n } catch {\n return cwd;\n }\n}\n"],"mappings":";;;AAAA,OAAO,UAAU;AACjB,SAAS,oBAAoB;AAYtB,SAAS,gBAAgB,MAAc,QAAQ,IAAI,GAAW;AACnE,SAAO,KAAK,KAAK,gBAAgB,GAAG,GAAG,OAAO;AAChD;AAYA,SAAS,gBAAgB,KAAqB;AAC5C,MAAI;AACF,UAAM,YAAY;AAAA,MAChB;AAAA,MAAO,CAAC,aAAa,kBAAkB;AAAA,MACvC,EAAE,KAAK,UAAU,SAAS,OAAO,CAAC,QAAQ,QAAQ,MAAM,EAAE;AAAA,IAC5D,EAAE,KAAK;AACP,WAAO,KAAK,QAAQ,KAAK,WAAW,IAAI;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  loadAgentTasks,
4
4
  taskFromParsed
5
- } from "./chunk-JZS6GZ6T.js";
5
+ } from "./chunk-AUIXX33A.js";
6
6
  import {
7
7
  AgentTaskSchema
8
8
  } from "./chunk-OUJSQSKE.js";
@@ -102,4 +102,4 @@ export {
102
102
  deleteUserTask,
103
103
  copyTaskToUser
104
104
  };
105
- //# sourceMappingURL=chunk-ILJPRYES.js.map
105
+ //# sourceMappingURL=chunk-USVFEWYL.js.map
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  isProcessAlive
4
- } from "./chunk-JR54LTPP.js";
4
+ } from "./chunk-QDLVIW2O.js";
5
5
  import {
6
6
  loadMergedConfig
7
7
  } from "./chunk-53RPGOEN.js";
@@ -187,4 +187,4 @@ export {
187
187
  getEmbeddingQueueDepth,
188
188
  gatherStats
189
189
  };
190
- //# sourceMappingURL=chunk-75Z7UKDY.js.map
190
+ //# sourceMappingURL=chunk-VRI56337.js.map