@tekmidian/pai 0.11.0 → 0.12.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 (128) hide show
  1. package/README.md +84 -10
  2. package/dist/{auto-route-D54Kv7yI.mjs → auto-route-CLYcToZ5.mjs} +4 -4
  3. package/dist/{auto-route-D54Kv7yI.mjs.map → auto-route-CLYcToZ5.mjs.map} +1 -1
  4. package/dist/cli/index.mjs +20 -10275
  5. package/dist/cli/index.mjs.map +1 -1
  6. package/dist/cli/program.d.mts +11 -0
  7. package/dist/cli/program.d.mts.map +1 -0
  8. package/dist/cli/program.mjs +249 -0
  9. package/dist/cli/program.mjs.map +1 -0
  10. package/dist/{clusters-BwmdKB-V.mjs → clusters-BYPw7vfW.mjs} +2 -2
  11. package/dist/{clusters-BwmdKB-V.mjs.map → clusters-BYPw7vfW.mjs.map} +1 -1
  12. package/dist/{config-DqBY3aT0.mjs → config-BuhHWyOK.mjs} +1 -1
  13. package/dist/{config-DqBY3aT0.mjs.map → config-BuhHWyOK.mjs.map} +1 -1
  14. package/dist/daemon/index.mjs +16 -18
  15. package/dist/daemon/index.mjs.map +1 -1
  16. package/dist/{daemon-CSKj8Xm9.mjs → daemon-BldK8-57.mjs} +197 -43
  17. package/dist/daemon-BldK8-57.mjs.map +1 -0
  18. package/dist/daemon-mcp/index.mjs +2 -2
  19. package/dist/{db-CYmBWcjh.mjs → db-CmYbAVCD.mjs} +1 -1
  20. package/dist/{db-CYmBWcjh.mjs.map → db-CmYbAVCD.mjs.map} +1 -1
  21. package/dist/{detect-CdaA48EI.mjs → detect-KjycLtXM.mjs} +1 -1
  22. package/dist/{detect-CdaA48EI.mjs.map → detect-KjycLtXM.mjs.map} +1 -1
  23. package/dist/{detector-Q_lVXtj-.mjs → detector-ZiOhHszd.mjs} +2 -2
  24. package/dist/{detector-Q_lVXtj-.mjs.map → detector-ZiOhHszd.mjs.map} +1 -1
  25. package/dist/{embeddings-DGRAPAYb.mjs → embeddings-BJPOcbik.mjs} +1 -1
  26. package/dist/{embeddings-DGRAPAYb.mjs.map → embeddings-BJPOcbik.mjs.map} +1 -1
  27. package/dist/factory-Q88X1bAN.mjs +69 -0
  28. package/dist/factory-Q88X1bAN.mjs.map +1 -0
  29. package/dist/{helpers-crDEr6S2.mjs → helpers-IjZkXBhj.mjs} +1 -1
  30. package/dist/{helpers-crDEr6S2.mjs.map → helpers-IjZkXBhj.mjs.map} +1 -1
  31. package/dist/hooks/observe.mjs +21 -0
  32. package/dist/hooks/observe.mjs.map +2 -2
  33. package/dist/index.mjs +9 -10
  34. package/dist/{indexer-backend-DcYThufd.mjs → indexer-backend-Cm5RS7y0.mjs} +3 -3
  35. package/dist/{indexer-backend-DcYThufd.mjs.map → indexer-backend-Cm5RS7y0.mjs.map} +1 -1
  36. package/dist/{ipc-client-C3pjwy2m.mjs → ipc-client-CoyUHPod.mjs} +1 -1
  37. package/dist/{ipc-client-C3pjwy2m.mjs.map → ipc-client-CoyUHPod.mjs.map} +1 -1
  38. package/dist/{kg-entity-DVzTsy6G.mjs → kg-entity-LXblD7LZ.mjs} +1 -1
  39. package/dist/{kg-entity-DVzTsy6G.mjs.map → kg-entity-LXblD7LZ.mjs.map} +1 -1
  40. package/dist/{kg-extraction-iR1BKKWK.mjs → kg-extraction-C8DEUHTS.mjs} +17 -6
  41. package/dist/kg-extraction-C8DEUHTS.mjs.map +1 -0
  42. package/dist/{latent-ideas-dWVuI_dg.mjs → latent-ideas-RyC6eyqI.mjs} +4 -4
  43. package/dist/{latent-ideas-dWVuI_dg.mjs.map → latent-ideas-RyC6eyqI.mjs.map} +1 -1
  44. package/dist/main-resolver-uFxNiDy7.mjs +1339 -0
  45. package/dist/main-resolver-uFxNiDy7.mjs.map +1 -0
  46. package/dist/{migrate-fLD6rAdO.mjs → migrate-B02wDDgS.mjs} +2 -2
  47. package/dist/{migrate-fLD6rAdO.mjs.map → migrate-B02wDDgS.mjs.map} +1 -1
  48. package/dist/{neighborhood-DixmpfPT.mjs → neighborhood-CklGIB8r.mjs} +2 -2
  49. package/dist/{neighborhood-DixmpfPT.mjs.map → neighborhood-CklGIB8r.mjs.map} +1 -1
  50. package/dist/{note-context-BY7rfGdl.mjs → note-context-qvZlVXVO.mjs} +1 -1
  51. package/dist/{note-context-BY7rfGdl.mjs.map → note-context-qvZlVXVO.mjs.map} +1 -1
  52. package/dist/{pai-marker-CXQPX2P6.mjs → pai-marker-HVBwwBW-.mjs} +1 -1
  53. package/dist/{pai-marker-CXQPX2P6.mjs.map → pai-marker-HVBwwBW-.mjs.map} +1 -1
  54. package/dist/pick-7Kg9DX7S.mjs +8250 -0
  55. package/dist/pick-7Kg9DX7S.mjs.map +1 -0
  56. package/dist/{postgres-Cp25xZes.mjs → postgres-B451Hnkm.mjs} +2 -2
  57. package/dist/{postgres-Cp25xZes.mjs.map → postgres-B451Hnkm.mjs.map} +1 -1
  58. package/dist/{query-feedback-C0hKUHVz.mjs → query-feedback-fapbqRgh.mjs} +1 -1
  59. package/dist/{query-feedback-C0hKUHVz.mjs.map → query-feedback-fapbqRgh.mjs.map} +1 -1
  60. package/dist/{reranker-CMNZcfVx.mjs → reranker-C08R99zn.mjs} +1 -1
  61. package/dist/{reranker-CMNZcfVx.mjs.map → reranker-C08R99zn.mjs.map} +1 -1
  62. package/dist/{search-i2nlQ-JM.mjs → search-HcdKtMla.mjs} +3 -3
  63. package/dist/{search-i2nlQ-JM.mjs.map → search-HcdKtMla.mjs.map} +1 -1
  64. package/dist/{sqlite-B3JHfJc2.mjs → sqlite-DQpY1Esi.mjs} +3 -3
  65. package/dist/{sqlite-B3JHfJc2.mjs.map → sqlite-DQpY1Esi.mjs.map} +1 -1
  66. package/dist/{state-BHZAhLou.mjs → state-BIlxNRUn.mjs} +1 -1
  67. package/dist/{state-BHZAhLou.mjs.map → state-BIlxNRUn.mjs.map} +1 -1
  68. package/dist/{stop-words-BaMEGVeY.mjs → stop-words-BwplsQ3z.mjs} +1 -1
  69. package/dist/{stop-words-BaMEGVeY.mjs.map → stop-words-BwplsQ3z.mjs.map} +1 -1
  70. package/dist/{sync-CmBKOL3K.mjs → sync-uPR4g438.mjs} +205 -6
  71. package/dist/sync-uPR4g438.mjs.map +1 -0
  72. package/dist/{themes-DO8mUVwD.mjs → themes-Cg8oG9Ra.mjs} +3 -3
  73. package/dist/{themes-DO8mUVwD.mjs.map → themes-Cg8oG9Ra.mjs.map} +1 -1
  74. package/dist/{tools-C1JNgya7.mjs → tools-Op3C2Nm6.mjs} +26 -26
  75. package/dist/{tools-C1JNgya7.mjs.map → tools-Op3C2Nm6.mjs.map} +1 -1
  76. package/dist/{trace-TYCLMCkY.mjs → trace-CLK-NPkb.mjs} +1 -1
  77. package/dist/{trace-TYCLMCkY.mjs.map → trace-CLK-NPkb.mjs.map} +1 -1
  78. package/dist/{utils-BAxjW3j8.mjs → utils-CqqgB0dH.mjs} +1 -1
  79. package/dist/{utils-BAxjW3j8.mjs.map → utils-CqqgB0dH.mjs.map} +1 -1
  80. package/dist/{vault-indexer-vNnL3Azb.mjs → vault-indexer-Dn_BccVK.mjs} +2 -2
  81. package/dist/{vault-indexer-vNnL3Azb.mjs.map → vault-indexer-Dn_BccVK.mjs.map} +1 -1
  82. package/dist/{work-queue-worker-BxsBtz6j.mjs → work-queue-worker-DHOIVVQ7.mjs} +5 -5
  83. package/dist/{work-queue-worker-BxsBtz6j.mjs.map → work-queue-worker-DHOIVVQ7.mjs.map} +1 -1
  84. package/dist/{zettelkasten-B-94vghH.mjs → zettelkasten-NwBD1NsT.mjs} +4 -4
  85. package/dist/{zettelkasten-B-94vghH.mjs.map → zettelkasten-NwBD1NsT.mjs.map} +1 -1
  86. package/docs/commands/README.md +151 -0
  87. package/docs/commands/_examples/kg.md +13 -0
  88. package/docs/commands/_examples/memory.md +13 -0
  89. package/docs/commands/_examples/observation.md +13 -0
  90. package/docs/commands/_examples/projects.md +16 -0
  91. package/docs/commands/_examples/skill.md +13 -0
  92. package/docs/commands/_examples/zettel.md +13 -0
  93. package/docs/commands/backup.md +24 -0
  94. package/docs/commands/clear-names.md +27 -0
  95. package/docs/commands/daemon.md +78 -0
  96. package/docs/commands/db.md +74 -0
  97. package/docs/commands/end.md +24 -0
  98. package/docs/commands/help.md +30 -0
  99. package/docs/commands/kg.md +89 -0
  100. package/docs/commands/mcp.md +35 -0
  101. package/docs/commands/memory.md +125 -0
  102. package/docs/commands/notify.md +83 -0
  103. package/docs/commands/observation.md +80 -0
  104. package/docs/commands/obsidian.md +60 -0
  105. package/docs/commands/pause.md +35 -0
  106. package/docs/commands/project.md +345 -0
  107. package/docs/commands/projects.md +364 -0
  108. package/docs/commands/registry.md +68 -0
  109. package/docs/commands/restore.md +31 -0
  110. package/docs/commands/sessions.md +25 -0
  111. package/docs/commands/setup.md +20 -0
  112. package/docs/commands/shell-init.md +18 -0
  113. package/docs/commands/skill.md +54 -0
  114. package/docs/commands/topic.md +46 -0
  115. package/docs/commands/update.md +18 -0
  116. package/docs/commands/zettel.md +151 -0
  117. package/docs/mcp-skill-guide.md +292 -0
  118. package/package.json +4 -2
  119. package/scripts/build-docs.mjs +371 -0
  120. package/src/hooks/ts/post-tool-use/observe.ts +43 -0
  121. package/dist/daemon-CSKj8Xm9.mjs.map +0 -1
  122. package/dist/db-BtuN768f.mjs +0 -206
  123. package/dist/db-BtuN768f.mjs.map +0 -1
  124. package/dist/factory-BufouUQ1.mjs +0 -44
  125. package/dist/factory-BufouUQ1.mjs.map +0 -1
  126. package/dist/indexer-D7MvSQPY.mjs +0 -1
  127. package/dist/kg-extraction-iR1BKKWK.mjs.map +0 -1
  128. package/dist/sync-CmBKOL3K.mjs.map +0 -1
@@ -1,15 +1,14 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs";
2
- import { n as openRegistry } from "./db-BtuN768f.mjs";
3
- import { n as openFederation } from "./db-CYmBWcjh.mjs";
4
- import { d as sha256 } from "./helpers-crDEr6S2.mjs";
5
- import { n as indexAll } from "./sync-CmBKOL3K.mjs";
6
- import { t as configureEmbeddingModel } from "./embeddings-DGRAPAYb.mjs";
7
- import { n as CONFIG_FILE, s as DEFAULT_NOTIFICATION_CONFIG, t as CONFIG_DIR } from "./config-DqBY3aT0.mjs";
8
- import { t as createStorageBackend } from "./factory-BufouUQ1.mjs";
9
- import { C as setStorageBackend, E as startTime, O as storageBackend, S as setStartTime, T as shutdownRequested, _ as setLastIndexTime, a as indexSchedulerTimer, b as setRegistryDb, c as lastVaultIndexTime, d as setDaemonConfig, f as setEmbedInProgress, g as setLastEmbedTime, h as setIndexSchedulerTimer, i as indexInProgress, k as vaultIndexInProgress, l as notificationConfig, m as setIndexInProgress, n as embedInProgress, o as lastEmbedTime, p as setEmbedSchedulerTimer, r as embedSchedulerTimer, s as lastIndexTime, t as daemonConfig, u as registryDb, v as setLastVaultIndexTime, w as setVaultIndexInProgress, x as setShutdownRequested, y as setNotificationConfig } from "./state-BHZAhLou.mjs";
10
- import { a as toolMemoryWakeup, c as toolSessionRoute, d as toolProjectInfo, f as toolProjectList, h as toolMemorySearch, i as toolMemoryTaxonomy, l as toolProjectDetect, m as toolMemoryGet, n as toolMemoryKgSearch, o as toolRegistrySearch, p as toolProjectTodo, r as toolMemoryFeedback, s as toolSessionList, u as toolProjectHealth } from "./tools-C1JNgya7.mjs";
11
- import { t as detectTopicShift } from "./detector-Q_lVXtj-.mjs";
12
- import { a as enqueue, n as startWorker, o as getStats, r as stopWorker, s as loadQueue, t as notifyNewWork } from "./work-queue-worker-BxsBtz6j.mjs";
2
+ import { a as openRegistry, n as indexAll } from "./sync-uPR4g438.mjs";
3
+ import { n as openFederation } from "./db-CmYbAVCD.mjs";
4
+ import { d as sha256 } from "./helpers-IjZkXBhj.mjs";
5
+ import { t as configureEmbeddingModel } from "./embeddings-BJPOcbik.mjs";
6
+ import { t as createStorageBackend } from "./factory-Q88X1bAN.mjs";
7
+ import { n as CONFIG_FILE, s as DEFAULT_NOTIFICATION_CONFIG, t as CONFIG_DIR } from "./config-BuhHWyOK.mjs";
8
+ import { C as setStorageBackend, E as startTime, O as storageBackend, S as setStartTime, T as shutdownRequested, _ as setLastIndexTime, a as indexSchedulerTimer, b as setRegistryDb, c as lastVaultIndexTime, d as setDaemonConfig, f as setEmbedInProgress, g as setLastEmbedTime, h as setIndexSchedulerTimer, i as indexInProgress, k as vaultIndexInProgress, l as notificationConfig, m as setIndexInProgress, n as embedInProgress, o as lastEmbedTime, p as setEmbedSchedulerTimer, r as embedSchedulerTimer, s as lastIndexTime, t as daemonConfig, u as registryDb, v as setLastVaultIndexTime, w as setVaultIndexInProgress, x as setShutdownRequested, y as setNotificationConfig } from "./state-BIlxNRUn.mjs";
9
+ import { a as toolMemoryWakeup, c as toolSessionRoute, d as toolProjectInfo, f as toolProjectList, h as toolMemorySearch, i as toolMemoryTaxonomy, l as toolProjectDetect, m as toolMemoryGet, n as toolMemoryKgSearch, o as toolRegistrySearch, p as toolProjectTodo, r as toolMemoryFeedback, s as toolSessionList, u as toolProjectHealth } from "./tools-Op3C2Nm6.mjs";
10
+ import { t as detectTopicShift } from "./detector-ZiOhHszd.mjs";
11
+ import { a as enqueue, n as startWorker, o as getStats, r as stopWorker, s as loadQueue, t as notifyNewWork } from "./work-queue-worker-DHOIVVQ7.mjs";
13
12
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
14
13
  import { setPriority } from "node:os";
15
14
  import { randomUUID } from "node:crypto";
@@ -112,7 +111,7 @@ async function runIndex() {
112
111
  try {
113
112
  process.stderr.write("[pai-daemon] Starting scheduled index run...\n");
114
113
  if (storageBackend.backendType === "sqlite") {
115
- const { SQLiteBackend } = await import("./sqlite-B3JHfJc2.mjs");
114
+ const { SQLiteBackend } = await import("./sqlite-DQpY1Esi.mjs");
116
115
  if (storageBackend instanceof SQLiteBackend) {
117
116
  const { projects, result } = await indexAll(storageBackend.getRawDb(), registryDb);
118
117
  const elapsed = Date.now() - t0;
@@ -120,7 +119,7 @@ async function runIndex() {
120
119
  process.stderr.write(`[pai-daemon] Index complete: ${projects} projects, ${result.filesProcessed} files, ${result.chunksCreated} chunks (${elapsed}ms)\n`);
121
120
  }
122
121
  } else {
123
- const { indexAllWithBackend } = await import("./indexer-backend-DcYThufd.mjs");
122
+ const { indexAllWithBackend } = await import("./indexer-backend-Cm5RS7y0.mjs");
124
123
  const { projects, result } = await indexAllWithBackend(storageBackend, registryDb);
125
124
  const elapsed = Date.now() - t0;
126
125
  setLastIndexTime(Date.now());
@@ -147,7 +146,7 @@ async function runVaultIndex() {
147
146
  process.stderr.write("[pai-daemon] Index/embed in progress, deferring vault index.\n");
148
147
  return;
149
148
  }
150
- const { lastVaultIndexTime } = await import("./state-BHZAhLou.mjs").then((n) => n.D);
149
+ const { lastVaultIndexTime } = await import("./state-BIlxNRUn.mjs").then((n) => n.D);
151
150
  if (lastVaultIndexTime > 0 && Date.now() - lastVaultIndexTime < VAULT_INDEX_MIN_INTERVAL_MS) return;
152
151
  let vaultProjectId = daemonConfig.vaultProjectId;
153
152
  if (!vaultProjectId) {
@@ -159,7 +158,7 @@ async function runVaultIndex() {
159
158
  const t0 = Date.now();
160
159
  process.stderr.write("[pai-daemon] Starting vault index run...\n");
161
160
  try {
162
- const { indexVault } = await import("./vault-indexer-vNnL3Azb.mjs");
161
+ const { indexVault } = await import("./vault-indexer-Dn_BccVK.mjs");
163
162
  const r = await indexVault(storageBackend, vaultProjectId, daemonConfig.vaultPath);
164
163
  const elapsed = Date.now() - t0;
165
164
  setLastVaultIndexTime(Date.now());
@@ -212,12 +211,12 @@ async function runEmbed() {
212
211
  const rows = registryDb.prepare("SELECT id, slug FROM projects WHERE status = 'active'").all();
213
212
  for (const r of rows) projectNames.set(r.id, r.slug);
214
213
  } catch {}
215
- const { embedChunksWithBackend } = await import("./indexer-backend-DcYThufd.mjs");
214
+ const { embedChunksWithBackend } = await import("./indexer-backend-Cm5RS7y0.mjs");
216
215
  const count = await embedChunksWithBackend(storageBackend, () => shutdownRequested, projectNames);
217
216
  let vaultEmbedCount = 0;
218
217
  if (daemonConfig.vaultPath) try {
219
- const { SQLiteBackend } = await import("./sqlite-B3JHfJc2.mjs");
220
- const { openFederation } = await import("./db-CYmBWcjh.mjs").then((n) => n.t);
218
+ const { SQLiteBackend } = await import("./sqlite-DQpY1Esi.mjs");
219
+ const { openFederation } = await import("./db-CmYbAVCD.mjs").then((n) => n.t);
221
220
  const federationDb = openFederation();
222
221
  const vaultSqliteBackend = new SQLiteBackend(federationDb);
223
222
  const vaultProjectNames = new Map(projectNames);
@@ -271,12 +270,12 @@ const REGISTRY_SCAN_STARTUP_DELAY_MS = 1e4;
271
270
  function startRegistryScanScheduler() {
272
271
  process.stderr.write("[pai-daemon] Registry scan scheduler: every 30min (first in 10s)\n");
273
272
  setTimeout(() => {
274
- import("./work-queue-worker-BxsBtz6j.mjs").then((n) => n.i).then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
273
+ import("./work-queue-worker-DHOIVVQ7.mjs").then((n) => n.i).then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
275
274
  process.stderr.write(`[pai-daemon] Startup registry scan error: ${e}\n`);
276
275
  });
277
276
  }, REGISTRY_SCAN_STARTUP_DELAY_MS);
278
277
  const timer = setInterval(() => {
279
- import("./work-queue-worker-BxsBtz6j.mjs").then((n) => n.i).then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
278
+ import("./work-queue-worker-DHOIVVQ7.mjs").then((n) => n.i).then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
280
279
  process.stderr.write(`[pai-daemon] Scheduled registry scan error: ${e}\n`);
281
280
  });
282
281
  }, REGISTRY_SCAN_INTERVAL_MS);
@@ -688,6 +687,90 @@ async function storeSessionSummary(pool, summary) {
688
687
  summary.observation_count ?? 0
689
688
  ]);
690
689
  }
690
+ const SKILL_TELEMETRY_SCHEMA_SQL = `
691
+ CREATE TABLE IF NOT EXISTS pai_skill_telemetry (
692
+ id SERIAL PRIMARY KEY,
693
+ scope TEXT NOT NULL DEFAULT 'default',
694
+ skill_name TEXT NOT NULL,
695
+ source TEXT NOT NULL DEFAULT 'local',
696
+ status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('trial','active','archived')),
697
+ trigger_count INTEGER NOT NULL DEFAULT 0,
698
+ accept_count INTEGER NOT NULL DEFAULT 0,
699
+ first_triggered TIMESTAMPTZ DEFAULT NOW(),
700
+ last_triggered TIMESTAMPTZ DEFAULT NOW(),
701
+ context_projects JSONB DEFAULT '[]'::jsonb,
702
+ hash TEXT,
703
+ audit_status TEXT,
704
+ last_audited TIMESTAMPTZ,
705
+ UNIQUE(scope, skill_name, source)
706
+ );
707
+
708
+ CREATE INDEX IF NOT EXISTS idx_skilltel_scope ON pai_skill_telemetry(scope);
709
+ CREATE INDEX IF NOT EXISTS idx_skilltel_status ON pai_skill_telemetry(scope, status);
710
+ CREATE INDEX IF NOT EXISTS idx_skilltel_last ON pai_skill_telemetry(last_triggered DESC);
711
+ `;
712
+ let _skillTelemetryEnsured = false;
713
+ async function ensureSkillTelemetryTable(pool) {
714
+ if (_skillTelemetryEnsured) return;
715
+ await pool.query(SKILL_TELEMETRY_SCHEMA_SQL);
716
+ _skillTelemetryEnsured = true;
717
+ }
718
+ /**
719
+ * Record a single skill invocation. Upserts on (scope, skill_name, source):
720
+ * increments trigger_count, refreshes last_triggered, and dedup-merges the
721
+ * project slug into context_projects.
722
+ */
723
+ async function recordSkillInvocation(pool, input) {
724
+ await ensureSkillTelemetryTable(pool);
725
+ const scope = input.scope ?? "default";
726
+ const source = input.source ?? "local";
727
+ const proj = input.project_slug ?? null;
728
+ const initialProjects = JSON.stringify(proj ? [proj] : []);
729
+ await pool.query(`INSERT INTO pai_skill_telemetry
730
+ (scope, skill_name, source, trigger_count, context_projects)
731
+ VALUES ($1, $2, $3, 1, $4::jsonb)
732
+ ON CONFLICT (scope, skill_name, source) DO UPDATE SET
733
+ trigger_count = pai_skill_telemetry.trigger_count + 1,
734
+ last_triggered = NOW(),
735
+ context_projects = CASE
736
+ WHEN $5::text IS NULL THEN pai_skill_telemetry.context_projects
737
+ WHEN pai_skill_telemetry.context_projects @> to_jsonb($5::text)
738
+ THEN pai_skill_telemetry.context_projects
739
+ ELSE pai_skill_telemetry.context_projects || to_jsonb($5::text)
740
+ END`, [
741
+ scope,
742
+ input.skill_name,
743
+ source,
744
+ initialProjects,
745
+ proj
746
+ ]);
747
+ }
748
+ /**
749
+ * List skill telemetry rows, most-triggered first.
750
+ */
751
+ async function querySkillTelemetry(pool, opts = {}) {
752
+ await ensureSkillTelemetryTable(pool);
753
+ const conditions = [];
754
+ const params = [];
755
+ let idx = 1;
756
+ conditions.push(`scope = $${idx++}`);
757
+ params.push(opts.scope ?? "default");
758
+ if (opts.status !== void 0) {
759
+ conditions.push(`status = $${idx++}`);
760
+ params.push(opts.status);
761
+ }
762
+ const where = `WHERE ${conditions.join(" AND ")}`;
763
+ const limit = opts.limit ?? 100;
764
+ params.push(limit);
765
+ return (await pool.query(`SELECT id, scope, skill_name, source, status,
766
+ trigger_count, accept_count,
767
+ first_triggered, last_triggered,
768
+ context_projects, hash, audit_status, last_audited
769
+ FROM pai_skill_telemetry
770
+ ${where}
771
+ ORDER BY trigger_count DESC, last_triggered DESC
772
+ LIMIT $${idx}`, params)).rows;
773
+ }
691
774
 
692
775
  //#endregion
693
776
  //#region src/daemon/daemon/dispatcher.ts
@@ -722,7 +805,7 @@ async function dispatchTool(method, params) {
722
805
  case "zettel_themes":
723
806
  case "zettel_god_notes":
724
807
  case "zettel_communities": {
725
- const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-C1JNgya7.mjs").then((n) => n.t);
808
+ const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-Op3C2Nm6.mjs").then((n) => n.t);
726
809
  switch (method) {
727
810
  case "zettel_explore": return toolZettelExplore(storageBackend, p);
728
811
  case "zettel_health": return toolZettelHealth(storageBackend, p);
@@ -736,27 +819,27 @@ async function dispatchTool(method, params) {
736
819
  break;
737
820
  }
738
821
  case "graph_clusters": {
739
- const { handleGraphClusters } = await import("./clusters-BwmdKB-V.mjs");
822
+ const { handleGraphClusters } = await import("./clusters-BYPw7vfW.mjs");
740
823
  return handleGraphClusters(storageBackend.getPool?.() ?? null, storageBackend, p);
741
824
  }
742
825
  case "graph_neighborhood": {
743
- const { handleGraphNeighborhood } = await import("./neighborhood-DixmpfPT.mjs");
826
+ const { handleGraphNeighborhood } = await import("./neighborhood-CklGIB8r.mjs");
744
827
  return handleGraphNeighborhood(storageBackend.getPool?.() ?? null, storageBackend, p);
745
828
  }
746
829
  case "graph_note_context": {
747
- const { handleGraphNoteContext } = await import("./note-context-BY7rfGdl.mjs");
830
+ const { handleGraphNoteContext } = await import("./note-context-qvZlVXVO.mjs");
748
831
  return handleGraphNoteContext(storageBackend.getPool?.() ?? null, storageBackend, p);
749
832
  }
750
833
  case "graph_trace": {
751
- const { handleGraphTrace } = await import("./trace-TYCLMCkY.mjs");
834
+ const { handleGraphTrace } = await import("./trace-CLK-NPkb.mjs");
752
835
  return handleGraphTrace(storageBackend, p);
753
836
  }
754
837
  case "graph_latent_ideas": {
755
- const { handleGraphLatentIdeas } = await import("./latent-ideas-dWVuI_dg.mjs");
838
+ const { handleGraphLatentIdeas } = await import("./latent-ideas-RyC6eyqI.mjs");
756
839
  return handleGraphLatentIdeas(storageBackend, p);
757
840
  }
758
841
  case "idea_materialize": {
759
- const { handleIdeaMaterialize } = await import("./latent-ideas-dWVuI_dg.mjs");
842
+ const { handleIdeaMaterialize } = await import("./latent-ideas-RyC6eyqI.mjs");
760
843
  if (!daemonConfig.vaultPath) throw new Error("idea_materialize requires vaultPath to be configured in the daemon config");
761
844
  return handleIdeaMaterialize(p, daemonConfig.vaultPath);
762
845
  }
@@ -764,7 +847,7 @@ async function dispatchTool(method, params) {
764
847
  case "kg_query":
765
848
  case "kg_invalidate":
766
849
  case "kg_contradictions": {
767
- const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-C1JNgya7.mjs").then((n) => n.t);
850
+ const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-Op3C2Nm6.mjs").then((n) => n.t);
768
851
  const pgPool = storageBackend.getPool?.() ?? null;
769
852
  if (!pgPool) throw new Error(`${method} requires a Postgres storage backend`);
770
853
  switch (method) {
@@ -776,7 +859,7 @@ async function dispatchTool(method, params) {
776
859
  break;
777
860
  }
778
861
  case "memory_tunnels": {
779
- const { toolMemoryTunnels } = await import("./tools-C1JNgya7.mjs").then((n) => n.t);
862
+ const { toolMemoryTunnels } = await import("./tools-Op3C2Nm6.mjs").then((n) => n.t);
780
863
  return toolMemoryTunnels(registryDb, storageBackend, p);
781
864
  }
782
865
  case "memory_feedback": {
@@ -819,6 +902,7 @@ async function handleRequest(request, socket) {
819
902
  if (method === "status") {
820
903
  const dbStats = await (async () => {
821
904
  try {
905
+ if (!storageBackend) return null;
822
906
  const fedStats = await storageBackend.getStats();
823
907
  const projects = registryDb.prepare("SELECT COUNT(*) AS n FROM projects").get().n;
824
908
  return {
@@ -842,7 +926,7 @@ async function handleRequest(request, socket) {
842
926
  lastEmbedTime: lastEmbedTime ? new Date(lastEmbedTime).toISOString() : null,
843
927
  embedIntervalSecs: daemonConfig.embedIntervalSecs,
844
928
  socketPath: daemonConfig.socketPath,
845
- storageBackend: storageBackend.backendType,
929
+ storageBackend: storageBackend?.backendType ?? "initializing",
846
930
  db: dbStats,
847
931
  vaultIndexInProgress,
848
932
  lastVaultIndexTime: lastVaultIndexTime ? new Date(lastVaultIndexTime).toISOString() : null,
@@ -998,6 +1082,77 @@ async function handleRequest(request, socket) {
998
1082
  socket.end();
999
1083
  return;
1000
1084
  }
1085
+ if (method === "skill_telemetry_record") {
1086
+ const pool = storageBackend.getPool?.();
1087
+ if (!pool) {
1088
+ sendResponse(socket, {
1089
+ id,
1090
+ ok: false,
1091
+ error: "Skill telemetry requires Postgres backend"
1092
+ });
1093
+ socket.end();
1094
+ return;
1095
+ }
1096
+ try {
1097
+ const p = params;
1098
+ let project_slug = null;
1099
+ if (p.cwd) {
1100
+ const row = registryDb.prepare("SELECT slug FROM projects WHERE status = 'active' AND ? LIKE root_path || '%' ORDER BY length(root_path) DESC LIMIT 1").get(p.cwd);
1101
+ if (row) project_slug = row.slug;
1102
+ }
1103
+ await recordSkillInvocation(pool, {
1104
+ skill_name: p.skill_name,
1105
+ source: p.source,
1106
+ scope: p.scope,
1107
+ project_slug
1108
+ });
1109
+ sendResponse(socket, {
1110
+ id,
1111
+ ok: true,
1112
+ result: { ok: true }
1113
+ });
1114
+ } catch (e) {
1115
+ sendResponse(socket, {
1116
+ id,
1117
+ ok: false,
1118
+ error: e instanceof Error ? e.message : String(e)
1119
+ });
1120
+ }
1121
+ socket.end();
1122
+ return;
1123
+ }
1124
+ if (method === "skill_telemetry_query") {
1125
+ const pool = storageBackend.getPool?.();
1126
+ if (!pool) {
1127
+ sendResponse(socket, {
1128
+ id,
1129
+ ok: false,
1130
+ error: "Skill telemetry requires Postgres backend"
1131
+ });
1132
+ socket.end();
1133
+ return;
1134
+ }
1135
+ try {
1136
+ const p = params;
1137
+ sendResponse(socket, {
1138
+ id,
1139
+ ok: true,
1140
+ result: await querySkillTelemetry(pool, {
1141
+ scope: p.scope,
1142
+ status: p.status,
1143
+ limit: p.limit
1144
+ })
1145
+ });
1146
+ } catch (e) {
1147
+ sendResponse(socket, {
1148
+ id,
1149
+ ok: false,
1150
+ error: e instanceof Error ? e.message : String(e)
1151
+ });
1152
+ }
1153
+ socket.end();
1154
+ return;
1155
+ }
1001
1156
  if (method === "observation_query") {
1002
1157
  const pool = storageBackend.getPool?.();
1003
1158
  if (!pool) {
@@ -1354,7 +1509,7 @@ async function serve(config) {
1354
1509
  process.stderr.write("[pai-daemon] Starting daemon...\n");
1355
1510
  process.stderr.write(`[pai-daemon] Socket: ${config.socketPath}\n`);
1356
1511
  process.stderr.write(`[pai-daemon] Storage backend: ${config.storageBackend}\n`);
1357
- const { notificationConfig } = await import("./state-BHZAhLou.mjs").then((n) => n.D);
1512
+ const { notificationConfig } = await import("./state-BIlxNRUn.mjs").then((n) => n.D);
1358
1513
  process.stderr.write(`[pai-daemon] Notification mode: ${notificationConfig.mode}\n`);
1359
1514
  try {
1360
1515
  setPriority(process.pid, 10);
@@ -1368,22 +1523,21 @@ async function serve(config) {
1368
1523
  process.stderr.write(`[pai-daemon] Fatal: Could not open registry: ${msg}\n`);
1369
1524
  process.exit(1);
1370
1525
  }
1371
- try {
1372
- const backend = await createStorageBackend(config);
1526
+ const server = await startIpcServer(config.socketPath);
1527
+ startRegistryScanScheduler();
1528
+ createStorageBackend(config, { waitForPostgres: true }).then((backend) => {
1373
1529
  setStorageBackend(backend);
1374
1530
  process.stderr.write(`[pai-daemon] Federation backend: ${backend.backendType}\n`);
1375
- } catch (e) {
1531
+ startIndexScheduler();
1532
+ if (backend.backendType === "postgres") startEmbedScheduler();
1533
+ else process.stderr.write("[pai-daemon] Embed scheduler: disabled (SQLite backend)\n");
1534
+ loadQueue();
1535
+ startWorker();
1536
+ }).catch((e) => {
1376
1537
  const msg = e instanceof Error ? e.message : String(e);
1377
1538
  process.stderr.write(`[pai-daemon] Fatal: Could not open federation storage: ${msg}\n`);
1378
1539
  process.exit(1);
1379
- }
1380
- startIndexScheduler();
1381
- if (storageBackend.backendType === "postgres") startEmbedScheduler();
1382
- else process.stderr.write("[pai-daemon] Embed scheduler: disabled (SQLite backend)\n");
1383
- loadQueue();
1384
- startWorker();
1385
- startRegistryScanScheduler();
1386
- const server = await startIpcServer(config.socketPath);
1540
+ });
1387
1541
  const shutdown = async (signal) => {
1388
1542
  process.stderr.write(`\n[pai-daemon] ${signal} received. Stopping.\n`);
1389
1543
  setShutdownRequested(true);
@@ -1423,4 +1577,4 @@ var daemon_exports = /* @__PURE__ */ __exportAll({ serve: () => serve });
1423
1577
 
1424
1578
  //#endregion
1425
1579
  export { serve as n, daemon_exports as t };
1426
- //# sourceMappingURL=daemon-CSKj8Xm9.mjs.map
1580
+ //# sourceMappingURL=daemon-BldK8-57.mjs.map