@goondocks/myco 0.13.0 → 0.14.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 (121) hide show
  1. package/dist/{agent-run-YBASQHC7.js → agent-run-VX5MAPRN.js} +4 -4
  2. package/dist/{agent-tasks-WBQFDHWC.js → agent-tasks-FJOBYYC5.js} +4 -4
  3. package/dist/{chunk-NCVR636M.js → chunk-4VF6KQ2Z.js} +55 -4
  4. package/dist/chunk-4VF6KQ2Z.js.map +1 -0
  5. package/dist/{chunk-EUQQVKGQ.js → chunk-CCKPBAKJ.js} +2 -2
  6. package/dist/{chunk-5BK6M6X5.js → chunk-JJXVDCEX.js} +160 -95
  7. package/dist/chunk-JJXVDCEX.js.map +1 -0
  8. package/dist/{chunk-VQEXXS56.js → chunk-NYTEHLVI.js} +2 -2
  9. package/dist/{chunk-W3T3QDBN.js → chunk-PSYLKCWQ.js} +17 -2
  10. package/dist/chunk-PSYLKCWQ.js.map +1 -0
  11. package/dist/{chunk-LPISXFM4.js → chunk-PX5KIOKY.js} +2 -2
  12. package/dist/{chunk-T77674VB.js → chunk-QB2UTRQE.js} +3 -3
  13. package/dist/chunk-QLCD77AN.js +93 -0
  14. package/dist/chunk-QLCD77AN.js.map +1 -0
  15. package/dist/{chunk-TFGGH6UB.js → chunk-RUDOGKWF.js} +2 -2
  16. package/dist/{chunk-NRT2ZRUG.js → chunk-S66YG6QK.js} +19 -1
  17. package/dist/{chunk-NRT2ZRUG.js.map → chunk-S66YG6QK.js.map} +1 -1
  18. package/dist/{chunk-2PWO3WPS.js → chunk-TVV6PZOC.js} +2 -2
  19. package/dist/{chunk-JBFFAGJK.js → chunk-X34OFKYU.js} +2 -2
  20. package/dist/{chunk-YYQWCTF6.js → chunk-XNHHADBK.js} +2 -2
  21. package/dist/{cli-WCBTILMW.js → cli-Z7VO7LIL.js} +36 -36
  22. package/dist/{client-MJUZJ5MC.js → client-CECN26WV.js} +3 -3
  23. package/dist/{config-WBCOTJUE.js → config-H657SF6B.js} +2 -2
  24. package/dist/{doctor-GDCLRJOF.js → doctor-TYMLSW5K.js} +5 -5
  25. package/dist/{executor-TCAXFOIS.js → executor-4DKCQN3A.js} +64 -23
  26. package/dist/executor-4DKCQN3A.js.map +1 -0
  27. package/dist/{init-ZSDMXY4T.js → init-W6VRN5ZZ.js} +10 -10
  28. package/dist/{init-wizard-6LDUVR7C.js → init-wizard-3RJFKAGM.js} +2 -2
  29. package/dist/{loader-L2TCAYCT.js → loader-JQLO6K44.js} +2 -2
  30. package/dist/{main-25MKYYKO.js → main-XUQRWNJ7.js} +255 -39
  31. package/dist/main-XUQRWNJ7.js.map +1 -0
  32. package/dist/{open-4YTUNIP3.js → open-6EC54JEU.js} +4 -4
  33. package/dist/{post-compact-E5V4OZJB.js → post-compact-55ISYIPY.js} +4 -4
  34. package/dist/{post-tool-use-Y6UWKCVD.js → post-tool-use-KNOFQNVX.js} +3 -3
  35. package/dist/{post-tool-use-failure-AHFXMNHX.js → post-tool-use-failure-UIRHWELN.js} +4 -4
  36. package/dist/{pre-compact-EI5EV3N7.js → pre-compact-T3CR4C3Q.js} +4 -4
  37. package/dist/{remove-F63WBELE.js → remove-HIIXTVAK.js} +4 -4
  38. package/dist/{resolution-events-BZYMUQ53.js → resolution-events-5EVUEWHS.js} +3 -3
  39. package/dist/{restart-GULUNCMX.js → restart-5FJYFNIR.js} +5 -5
  40. package/dist/{search-NLZMCEAG.js → search-C3CIHCMP.js} +4 -4
  41. package/dist/{server-CXPWUO6H.js → server-XJTAWCHN.js} +3 -3
  42. package/dist/{session-XXVEDIQZ.js → session-CUGCZWCY.js} +6 -6
  43. package/dist/{session-end-6DP6VTZV.js → session-end-5AI4U3KC.js} +3 -3
  44. package/dist/{session-start-QNAQDF5M.js → session-start-XHH6RN7T.js} +8 -8
  45. package/dist/{setup-llm-ER3B7AZ2.js → setup-llm-3LYRV4KB.js} +5 -5
  46. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +40 -8
  47. package/dist/src/agent/definitions/tasks/skill-generate.yaml +8 -3
  48. package/dist/src/cli.js +1 -1
  49. package/dist/src/daemon/main.js +1 -1
  50. package/dist/src/hooks/post-tool-use.js +1 -1
  51. package/dist/src/hooks/session-end.js +1 -1
  52. package/dist/src/hooks/session-start.js +1 -1
  53. package/dist/src/hooks/stop.js +1 -1
  54. package/dist/src/hooks/user-prompt-submit.js +1 -1
  55. package/dist/src/mcp/server.js +1 -1
  56. package/dist/{stats-VQ7XMOCU.js → stats-BDE5FTO6.js} +6 -6
  57. package/dist/{stop-VTO2KIRG.js → stop-ZIKA2LGJ.js} +3 -3
  58. package/dist/{stop-failure-C5T6LJQR.js → stop-failure-MF22OJ7R.js} +4 -4
  59. package/dist/{subagent-start-NZF42NKF.js → subagent-start-XNAZKYVD.js} +4 -4
  60. package/dist/{subagent-stop-UV5ECFVU.js → subagent-stop-QTJSJYIT.js} +4 -4
  61. package/dist/{task-completed-3SV6TL3V.js → task-completed-24BVLKOC.js} +4 -4
  62. package/dist/{team-XSJXLBZX.js → team-SJPDXELY.js} +2 -2
  63. package/dist/turns-3ZQAF6HF.js +16 -0
  64. package/dist/ui/assets/index-BmsHIwjl.css +1 -0
  65. package/dist/ui/assets/index-Cn6cQwJy.js +842 -0
  66. package/dist/ui/index.html +2 -2
  67. package/dist/{update-5GXOQIY5.js → update-LRPXOWMZ.js} +4 -4
  68. package/dist/{user-prompt-submit-VLQG77A6.js → user-prompt-submit-HPBZOZHM.js} +3 -3
  69. package/dist/{verify-WF7U3NQW.js → verify-JHIMXTY5.js} +2 -2
  70. package/dist/{version-RGX7TZ7V.js → version-ELM3BK4H.js} +2 -2
  71. package/dist/version-ELM3BK4H.js.map +1 -0
  72. package/package.json +1 -1
  73. package/dist/chunk-5BK6M6X5.js.map +0 -1
  74. package/dist/chunk-NCVR636M.js.map +0 -1
  75. package/dist/chunk-W3T3QDBN.js.map +0 -1
  76. package/dist/executor-TCAXFOIS.js.map +0 -1
  77. package/dist/main-25MKYYKO.js.map +0 -1
  78. package/dist/ui/assets/index-BeygBZGu.css +0 -1
  79. package/dist/ui/assets/index-CbGC0T_o.js +0 -822
  80. /package/dist/{agent-run-YBASQHC7.js.map → agent-run-VX5MAPRN.js.map} +0 -0
  81. /package/dist/{agent-tasks-WBQFDHWC.js.map → agent-tasks-FJOBYYC5.js.map} +0 -0
  82. /package/dist/{chunk-EUQQVKGQ.js.map → chunk-CCKPBAKJ.js.map} +0 -0
  83. /package/dist/{chunk-VQEXXS56.js.map → chunk-NYTEHLVI.js.map} +0 -0
  84. /package/dist/{chunk-LPISXFM4.js.map → chunk-PX5KIOKY.js.map} +0 -0
  85. /package/dist/{chunk-T77674VB.js.map → chunk-QB2UTRQE.js.map} +0 -0
  86. /package/dist/{chunk-TFGGH6UB.js.map → chunk-RUDOGKWF.js.map} +0 -0
  87. /package/dist/{chunk-2PWO3WPS.js.map → chunk-TVV6PZOC.js.map} +0 -0
  88. /package/dist/{chunk-JBFFAGJK.js.map → chunk-X34OFKYU.js.map} +0 -0
  89. /package/dist/{chunk-YYQWCTF6.js.map → chunk-XNHHADBK.js.map} +0 -0
  90. /package/dist/{cli-WCBTILMW.js.map → cli-Z7VO7LIL.js.map} +0 -0
  91. /package/dist/{client-MJUZJ5MC.js.map → client-CECN26WV.js.map} +0 -0
  92. /package/dist/{config-WBCOTJUE.js.map → config-H657SF6B.js.map} +0 -0
  93. /package/dist/{doctor-GDCLRJOF.js.map → doctor-TYMLSW5K.js.map} +0 -0
  94. /package/dist/{init-ZSDMXY4T.js.map → init-W6VRN5ZZ.js.map} +0 -0
  95. /package/dist/{init-wizard-6LDUVR7C.js.map → init-wizard-3RJFKAGM.js.map} +0 -0
  96. /package/dist/{loader-L2TCAYCT.js.map → loader-JQLO6K44.js.map} +0 -0
  97. /package/dist/{open-4YTUNIP3.js.map → open-6EC54JEU.js.map} +0 -0
  98. /package/dist/{post-compact-E5V4OZJB.js.map → post-compact-55ISYIPY.js.map} +0 -0
  99. /package/dist/{post-tool-use-Y6UWKCVD.js.map → post-tool-use-KNOFQNVX.js.map} +0 -0
  100. /package/dist/{post-tool-use-failure-AHFXMNHX.js.map → post-tool-use-failure-UIRHWELN.js.map} +0 -0
  101. /package/dist/{pre-compact-EI5EV3N7.js.map → pre-compact-T3CR4C3Q.js.map} +0 -0
  102. /package/dist/{remove-F63WBELE.js.map → remove-HIIXTVAK.js.map} +0 -0
  103. /package/dist/{resolution-events-BZYMUQ53.js.map → resolution-events-5EVUEWHS.js.map} +0 -0
  104. /package/dist/{restart-GULUNCMX.js.map → restart-5FJYFNIR.js.map} +0 -0
  105. /package/dist/{search-NLZMCEAG.js.map → search-C3CIHCMP.js.map} +0 -0
  106. /package/dist/{server-CXPWUO6H.js.map → server-XJTAWCHN.js.map} +0 -0
  107. /package/dist/{session-XXVEDIQZ.js.map → session-CUGCZWCY.js.map} +0 -0
  108. /package/dist/{session-end-6DP6VTZV.js.map → session-end-5AI4U3KC.js.map} +0 -0
  109. /package/dist/{session-start-QNAQDF5M.js.map → session-start-XHH6RN7T.js.map} +0 -0
  110. /package/dist/{setup-llm-ER3B7AZ2.js.map → setup-llm-3LYRV4KB.js.map} +0 -0
  111. /package/dist/{stats-VQ7XMOCU.js.map → stats-BDE5FTO6.js.map} +0 -0
  112. /package/dist/{stop-VTO2KIRG.js.map → stop-ZIKA2LGJ.js.map} +0 -0
  113. /package/dist/{stop-failure-C5T6LJQR.js.map → stop-failure-MF22OJ7R.js.map} +0 -0
  114. /package/dist/{subagent-start-NZF42NKF.js.map → subagent-start-XNAZKYVD.js.map} +0 -0
  115. /package/dist/{subagent-stop-UV5ECFVU.js.map → subagent-stop-QTJSJYIT.js.map} +0 -0
  116. /package/dist/{task-completed-3SV6TL3V.js.map → task-completed-24BVLKOC.js.map} +0 -0
  117. /package/dist/{team-XSJXLBZX.js.map → team-SJPDXELY.js.map} +0 -0
  118. /package/dist/{version-RGX7TZ7V.js.map → turns-3ZQAF6HF.js.map} +0 -0
  119. /package/dist/{update-5GXOQIY5.js.map → update-LRPXOWMZ.js.map} +0 -0
  120. /package/dist/{user-prompt-submit-VLQG77A6.js.map → user-prompt-submit-HPBZOZHM.js.map} +0 -0
  121. /package/dist/{verify-WF7U3NQW.js.map → verify-JHIMXTY5.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/daemon/team-context.ts","../src/db/queries/team-outbox.ts"],"sourcesContent":["/**\n * Module-level state for team sync.\n *\n * Initialized once by the daemon on startup. Query modules import\n * `isTeamSyncEnabled()` and `getTeamMachineId()` to decide whether\n * to enqueue outbox records on write.\n */\n\nimport { SYNC_PROTOCOL_VERSION, DEFAULT_MACHINE_ID } from '@myco/constants.js';\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n\nlet teamSyncEnabled = false;\nlet teamMachineId = DEFAULT_MACHINE_ID;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Initialize team context. Called once on daemon startup.\n */\nexport function initTeamContext(enabled: boolean, machineId: string): void {\n teamSyncEnabled = enabled;\n teamMachineId = machineId;\n}\n\n/**\n * Whether team sync is currently enabled.\n *\n * Query modules check this before enqueuing outbox records.\n */\nexport function isTeamSyncEnabled(): boolean {\n return teamSyncEnabled;\n}\n\n/**\n * The machine ID for this instance.\n */\nexport function getTeamMachineId(): string {\n return teamMachineId;\n}\n\n/**\n * The sync protocol version in use.\n */\nexport function getTeamSyncProtocolVersion(): number {\n return SYNC_PROTOCOL_VERSION;\n}\n\n/**\n * Reset team context (for testing).\n */\nexport function resetTeamContext(): void {\n teamSyncEnabled = false;\n teamMachineId = DEFAULT_MACHINE_ID;\n}\n","/**\n * Team outbox CRUD query helpers.\n *\n * The outbox pattern: write paths enqueue records here when team sync is enabled.\n * The sync client flushes pending records in batches to the Cloudflare Worker.\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 { isTeamSyncEnabled, getTeamMachineId } from '@myco/daemon/team-context.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Max records returned per listPending call. */\nconst BURST_BATCH_SIZE = 200;\n\n/** Age in seconds after which sent records are pruned (24 hours). */\nconst SENT_PRUNE_AGE_SECONDS = 86_400;\n\n/** Milliseconds-per-second multiplier for epoch math. */\nconst MS_PER_SECOND = 1000;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required when enqueuing an outbox record. */\nexport interface OutboxInsert {\n table_name: string;\n row_id: string;\n operation?: string;\n payload: string;\n machine_id: string;\n created_at: number;\n}\n\n/** Row shape returned from outbox queries. */\nexport interface OutboxRow {\n id: number;\n table_name: string;\n row_id: string;\n operation: string;\n payload: string;\n machine_id: string;\n created_at: number;\n sent_at: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst OUTBOX_COLUMNS = [\n 'id',\n 'table_name',\n 'row_id',\n 'operation',\n 'payload',\n 'machine_id',\n 'created_at',\n 'sent_at',\n] as const;\n\nconst SELECT_COLUMNS = OUTBOX_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed OutboxRow. */\nfunction toOutboxRow(row: Record<string, unknown>): OutboxRow {\n return {\n id: row.id as number,\n table_name: row.table_name as string,\n row_id: row.row_id as string,\n operation: row.operation as string,\n payload: row.payload as string,\n machine_id: row.machine_id as string,\n created_at: row.created_at as number,\n sent_at: (row.sent_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Convenience helper — used by query modules\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue a row for team sync if sync is enabled.\n *\n * Centralizes the if-enabled / enqueue / serialize pattern that every\n * write-path query module previously duplicated inline.\n */\nexport function syncRow(tableName: string, row: { id: string | number; created_at?: number }): void {\n if (!isTeamSyncEnabled()) return;\n enqueueOutbox({\n table_name: tableName,\n row_id: String(row.id),\n payload: JSON.stringify(row),\n machine_id: getTeamMachineId(),\n created_at: row.created_at ?? Math.floor(Date.now() / 1000),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue a record into the team outbox for later sync.\n *\n * Inserted with `sent_at = NULL` (pending).\n */\nexport function enqueueOutbox(data: OutboxInsert): OutboxRow {\n const db = getDatabase();\n\n const info = db.prepare(\n `INSERT INTO team_outbox (\n table_name, row_id, operation, payload, machine_id, created_at\n ) VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(\n data.table_name,\n data.row_id,\n data.operation ?? 'upsert',\n data.payload,\n data.machine_id,\n data.created_at,\n );\n\n const id = Number(info.lastInsertRowid);\n\n return toOutboxRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM team_outbox WHERE id = ?`).get(id) as Record<string, unknown>,\n );\n}\n\n/**\n * List pending outbox records (oldest-first).\n *\n * Uses burst sizing: fetches BURST_BATCH_SIZE rows and returns them all.\n * If fewer than BURST_THRESHOLD rows come back, callers get a normal-size\n * batch; if more, the full burst. This avoids a separate COUNT query.\n */\nexport function listPending(limit?: number): OutboxRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM team_outbox\n WHERE sent_at IS NULL\n ORDER BY created_at ASC\n LIMIT ?`,\n ).all(limit ?? BURST_BATCH_SIZE) as Record<string, unknown>[];\n\n return rows.map(toOutboxRow);\n}\n\n/**\n * Mark outbox records as sent by setting sent_at.\n */\nexport function markSent(ids: number[], sentAt: number): void {\n if (ids.length === 0) return;\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET sent_at = ?\n WHERE id IN (${placeholders})`,\n ).run(sentAt, ...ids);\n}\n\n/**\n * Reset sent_at to NULL for records that need to be retried.\n *\n * This allows the sync client to re-enqueue specific records for retry.\n */\nexport function markForRetry(ids: number[]): void {\n if (ids.length === 0) return;\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET sent_at = NULL\n WHERE id IN (${placeholders})`,\n ).run(...ids);\n}\n\n/**\n * Prune old outbox records.\n *\n * Removes sent records older than 24 hours.\n *\n * @returns the number of records deleted.\n */\nexport function pruneOld(): number {\n const db = getDatabase();\n const cutoff = Math.floor(Date.now() / MS_PER_SECOND) - SENT_PRUNE_AGE_SECONDS;\n\n const info = db.prepare(\n `DELETE FROM team_outbox\n WHERE sent_at IS NOT NULL AND sent_at < ?`,\n ).run(cutoff);\n\n return info.changes;\n}\n\n/**\n * Count pending (unsent) outbox records.\n */\nexport function countPending(): number {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM team_outbox WHERE sent_at IS NULL`,\n ).get() as { count: number };\n\n return row.count;\n}\n\n// ---------------------------------------------------------------------------\n// Backfill\n// ---------------------------------------------------------------------------\n\n/** Tables to backfill (must have id, machine_id, synced_at columns). */\nconst BACKFILL_TABLES = [\n 'sessions',\n 'prompt_batches',\n 'spores',\n 'entities',\n 'graph_edges',\n 'resolution_events',\n 'plans',\n 'artifacts',\n 'digest_extracts',\n 'skill_candidates',\n 'skill_records',\n] as const;\n// entity_mentions excluded — no `id` column (composite key entity_id+note_id+note_type)\n// skill_usage excluded — no `synced_at` column (syncs via syncRow on insert)\n\n/**\n * Enqueue all unsynced records across all synced tables into the outbox.\n *\n * Scans each table for rows where `synced_at IS NULL`, serializes the full\n * row as JSON, and inserts into the outbox. Idempotent — re-running only\n * picks up rows not yet in the outbox (checked via existing outbox entries).\n *\n * @returns the total number of records enqueued.\n */\nexport function backfillUnsynced(machineId: string): number {\n const db = getDatabase();\n let total = 0;\n\n const now = Math.floor(Date.now() / MS_PER_SECOND);\n\n // Process one table at a time in separate transactions to avoid long locks\n for (const table of BACKFILL_TABLES) {\n const rows = db.prepare(\n `SELECT * FROM ${table}\n WHERE synced_at IS NULL\n AND NOT EXISTS (\n SELECT 1 FROM team_outbox\n WHERE team_outbox.table_name = ? AND team_outbox.row_id = CAST(${table}.id AS TEXT)\n )`,\n ).all(table) as Record<string, unknown>[];\n\n if (rows.length === 0) continue;\n\n const insertBatch = db.transaction((batchRows: Record<string, unknown>[]) => {\n const stmt = db.prepare(\n `INSERT INTO team_outbox (table_name, row_id, operation, payload, machine_id, created_at)\n VALUES (?, ?, 'upsert', ?, ?, ?)`,\n );\n for (const row of batchRows) {\n stmt.run(table, String(row.id), JSON.stringify(row), machineId, now);\n }\n });\n\n insertBatch(rows);\n total += rows.length;\n }\n\n return total;\n}\n\n"],"mappings":";;;;;;;;;AAcA,IAAI,kBAAkB;AACtB,IAAI,gBAAgB;AASb,SAAS,gBAAgB,SAAkB,WAAyB;AACzE,oBAAkB;AAClB,kBAAgB;AAClB;AAOO,SAAS,oBAA6B;AAC3C,SAAO;AACT;AAKO,SAAS,mBAA2B;AACzC,SAAO;AACT;;;ACzBA,IAAM,mBAAmB;AAGzB,IAAM,yBAAyB;AAG/B,IAAM,gBAAgB;AAgCtB,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,eAAe,KAAK,IAAI;AAO/C,SAAS,YAAY,KAAyC;AAC5D,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,YAAY,IAAI;AAAA,IAChB,QAAQ,IAAI;AAAA,IACZ,WAAW,IAAI;AAAA,IACf,SAAS,IAAI;AAAA,IACb,YAAY,IAAI;AAAA,IAChB,YAAY,IAAI;AAAA,IAChB,SAAU,IAAI,WAAsB;AAAA,EACtC;AACF;AAYO,SAAS,QAAQ,WAAmB,KAAyD;AAClG,MAAI,CAAC,kBAAkB,EAAG;AAC1B,gBAAc;AAAA,IACZ,YAAY;AAAA,IACZ,QAAQ,OAAO,IAAI,EAAE;AAAA,IACrB,SAAS,KAAK,UAAU,GAAG;AAAA,IAC3B,YAAY,iBAAiB;AAAA,IAC7B,YAAY,IAAI,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,EAC5D,CAAC;AACH;AAWO,SAAS,cAAc,MAA+B;AAC3D,QAAM,KAAK,YAAY;AAEvB,QAAM,OAAO,GAAG;AAAA,IACd;AAAA;AAAA;AAAA,EAGF,EAAE;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,aAAa;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAEA,QAAM,KAAK,OAAO,KAAK,eAAe;AAEtC,SAAO;AAAA,IACL,GAAG,QAAQ,UAAU,cAAc,gCAAgC,EAAE,IAAI,EAAE;AAAA,EAC7E;AACF;AASO,SAAS,YAAY,OAA6B;AACvD,QAAM,KAAK,YAAY;AAEvB,QAAM,OAAO,GAAG;AAAA,IACd,UAAU,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1B,EAAE,IAAI,SAAS,gBAAgB;AAE/B,SAAO,KAAK,IAAI,WAAW;AAC7B;AAKO,SAAS,SAAS,KAAe,QAAsB;AAC5D,MAAI,IAAI,WAAW,EAAG;AAEtB,QAAM,KAAK,YAAY;AACvB,QAAM,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAEjD,KAAG;AAAA,IACD;AAAA;AAAA,oBAEgB,YAAY;AAAA,EAC9B,EAAE,IAAI,QAAQ,GAAG,GAAG;AACtB;AA2BO,SAAS,WAAmB;AACjC,QAAM,KAAK,YAAY;AACvB,QAAM,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,aAAa,IAAI;AAExD,QAAM,OAAO,GAAG;AAAA,IACd;AAAA;AAAA,EAEF,EAAE,IAAI,MAAM;AAEZ,SAAO,KAAK;AACd;AAKO,SAAS,eAAuB;AACrC,QAAM,KAAK,YAAY;AAEvB,QAAM,MAAM,GAAG;AAAA,IACb;AAAA,EACF,EAAE,IAAI;AAEN,SAAO,IAAI;AACb;AAOA,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaO,SAAS,iBAAiB,WAA2B;AAC1D,QAAM,KAAK,YAAY;AACvB,MAAI,QAAQ;AAEZ,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,aAAa;AAGjD,aAAW,SAAS,iBAAiB;AACnC,UAAM,OAAO,GAAG;AAAA,MACd,iBAAiB,KAAK;AAAA;AAAA;AAAA;AAAA,0EAI8C,KAAK;AAAA;AAAA,IAE3E,EAAE,IAAI,KAAK;AAEX,QAAI,KAAK,WAAW,EAAG;AAEvB,UAAM,cAAc,GAAG,YAAY,CAAC,cAAyC;AAC3E,YAAM,OAAO,GAAG;AAAA,QACd;AAAA;AAAA,MAEF;AACA,iBAAW,OAAO,WAAW;AAC3B,aAAK,IAAI,OAAO,OAAO,IAAI,EAAE,GAAG,KAAK,UAAU,GAAG,GAAG,WAAW,GAAG;AAAA,MACrE;AAAA,IACF,CAAC;AAED,gBAAY,IAAI;AAChB,aAAS,KAAK;AAAA,EAChB;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/daemon/team-context.ts","../src/db/queries/team-outbox.ts"],"sourcesContent":["/**\n * Module-level state for team sync.\n *\n * Initialized once by the daemon on startup. Query modules import\n * `isTeamSyncEnabled()` and `getTeamMachineId()` to decide whether\n * to enqueue outbox records on write.\n */\n\nimport { SYNC_PROTOCOL_VERSION, DEFAULT_MACHINE_ID } from '@myco/constants.js';\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n\nlet teamSyncEnabled = false;\nlet teamMachineId = DEFAULT_MACHINE_ID;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Initialize team context. Called once on daemon startup.\n */\nexport function initTeamContext(enabled: boolean, machineId: string): void {\n teamSyncEnabled = enabled;\n teamMachineId = machineId;\n}\n\n/**\n * Whether team sync is currently enabled.\n *\n * Query modules check this before enqueuing outbox records.\n */\nexport function isTeamSyncEnabled(): boolean {\n return teamSyncEnabled;\n}\n\n/**\n * The machine ID for this instance.\n */\nexport function getTeamMachineId(): string {\n return teamMachineId;\n}\n\n/**\n * The sync protocol version in use.\n */\nexport function getTeamSyncProtocolVersion(): number {\n return SYNC_PROTOCOL_VERSION;\n}\n\n/**\n * Reset team context (for testing).\n */\nexport function resetTeamContext(): void {\n teamSyncEnabled = false;\n teamMachineId = DEFAULT_MACHINE_ID;\n}\n","/**\n * Team outbox CRUD query helpers.\n *\n * The outbox pattern: write paths enqueue records here when team sync is enabled.\n * The sync client flushes pending records in batches to the Cloudflare Worker.\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 { isTeamSyncEnabled, getTeamMachineId } from '@myco/daemon/team-context.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Max records returned per listPending call. */\nconst BURST_BATCH_SIZE = 200;\n\n/** Age in seconds after which sent records are pruned (24 hours). */\nconst SENT_PRUNE_AGE_SECONDS = 86_400;\n\n/** Milliseconds-per-second multiplier for epoch math. */\nconst MS_PER_SECOND = 1000;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required when enqueuing an outbox record. */\nexport interface OutboxInsert {\n table_name: string;\n row_id: string;\n operation?: string;\n payload: string;\n machine_id: string;\n created_at: number;\n}\n\n/** Row shape returned from outbox queries. */\nexport interface OutboxRow {\n id: number;\n table_name: string;\n row_id: string;\n operation: string;\n payload: string;\n machine_id: string;\n created_at: number;\n sent_at: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst OUTBOX_COLUMNS = [\n 'id',\n 'table_name',\n 'row_id',\n 'operation',\n 'payload',\n 'machine_id',\n 'created_at',\n 'sent_at',\n] as const;\n\nconst SELECT_COLUMNS = OUTBOX_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed OutboxRow. */\nfunction toOutboxRow(row: Record<string, unknown>): OutboxRow {\n return {\n id: row.id as number,\n table_name: row.table_name as string,\n row_id: row.row_id as string,\n operation: row.operation as string,\n payload: row.payload as string,\n machine_id: row.machine_id as string,\n created_at: row.created_at as number,\n sent_at: (row.sent_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Convenience helper — used by query modules\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue a row for team sync if sync is enabled.\n *\n * Centralizes the if-enabled / enqueue / serialize pattern that every\n * write-path query module previously duplicated inline.\n */\nexport function syncRow(tableName: string, row: { id: string | number; created_at?: number }): void {\n if (!isTeamSyncEnabled()) return;\n enqueueOutbox({\n table_name: tableName,\n row_id: String(row.id),\n payload: JSON.stringify(row),\n machine_id: getTeamMachineId(),\n created_at: row.created_at ?? Math.floor(Date.now() / 1000),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue a record into the team outbox for later sync.\n *\n * Inserted with `sent_at = NULL` (pending).\n */\nexport function enqueueOutbox(data: OutboxInsert): OutboxRow {\n const db = getDatabase();\n\n const info = db.prepare(\n `INSERT INTO team_outbox (\n table_name, row_id, operation, payload, machine_id, created_at\n ) VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(\n data.table_name,\n data.row_id,\n data.operation ?? 'upsert',\n data.payload,\n data.machine_id,\n data.created_at,\n );\n\n const id = Number(info.lastInsertRowid);\n\n return toOutboxRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM team_outbox WHERE id = ?`).get(id) as Record<string, unknown>,\n );\n}\n\n/**\n * List pending outbox records (oldest-first).\n *\n * Uses burst sizing: fetches BURST_BATCH_SIZE rows and returns them all.\n * If fewer than BURST_THRESHOLD rows come back, callers get a normal-size\n * batch; if more, the full burst. This avoids a separate COUNT query.\n */\nexport function listPending(limit?: number): OutboxRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM team_outbox\n WHERE sent_at IS NULL\n ORDER BY created_at ASC\n LIMIT ?`,\n ).all(limit ?? BURST_BATCH_SIZE) as Record<string, unknown>[];\n\n return rows.map(toOutboxRow);\n}\n\n/**\n * Mark outbox records as sent by setting sent_at.\n */\nexport function markSent(ids: number[], sentAt: number): void {\n if (ids.length === 0) return;\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET sent_at = ?\n WHERE id IN (${placeholders})`,\n ).run(sentAt, ...ids);\n}\n\n/**\n * Reset sent_at to NULL for records that need to be retried.\n *\n * This allows the sync client to re-enqueue specific records for retry.\n */\nexport function markForRetry(ids: number[]): void {\n if (ids.length === 0) return;\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET sent_at = NULL\n WHERE id IN (${placeholders})`,\n ).run(...ids);\n}\n\n/**\n * Prune old outbox records.\n *\n * Removes sent records older than 24 hours.\n *\n * @returns the number of records deleted.\n */\nexport function pruneOld(): number {\n const db = getDatabase();\n const cutoff = Math.floor(Date.now() / MS_PER_SECOND) - SENT_PRUNE_AGE_SECONDS;\n\n const info = db.prepare(\n `DELETE FROM team_outbox\n WHERE sent_at IS NOT NULL AND sent_at < ?`,\n ).run(cutoff);\n\n return info.changes;\n}\n\n/**\n * Count pending (unsent) outbox records.\n */\nexport function countPending(): number {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM team_outbox WHERE sent_at IS NULL`,\n ).get() as { count: number };\n\n return row.count;\n}\n\n// ---------------------------------------------------------------------------\n// Source-row sync bookkeeping\n// ---------------------------------------------------------------------------\n\n/** Tables eligible for backfill/sync (must have id, machine_id, synced_at columns). */\nconst BACKFILL_TABLES = [\n 'sessions',\n 'prompt_batches',\n 'spores',\n 'entities',\n 'graph_edges',\n 'resolution_events',\n 'plans',\n 'artifacts',\n 'digest_extracts',\n 'skill_candidates',\n 'skill_records',\n] as const;\n// entity_mentions excluded — no `id` column (composite key entity_id+note_id+note_type)\n// skill_usage excluded — no `synced_at` column (syncs via syncRow on insert)\n\nconst BACKFILL_TABLE_SET = new Set<string>(BACKFILL_TABLES);\n\n/**\n * Mark source rows as synced after successful outbox flush.\n *\n * Groups outbox records by table_name, then sets `synced_at` on the\n * corresponding source rows. This closes the re-enqueue loop: once\n * synced_at is non-NULL, `backfillUnsynced` skips the row even after\n * the outbox entry is pruned.\n */\nexport function markSourceRowsSynced(records: OutboxRow[], syncedAt: number): void {\n const db = getDatabase();\n\n // Group row_ids by table\n const byTable = new Map<string, string[]>();\n for (const rec of records) {\n if (!BACKFILL_TABLE_SET.has(rec.table_name)) continue;\n const ids = byTable.get(rec.table_name) ?? [];\n ids.push(rec.row_id);\n byTable.set(rec.table_name, ids);\n }\n\n for (const [table, ids] of byTable) {\n const placeholders = ids.map(() => '?').join(', ');\n db.prepare(\n `UPDATE ${table} SET synced_at = ? WHERE id IN (${placeholders}) AND synced_at IS NULL`,\n ).run(syncedAt, ...ids);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Backfill\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue all unsynced records across all synced tables into the outbox.\n *\n * Scans each table for rows where `synced_at IS NULL`, serializes the full\n * row as JSON, and inserts into the outbox. Idempotent — re-running only\n * picks up rows not yet in the outbox (checked via existing outbox entries).\n *\n * @returns the total number of records enqueued.\n */\nexport function backfillUnsynced(machineId: string): number {\n const db = getDatabase();\n let total = 0;\n\n const now = Math.floor(Date.now() / MS_PER_SECOND);\n\n // Process one table at a time in separate transactions to avoid long locks\n for (const table of BACKFILL_TABLES) {\n const rows = db.prepare(\n `SELECT * FROM ${table}\n WHERE synced_at IS NULL\n AND NOT EXISTS (\n SELECT 1 FROM team_outbox\n WHERE team_outbox.table_name = ? AND team_outbox.row_id = CAST(${table}.id AS TEXT)\n )`,\n ).all(table) as Record<string, unknown>[];\n\n if (rows.length === 0) continue;\n\n const insertBatch = db.transaction((batchRows: Record<string, unknown>[]) => {\n const stmt = db.prepare(\n `INSERT INTO team_outbox (table_name, row_id, operation, payload, machine_id, created_at)\n VALUES (?, ?, 'upsert', ?, ?, ?)`,\n );\n for (const row of batchRows) {\n stmt.run(table, String(row.id), JSON.stringify(row), machineId, now);\n }\n });\n\n insertBatch(rows);\n total += rows.length;\n }\n\n return total;\n}\n\n"],"mappings":"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","names":[]}
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  getTeamMachineId,
4
4
  syncRow
5
- } from "./chunk-NRT2ZRUG.js";
5
+ } from "./chunk-S66YG6QK.js";
6
6
  import {
7
7
  getDatabase
8
8
  } from "./chunk-MYX5NCRH.js";
@@ -88,4 +88,4 @@ export {
88
88
  insertResolutionEvent,
89
89
  listResolutionEvents
90
90
  };
91
- //# sourceMappingURL=chunk-2PWO3WPS.js.map
91
+ //# sourceMappingURL=chunk-TVV6PZOC.js.map
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  getTeamMachineId,
4
4
  syncRow
5
- } from "./chunk-NRT2ZRUG.js";
5
+ } from "./chunk-S66YG6QK.js";
6
6
  import {
7
7
  getDatabase
8
8
  } from "./chunk-MYX5NCRH.js";
@@ -296,4 +296,4 @@ export {
296
296
  getSessionImpact,
297
297
  deleteSessionCascade
298
298
  };
299
- //# sourceMappingURL=chunk-JBFFAGJK.js.map
299
+ //# sourceMappingURL=chunk-X34OFKYU.js.map
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-OQVKLTQY.js";
9
9
  import {
10
10
  DaemonClient
11
- } from "./chunk-VQEXXS56.js";
11
+ } from "./chunk-NYTEHLVI.js";
12
12
  import {
13
13
  resolveVaultDir
14
14
  } from "./chunk-JTYZRPX5.js";
@@ -39,4 +39,4 @@ async function sendEvent(hookName, buildEvent) {
39
39
  export {
40
40
  sendEvent
41
41
  };
42
- //# sourceMappingURL=chunk-YYQWCTF6.js.map
42
+ //# sourceMappingURL=chunk-XNHHADBK.js.map
@@ -2,13 +2,13 @@
2
2
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
3
3
  import {
4
4
  loadEnv
5
- } from "./chunk-TFGGH6UB.js";
5
+ } from "./chunk-RUDOGKWF.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
7
  import "./chunk-TNCBMGWB.js";
8
8
  import "./chunk-HHZ3RTEI.js";
9
9
  import "./chunk-MYX5NCRH.js";
10
- import "./chunk-VQEXXS56.js";
11
- import "./chunk-EUQQVKGQ.js";
10
+ import "./chunk-NYTEHLVI.js";
11
+ import "./chunk-CCKPBAKJ.js";
12
12
  import "./chunk-LPUQPDC2.js";
13
13
  import "./chunk-TRA3R4EC.js";
14
14
  import "./chunk-S6I62FAH.js";
@@ -54,29 +54,29 @@ async function main() {
54
54
  process.stdout.write(USAGE);
55
55
  return;
56
56
  }
57
- if (cmd === "init") return (await import("./init-ZSDMXY4T.js")).run(args);
57
+ if (cmd === "init") return (await import("./init-W6VRN5ZZ.js")).run(args);
58
58
  if (cmd === "detect-providers") return (await import("./detect-providers-PAVE2X6O.js")).run(args);
59
59
  if (cmd === "version" || cmd === "--version" || cmd === "-v") {
60
- const { getPluginVersion } = await import("./version-RGX7TZ7V.js");
60
+ const { getPluginVersion } = await import("./version-ELM3BK4H.js");
61
61
  console.log(getPluginVersion());
62
62
  return;
63
63
  }
64
- if (cmd === "mcp") return (await import("./server-CXPWUO6H.js")).main();
64
+ if (cmd === "mcp") return (await import("./server-XJTAWCHN.js")).main();
65
65
  if (cmd === "hook") {
66
66
  const hookName = args[0];
67
67
  const HOOK_DISPATCH = {
68
- "session-start": () => import("./session-start-QNAQDF5M.js"),
69
- "session-end": () => import("./session-end-6DP6VTZV.js"),
70
- "stop": () => import("./stop-VTO2KIRG.js"),
71
- "user-prompt-submit": () => import("./user-prompt-submit-VLQG77A6.js"),
72
- "post-tool-use": () => import("./post-tool-use-Y6UWKCVD.js"),
73
- "post-tool-use-failure": () => import("./post-tool-use-failure-AHFXMNHX.js"),
74
- "subagent-start": () => import("./subagent-start-NZF42NKF.js"),
75
- "subagent-stop": () => import("./subagent-stop-UV5ECFVU.js"),
76
- "stop-failure": () => import("./stop-failure-C5T6LJQR.js"),
77
- "task-completed": () => import("./task-completed-3SV6TL3V.js"),
78
- "pre-compact": () => import("./pre-compact-EI5EV3N7.js"),
79
- "post-compact": () => import("./post-compact-E5V4OZJB.js")
68
+ "session-start": () => import("./session-start-XHH6RN7T.js"),
69
+ "session-end": () => import("./session-end-5AI4U3KC.js"),
70
+ "stop": () => import("./stop-ZIKA2LGJ.js"),
71
+ "user-prompt-submit": () => import("./user-prompt-submit-HPBZOZHM.js"),
72
+ "post-tool-use": () => import("./post-tool-use-KNOFQNVX.js"),
73
+ "post-tool-use-failure": () => import("./post-tool-use-failure-UIRHWELN.js"),
74
+ "subagent-start": () => import("./subagent-start-XNAZKYVD.js"),
75
+ "subagent-stop": () => import("./subagent-stop-QTJSJYIT.js"),
76
+ "stop-failure": () => import("./stop-failure-MF22OJ7R.js"),
77
+ "task-completed": () => import("./task-completed-24BVLKOC.js"),
78
+ "pre-compact": () => import("./pre-compact-T3CR4C3Q.js"),
79
+ "post-compact": () => import("./post-compact-55ISYIPY.js")
80
80
  };
81
81
  const loader = HOOK_DISPATCH[hookName];
82
82
  if (!loader) {
@@ -85,13 +85,13 @@ async function main() {
85
85
  }
86
86
  return (await loader()).main();
87
87
  }
88
- if (cmd === "daemon") return (await import("./main-25MKYYKO.js")).main();
88
+ if (cmd === "daemon") return (await import("./main-XUQRWNJ7.js")).main();
89
89
  if (cmd === "doctor") {
90
90
  const vaultDir2 = resolveVaultDir();
91
- return (await import("./doctor-GDCLRJOF.js")).run(args, vaultDir2);
91
+ return (await import("./doctor-TYMLSW5K.js")).run(args, vaultDir2);
92
92
  }
93
- if (cmd === "update") return (await import("./update-5GXOQIY5.js")).run(args);
94
- if (cmd === "remove") return (await import("./remove-F63WBELE.js")).run(args);
93
+ if (cmd === "update") return (await import("./update-LRPXOWMZ.js")).run(args);
94
+ if (cmd === "remove") return (await import("./remove-HIIXTVAK.js")).run(args);
95
95
  const vaultDir = resolveVaultDir();
96
96
  if (!fs.existsSync(path.join(vaultDir, "myco.yaml"))) {
97
97
  console.error(`No myco.yaml found in ${vaultDir}. Run 'myco init' first.`);
@@ -99,37 +99,37 @@ async function main() {
99
99
  }
100
100
  switch (cmd) {
101
101
  case "config":
102
- return (await import("./config-WBCOTJUE.js")).run(args, vaultDir);
102
+ return (await import("./config-H657SF6B.js")).run(args, vaultDir);
103
103
  case "verify":
104
- return (await import("./verify-WF7U3NQW.js")).run(args, vaultDir);
104
+ return (await import("./verify-JHIMXTY5.js")).run(args, vaultDir);
105
105
  case "stats":
106
- return (await import("./stats-VQ7XMOCU.js")).run(args, vaultDir);
106
+ return (await import("./stats-BDE5FTO6.js")).run(args, vaultDir);
107
107
  case "search":
108
- return (await import("./search-NLZMCEAG.js")).run(args, vaultDir);
108
+ return (await import("./search-C3CIHCMP.js")).run(args, vaultDir);
109
109
  case "vectors":
110
- return (await import("./search-NLZMCEAG.js")).runVectors(args, vaultDir);
110
+ return (await import("./search-C3CIHCMP.js")).runVectors(args, vaultDir);
111
111
  case "session":
112
- return (await import("./session-XXVEDIQZ.js")).run(args, vaultDir);
112
+ return (await import("./session-CUGCZWCY.js")).run(args, vaultDir);
113
113
  case "setup-llm":
114
- return (await import("./setup-llm-ER3B7AZ2.js")).run(args, vaultDir);
114
+ return (await import("./setup-llm-3LYRV4KB.js")).run(args, vaultDir);
115
115
  case "setup-digest":
116
116
  return (await import("./setup-digest-4KDSXAIV.js")).run(args, vaultDir);
117
117
  case "agent":
118
- return (await import("./agent-run-YBASQHC7.js")).run(args, vaultDir);
118
+ return (await import("./agent-run-VX5MAPRN.js")).run(args, vaultDir);
119
119
  case "task":
120
- return (await import("./agent-tasks-WBQFDHWC.js")).run(args, vaultDir);
120
+ return (await import("./agent-tasks-FJOBYYC5.js")).run(args, vaultDir);
121
121
  case "team": {
122
122
  const sub = args[0];
123
- if (sub === "init") return (await import("./team-XSJXLBZX.js")).teamInit(vaultDir);
124
- if (sub === "upgrade") return (await import("./team-XSJXLBZX.js")).teamUpgrade(vaultDir);
123
+ if (sub === "init") return (await import("./team-SJPDXELY.js")).teamInit(vaultDir);
124
+ if (sub === "upgrade") return (await import("./team-SJPDXELY.js")).teamUpgrade(vaultDir);
125
125
  console.error("Usage: myco team <init|upgrade>");
126
126
  process.exit(1);
127
127
  break;
128
128
  }
129
129
  case "open":
130
- return (await import("./open-4YTUNIP3.js")).run(args, vaultDir);
130
+ return (await import("./open-6EC54JEU.js")).run(args, vaultDir);
131
131
  case "restart":
132
- return (await import("./restart-GULUNCMX.js")).run(args, vaultDir);
132
+ return (await import("./restart-5FJYFNIR.js")).run(args, vaultDir);
133
133
  case "logs":
134
134
  return (await import("./logs-LXHPDKUA.js")).run(args, vaultDir);
135
135
  default:
@@ -142,4 +142,4 @@ main().catch((err) => {
142
142
  console.error(`myco: ${err.message}`);
143
143
  process.exit(1);
144
144
  });
145
- //# sourceMappingURL=cli-WCBTILMW.js.map
145
+ //# sourceMappingURL=cli-Z7VO7LIL.js.map
@@ -2,8 +2,8 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  DaemonClient,
4
4
  resolveCliEntryPath
5
- } from "./chunk-VQEXXS56.js";
6
- import "./chunk-EUQQVKGQ.js";
5
+ } from "./chunk-NYTEHLVI.js";
6
+ import "./chunk-CCKPBAKJ.js";
7
7
  import "./chunk-LPUQPDC2.js";
8
8
  import "./chunk-TRA3R4EC.js";
9
9
  import "./chunk-S6I62FAH.js";
@@ -12,4 +12,4 @@ export {
12
12
  DaemonClient,
13
13
  resolveCliEntryPath
14
14
  };
15
- //# sourceMappingURL=client-MJUZJ5MC.js.map
15
+ //# sourceMappingURL=client-CECN26WV.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  loadConfig,
7
7
  updateConfig
8
- } from "./chunk-W3T3QDBN.js";
8
+ } from "./chunk-PSYLKCWQ.js";
9
9
  import "./chunk-TRA3R4EC.js";
10
10
  import "./chunk-S6I62FAH.js";
11
11
  import "./chunk-D7TYRPRM.js";
@@ -87,4 +87,4 @@ function parseValue(raw) {
87
87
  export {
88
88
  run
89
89
  };
90
- //# sourceMappingURL=config-WBCOTJUE.js.map
90
+ //# sourceMappingURL=config-H657SF6B.js.map
@@ -1,15 +1,15 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  isProcessAlive
4
- } from "./chunk-TFGGH6UB.js";
4
+ } from "./chunk-RUDOGKWF.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import {
7
7
  MYCO_MCP_SERVER_NAME
8
8
  } from "./chunk-TNCBMGWB.js";
9
9
  import "./chunk-HHZ3RTEI.js";
10
10
  import "./chunk-MYX5NCRH.js";
11
- import "./chunk-VQEXXS56.js";
12
- import "./chunk-EUQQVKGQ.js";
11
+ import "./chunk-NYTEHLVI.js";
12
+ import "./chunk-CCKPBAKJ.js";
13
13
  import "./chunk-LPUQPDC2.js";
14
14
  import "./chunk-TRA3R4EC.js";
15
15
  import "./chunk-S6I62FAH.js";
@@ -29,7 +29,7 @@ async function checkVault(vaultDir) {
29
29
  return { check: { name: "Vault", status: "fail", detail: `${CONFIG_FILENAME} not found in ${vaultDir}`, fixable: false }, config: null };
30
30
  }
31
31
  try {
32
- const { loadConfig } = await import("./loader-L2TCAYCT.js");
32
+ const { loadConfig } = await import("./loader-JQLO6K44.js");
33
33
  const config = loadConfig(vaultDir);
34
34
  return { check: { name: "Vault", status: "ok", detail: `.myco/ (v${config.version})`, fixable: false }, config };
35
35
  } catch (err) {
@@ -251,4 +251,4 @@ export {
251
251
  run,
252
252
  runChecks
253
253
  };
254
- //# sourceMappingURL=doctor-GDCLRJOF.js.map
254
+ //# sourceMappingURL=doctor-TYMLSW5K.js.map
@@ -19,18 +19,18 @@ import {
19
19
  insertReport,
20
20
  insertRun,
21
21
  insertSkillRecord,
22
- insertTurn,
23
22
  listCandidates,
24
23
  listDigestExtracts,
25
24
  listEntities,
26
25
  listGraphEdges,
27
26
  listSkillRecords,
28
27
  markBatchProcessed,
28
+ notify,
29
29
  updateCandidate,
30
30
  updateRunStatus,
31
31
  updateSkillRecord,
32
32
  upsertDigestExtract
33
- } from "./chunk-5BK6M6X5.js";
33
+ } from "./chunk-JJXVDCEX.js";
34
34
  import {
35
35
  fullTextSearch
36
36
  } from "./chunk-DTE3SHYK.js";
@@ -46,27 +46,30 @@ import {
46
46
  resolveDefinitionsDir,
47
47
  resolveEffectiveConfig
48
48
  } from "./chunk-NVCGF2DS.js";
49
+ import {
50
+ insertTurn
51
+ } from "./chunk-QLCD77AN.js";
49
52
  import {
50
53
  insertResolutionEvent
51
- } from "./chunk-2PWO3WPS.js";
54
+ } from "./chunk-TVV6PZOC.js";
52
55
  import "./chunk-IB76KGBY.js";
53
56
  import {
54
57
  DEFAULT_IMPORTANCE,
55
58
  insertSpore,
56
59
  listSpores,
57
60
  updateSporeStatus
58
- } from "./chunk-LPISXFM4.js";
61
+ } from "./chunk-PX5KIOKY.js";
59
62
  import {
60
63
  listSessions,
61
64
  updateSession
62
- } from "./chunk-JBFFAGJK.js";
63
- import "./chunk-NRT2ZRUG.js";
65
+ } from "./chunk-X34OFKYU.js";
66
+ import "./chunk-S66YG6QK.js";
64
67
  import {
65
68
  createSchema
66
- } from "./chunk-NCVR636M.js";
69
+ } from "./chunk-4VF6KQ2Z.js";
67
70
  import {
68
71
  loadConfig
69
- } from "./chunk-W3T3QDBN.js";
72
+ } from "./chunk-PSYLKCWQ.js";
70
73
  import {
71
74
  getDatabase,
72
75
  initDatabase,
@@ -74,7 +77,7 @@ import {
74
77
  } from "./chunk-MYX5NCRH.js";
75
78
  import {
76
79
  getPluginVersion
77
- } from "./chunk-EUQQVKGQ.js";
80
+ } from "./chunk-CCKPBAKJ.js";
78
81
  import {
79
82
  findPackageRoot
80
83
  } from "./chunk-LPUQPDC2.js";
@@ -178,13 +181,29 @@ function validateSkillContent(content, dirName) {
178
181
  if (managedMatch && managedMatch[1].trim() !== "myco") {
179
182
  issues.push(`managed_by must be "myco". Got: "${managedMatch[1].trim()}"`);
180
183
  }
184
+ const allowedToolsMatch = frontmatter.match(/^allowed-tools:\s*(.+)$/m);
185
+ if (allowedToolsMatch) {
186
+ const toolsValue = allowedToolsMatch[1].trim();
187
+ if (toolsValue.includes("vault_")) {
188
+ issues.push(
189
+ "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions \u2014 use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
190
+ );
191
+ }
192
+ }
193
+ const listToolLines = frontmatter.match(/^\s+-\s+vault_\w+/gm);
194
+ if (listToolLines) {
195
+ issues.push(
196
+ "allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions \u2014 use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
197
+ );
198
+ }
181
199
  const lineCount = content.split("\n").length;
182
200
  if (lineCount > MAX_SKILL_LINES) {
183
201
  issues.push(`Skill is ${lineCount} lines (max ${MAX_SKILL_LINES})`);
184
202
  }
185
203
  return issues;
186
204
  }
187
- function createVaultTools(agentId, runId, turnOffset = 0, embeddingManager, teamClient, machineId, projectRoot) {
205
+ function createVaultTools(agentId, runId, options) {
206
+ const { turnOffset = 0, embeddingManager, teamClient, machineId, projectRoot, vaultDir } = options ?? {};
188
207
  let turnCounter = turnOffset;
189
208
  function recordTurn(toolName, toolInput) {
190
209
  turnCounter++;
@@ -679,6 +698,14 @@ function createVaultTools(agentId, runId, turnOffset = 0, embeddingManager, team
679
698
  created_at: now,
680
699
  updated_at: now
681
700
  });
701
+ notify(vaultDir, {
702
+ domain: "skills",
703
+ type: "skill.surveyed",
704
+ title: `Skill candidate: ${args.topic}`,
705
+ message: args.rationale.slice(0, 120),
706
+ link: "/skills?tab=candidates",
707
+ metadata: { candidateId: candidate.id, topic: args.topic }
708
+ });
682
709
  return textResult(candidate);
683
710
  }
684
711
  case "update": {
@@ -896,6 +923,15 @@ function createVaultTools(agentId, runId, turnOffset = 0, embeddingManager, team
896
923
  }
897
924
  }
898
925
  })();
926
+ const isNew = generation === 1;
927
+ notify(vaultDir, {
928
+ domain: "skills",
929
+ type: isNew ? "skill.created" : "skill.evolved",
930
+ title: isNew ? `Skill created: ${args.display_name}` : `Skill evolved: ${args.display_name}`,
931
+ message: args.description.slice(0, 120),
932
+ link: `/skills?skill=${encodeURIComponent(args.name)}`,
933
+ metadata: { skillId: recordId, name: args.name, generation }
934
+ });
899
935
  recordTurn("vault_write_skill", args);
900
936
  return textResult({
901
937
  id: recordId,
@@ -929,16 +965,16 @@ function createVaultTools(agentId, runId, turnOffset = 0, embeddingManager, team
929
965
  vaultWriteSkill
930
966
  ];
931
967
  }
932
- function createVaultToolServer(agentId, runId, embeddingManager) {
933
- const tools = createVaultTools(agentId, runId, 0, embeddingManager);
968
+ function createVaultToolServer(agentId, runId, options) {
969
+ const tools = createVaultTools(agentId, runId, options);
934
970
  return createSdkMcpServer({
935
971
  name: "myco-vault",
936
972
  version: getPluginVersion(),
937
973
  tools
938
974
  });
939
975
  }
940
- function createScopedVaultToolServer(agentId, runId, toolNames, turnOffset = 0, embeddingManager, projectRoot) {
941
- const allTools = createVaultTools(agentId, runId, turnOffset, embeddingManager, null, void 0, projectRoot);
976
+ function createScopedVaultToolServer(agentId, runId, toolNames, options) {
977
+ const allTools = createVaultTools(agentId, runId, options);
942
978
  const nameSet = new Set(toolNames);
943
979
  const scopedTools = allTools.filter((t) => nameSet.has(t.name));
944
980
  return createSdkMcpServer({
@@ -1454,9 +1490,9 @@ async function executePhase(query, phasePrompt, phaseModel, systemPrompt, toolSe
1454
1490
  };
1455
1491
  }
1456
1492
  }
1457
- async function executeSingleQuery(config, systemPrompt, taskPrompt, agentId, runId, provider, embeddingManager, abortController) {
1493
+ async function executeSingleQuery(config, systemPrompt, taskPrompt, agentId, runId, provider, embeddingManager, abortController, vaultDir) {
1458
1494
  const { query } = await import("@anthropic-ai/claude-agent-sdk");
1459
- const toolServer = createVaultToolServer(agentId, runId, embeddingManager);
1495
+ const toolServer = createVaultToolServer(agentId, runId, { embeddingManager, vaultDir });
1460
1496
  const env = buildPhaseEnv(provider);
1461
1497
  const effectiveModel = provider?.model ?? config.model;
1462
1498
  let resultCostUsd = 0;
@@ -1483,7 +1519,7 @@ async function executeSingleQuery(config, systemPrompt, taskPrompt, agentId, run
1483
1519
  }
1484
1520
  return { tokensUsed: resultTokens, costUsd: resultCostUsd };
1485
1521
  }
1486
- async function executePhasedQuery(config, systemPrompt, vaultContext, agentId, runId, taskProviderOverride, phaseProviderOverrides, instruction, embeddingManager, abortController, projectRoot) {
1522
+ async function executePhasedQuery(config, systemPrompt, vaultContext, agentId, runId, taskProviderOverride, phaseProviderOverrides, instruction, embeddingManager, abortController, projectRoot, vaultDir) {
1487
1523
  const { query } = await import("@anthropic-ai/claude-agent-sdk");
1488
1524
  const phases = config.phases;
1489
1525
  const phaseResults = [];
@@ -1535,9 +1571,12 @@ async function executePhasedQuery(config, systemPrompt, vaultContext, agentId, r
1535
1571
  agentId,
1536
1572
  runId,
1537
1573
  phase.tools,
1538
- runningTurnCount + indexInWave * effectiveMaxTurns,
1539
- embeddingManager,
1540
- projectRoot
1574
+ {
1575
+ turnOffset: runningTurnCount + indexInWave * effectiveMaxTurns,
1576
+ embeddingManager,
1577
+ projectRoot,
1578
+ vaultDir
1579
+ }
1541
1580
  );
1542
1581
  const phaseProvider = phase.provider ?? phaseOverride?.provider ?? taskProviderOverride ?? config.execution?.provider;
1543
1582
  const env = buildPhaseEnv(phaseProvider);
@@ -1703,7 +1742,8 @@ async function runAgent(vaultDir, options) {
1703
1742
  options?.instruction,
1704
1743
  options?.embeddingManager,
1705
1744
  taskAbortController,
1706
- projectRoot
1745
+ projectRoot,
1746
+ vaultDir
1707
1747
  );
1708
1748
  tokensUsed = result.tokensUsed;
1709
1749
  costUsd = result.costUsd;
@@ -1724,7 +1764,8 @@ async function runAgent(vaultDir, options) {
1724
1764
  runId,
1725
1765
  singleProvider,
1726
1766
  options?.embeddingManager,
1727
- taskAbortController
1767
+ taskAbortController,
1768
+ vaultDir
1728
1769
  );
1729
1770
  tokensUsed = result.tokensUsed;
1730
1771
  costUsd = result.costUsd;
@@ -1786,4 +1827,4 @@ export {
1786
1827
  computeWaves,
1787
1828
  runAgent
1788
1829
  };
1789
- //# sourceMappingURL=executor-TCAXFOIS.js.map
1830
+ //# sourceMappingURL=executor-4DKCQN3A.js.map