@deeplake/hivemind 0.7.45 → 0.7.47

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 (39) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +64 -0
  4. package/bundle/cli.js +22702 -7775
  5. package/codex/bundle/capture.js +228 -0
  6. package/codex/bundle/commands/auth-login.js +228 -0
  7. package/codex/bundle/graph-pull-worker.js +1370 -0
  8. package/codex/bundle/pre-tool-use.js +228 -0
  9. package/codex/bundle/session-start-setup.js +228 -0
  10. package/codex/bundle/session-start.js +255 -4
  11. package/codex/bundle/shell/deeplake-shell.js +1028 -28
  12. package/codex/bundle/skillify-worker.js +94 -3
  13. package/codex/bundle/stop.js +282 -50
  14. package/codex/skills/hivemind-goals/SKILL.md +157 -0
  15. package/cursor/bundle/capture.js +282 -50
  16. package/cursor/bundle/commands/auth-login.js +228 -0
  17. package/cursor/bundle/graph-pull-worker.js +1370 -0
  18. package/cursor/bundle/pre-tool-use.js +228 -0
  19. package/cursor/bundle/session-end.js +65 -44
  20. package/cursor/bundle/session-start.js +662 -6
  21. package/cursor/bundle/shell/deeplake-shell.js +1028 -28
  22. package/cursor/bundle/skillify-worker.js +94 -3
  23. package/hermes/bundle/capture.js +282 -50
  24. package/hermes/bundle/commands/auth-login.js +228 -0
  25. package/hermes/bundle/graph-pull-worker.js +1370 -0
  26. package/hermes/bundle/pre-tool-use.js +228 -0
  27. package/hermes/bundle/session-end.js +65 -44
  28. package/hermes/bundle/session-start.js +662 -6
  29. package/hermes/bundle/shell/deeplake-shell.js +1028 -28
  30. package/hermes/bundle/skillify-worker.js +94 -3
  31. package/mcp/bundle/server.js +228 -0
  32. package/openclaw/dist/chunks/config-FH6JYSJW.js +53 -0
  33. package/openclaw/dist/index.js +307 -2
  34. package/openclaw/dist/skillify-worker.js +94 -3
  35. package/openclaw/openclaw.plugin.json +4 -2
  36. package/openclaw/package.json +1 -1
  37. package/openclaw/skills/hivemind-goals/SKILL.md +30 -0
  38. package/package.json +4 -1
  39. package/openclaw/dist/chunks/config-XEK4MJJS.js +0 -36
@@ -378,6 +378,65 @@ var SKILLS_COLUMNS = Object.freeze([
378
378
  { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
379
379
  { name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
380
380
  ]);
381
+ var RULES_COLUMNS = Object.freeze([
382
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
383
+ { name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
384
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
385
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
386
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
387
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
388
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
389
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
390
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
391
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
392
+ ]);
393
+ var TASKS_COLUMNS = Object.freeze([
394
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
395
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
396
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
397
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
398
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
399
+ { name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
400
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
401
+ { name: "kpis", sql: "JSONB" },
402
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
403
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
404
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
405
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
406
+ ]);
407
+ var TASK_EVENTS_COLUMNS = Object.freeze([
408
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
409
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
410
+ { name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
411
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
412
+ { name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
413
+ { name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
414
+ { name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
415
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
416
+ { name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
417
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
418
+ ]);
419
+ var GOALS_COLUMNS = Object.freeze([
420
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
421
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
422
+ { name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
423
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
424
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
425
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
426
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
427
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
428
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
429
+ ]);
430
+ var KPIS_COLUMNS = Object.freeze([
431
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
432
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
433
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
434
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
435
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
436
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
437
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
438
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
439
+ ]);
381
440
  function validateSchema(label, cols) {
382
441
  const seen = /* @__PURE__ */ new Set();
383
442
  for (const col of cols) {
@@ -395,9 +454,38 @@ function validateSchema(label, cols) {
395
454
  }
396
455
  }
397
456
  }
457
+ var CODEBASE_COLUMNS = Object.freeze([
458
+ // Identity key (matches the PK below)
459
+ { name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
460
+ { name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
461
+ { name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
462
+ { name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
463
+ { name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
464
+ { name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
465
+ // Observation metadata
466
+ { name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
467
+ { name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
468
+ { name: "ts", sql: "TIMESTAMP" },
469
+ { name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
470
+ // Snapshot payload
471
+ { name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
472
+ { name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
473
+ { name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
474
+ { name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
475
+ // Generator metadata (for drift diagnostics — what hivemind version produced this?)
476
+ { name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
477
+ { name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
478
+ { name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
479
+ ]);
398
480
  validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
399
481
  validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
400
482
  validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
483
+ validateSchema("RULES_COLUMNS", RULES_COLUMNS);
484
+ validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
485
+ validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
486
+ validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
487
+ validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
488
+ validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
401
489
  function buildCreateTableSql(tableName, cols) {
402
490
  const safe = sqlIdent(tableName);
403
491
  const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
@@ -693,9 +781,12 @@ function resolveRecordScope(args) {
693
781
 
694
782
  // dist/src/skillify/state.js
695
783
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, rmdirSync, existsSync as existsSync4, lstatSync, unlinkSync, openSync, closeSync } from "node:fs";
784
+ import { join as join6 } from "node:path";
785
+
786
+ // dist/src/utils/repo-identity.js
696
787
  import { execSync } from "node:child_process";
697
788
  import { createHash } from "node:crypto";
698
- import { join as join6, basename } from "node:path";
789
+ import { basename, resolve } from "node:path";
699
790
 
700
791
  // dist/src/skillify/legacy-migration.js
701
792
  import { existsSync as existsSync3, renameSync } from "node:fs";
@@ -881,7 +972,7 @@ async function query(sql, retries = 4) {
881
972
  const base = Math.min(3e4, 2e3 * Math.pow(2, attempt));
882
973
  const delay = base + Math.floor(Math.random() * 1e3);
883
974
  wlog(`fetch failed (${e?.name ?? e?.code ?? e?.message}), retrying in ${delay}ms (attempt ${attempt + 1}/${retries})`);
884
- await new Promise((resolve) => setTimeout(resolve, delay));
975
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
885
976
  continue;
886
977
  }
887
978
  throw e;
@@ -897,7 +988,7 @@ async function query(sql, retries = 4) {
897
988
  const base = Math.min(3e4, 2e3 * Math.pow(2, attempt));
898
989
  const delay = base + Math.floor(Math.random() * 1e3);
899
990
  wlog(`API ${r.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${retries})`);
900
- await new Promise((resolve) => setTimeout(resolve, delay));
991
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
901
992
  continue;
902
993
  }
903
994
  throw new Error(`API ${r.status}: ${(await r.text()).slice(0, 200)}`);
@@ -59,13 +59,13 @@ import { dirname as dirname6, join as join19 } from "node:path";
59
59
 
60
60
  // dist/src/utils/stdin.js
61
61
  function readStdin() {
62
- return new Promise((resolve2, reject) => {
62
+ return new Promise((resolve3, reject) => {
63
63
  let data = "";
64
64
  process.stdin.setEncoding("utf-8");
65
65
  process.stdin.on("data", (chunk) => data += chunk);
66
66
  process.stdin.on("end", () => {
67
67
  try {
68
- resolve2(JSON.parse(data));
68
+ resolve3(JSON.parse(data));
69
69
  } catch (err) {
70
70
  reject(new Error(`Failed to parse hook input: ${err}`));
71
71
  }
@@ -103,6 +103,23 @@ function loadConfig() {
103
103
  tableName: process.env.HIVEMIND_TABLE ?? "memory",
104
104
  sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
105
105
  skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
106
+ // Defaults match the table name written into the SQL — keep aligned
107
+ // with RULES_COLUMNS / TASKS_COLUMNS / TASK_EVENTS_COLUMNS in
108
+ // deeplake-schema.ts and with the e2e test-org override convention
109
+ // (memory_test / sessions_test → goals_test, etc.) documented in
110
+ // CLAUDE.md.
111
+ rulesTableName: process.env.HIVEMIND_RULES_TABLE ?? "hivemind_rules",
112
+ tasksTableName: process.env.HIVEMIND_TASKS_TABLE ?? "hivemind_tasks",
113
+ taskEventsTableName: process.env.HIVEMIND_TASK_EVENTS_TABLE ?? "hivemind_task_events",
114
+ // Goals + KPIs (refined design — VFS path classifier maps
115
+ // memory/goal/<user>/<status>/<uuid>.md → hivemind_goals row
116
+ // memory/kpi/<uuid>/<kpi_id>.md → hivemind_kpis row
117
+ // See src/shell/deeplake-fs.ts for the translation logic and
118
+ // GOALS_COLUMNS / KPIS_COLUMNS in deeplake-schema.ts for the
119
+ // table shape.
120
+ goalsTableName: process.env.HIVEMIND_GOALS_TABLE ?? "hivemind_goals",
121
+ kpisTableName: process.env.HIVEMIND_KPIS_TABLE ?? "hivemind_kpis",
122
+ codebaseTableName: process.env.HIVEMIND_CODEBASE_TABLE ?? "codebase",
106
123
  memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join(home, ".deeplake", "memory")
107
124
  };
108
125
  }
@@ -203,6 +220,65 @@ var SKILLS_COLUMNS = Object.freeze([
203
220
  { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
204
221
  { name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
205
222
  ]);
223
+ var RULES_COLUMNS = Object.freeze([
224
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
225
+ { name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
226
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
227
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
228
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
229
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
230
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
231
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
232
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
233
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
234
+ ]);
235
+ var TASKS_COLUMNS = Object.freeze([
236
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
237
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
238
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
239
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
240
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
241
+ { name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
242
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
243
+ { name: "kpis", sql: "JSONB" },
244
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
245
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
246
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
247
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
248
+ ]);
249
+ var TASK_EVENTS_COLUMNS = Object.freeze([
250
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
251
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
252
+ { name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
253
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
254
+ { name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
255
+ { name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
256
+ { name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
257
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
258
+ { name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
259
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
260
+ ]);
261
+ var GOALS_COLUMNS = Object.freeze([
262
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
263
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
264
+ { name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
265
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
266
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
267
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
268
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
269
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
270
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
271
+ ]);
272
+ var KPIS_COLUMNS = Object.freeze([
273
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
274
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
275
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
276
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
277
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
278
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
279
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
280
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
281
+ ]);
206
282
  function validateSchema(label, cols) {
207
283
  const seen = /* @__PURE__ */ new Set();
208
284
  for (const col of cols) {
@@ -220,9 +296,38 @@ function validateSchema(label, cols) {
220
296
  }
221
297
  }
222
298
  }
299
+ var CODEBASE_COLUMNS = Object.freeze([
300
+ // Identity key (matches the PK below)
301
+ { name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
302
+ { name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
303
+ { name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
304
+ { name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
305
+ { name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
306
+ { name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
307
+ // Observation metadata
308
+ { name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
309
+ { name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
310
+ { name: "ts", sql: "TIMESTAMP" },
311
+ { name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
312
+ // Snapshot payload
313
+ { name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
314
+ { name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
315
+ { name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
316
+ { name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
317
+ // Generator metadata (for drift diagnostics — what hivemind version produced this?)
318
+ { name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
319
+ { name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
320
+ { name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
321
+ ]);
223
322
  validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
224
323
  validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
225
324
  validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
325
+ validateSchema("RULES_COLUMNS", RULES_COLUMNS);
326
+ validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
327
+ validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
328
+ validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
329
+ validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
330
+ validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
226
331
  function buildCreateTableSql(tableName, cols) {
227
332
  const safe = sqlIdent(tableName);
228
333
  const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
@@ -447,7 +552,7 @@ function getQueryTimeoutMs() {
447
552
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
448
553
  }
449
554
  function sleep2(ms) {
450
- return new Promise((resolve2) => setTimeout(resolve2, ms));
555
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
451
556
  }
452
557
  function isTimeoutError(error) {
453
558
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -477,7 +582,7 @@ var Semaphore = class {
477
582
  this.active++;
478
583
  return;
479
584
  }
480
- await new Promise((resolve2) => this.waiting.push(resolve2));
585
+ await new Promise((resolve3) => this.waiting.push(resolve3));
481
586
  }
482
587
  release() {
483
588
  this.active--;
@@ -787,6 +892,24 @@ var DeeplakeApi = class {
787
892
  * This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
788
893
  * worker.
789
894
  */
895
+ /**
896
+ * Create the codebase table. One row per (org, workspace, repo, user,
897
+ * worktree, commit) — see CODEBASE_COLUMNS for the schema. Healing
898
+ * + index follow the same pattern as ensureSessionsTable.
899
+ */
900
+ async ensureCodebaseTable(name) {
901
+ const safe = sqlIdent(name);
902
+ const tables = await this.listTables();
903
+ if (!tables.includes(safe)) {
904
+ log3(`table "${safe}" not found, creating`);
905
+ await this.createTableWithRetry(buildCreateTableSql(safe, CODEBASE_COLUMNS), safe);
906
+ log3(`table "${safe}" created`);
907
+ if (!tables.includes(safe))
908
+ this._tablesCache = [...tables, safe];
909
+ }
910
+ await this.healSchema(safe, CODEBASE_COLUMNS);
911
+ await this.ensureLookupIndex(safe, "codebase_identity", `("org_id", "workspace_id", "repo_slug", "user_id", "worktree_id", "commit_sha")`);
912
+ }
790
913
  async ensureSkillsTable(name) {
791
914
  const safe = sqlIdent(name);
792
915
  const tables = await this.listTables();
@@ -800,6 +923,111 @@ var DeeplakeApi = class {
800
923
  await this.healSchema(safe, SKILLS_COLUMNS);
801
924
  await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
802
925
  }
926
+ /**
927
+ * Create the rules table.
928
+ *
929
+ * One row per rule version (same write pattern as skills): edits INSERT
930
+ * a fresh row with version+1, reads pick latest per rule_id via
931
+ * `ORDER BY version DESC LIMIT 1`. Sidesteps the Deeplake
932
+ * UPDATE-coalescing quirk by never UPDATEing.
933
+ */
934
+ async ensureRulesTable(name) {
935
+ const safe = sqlIdent(name);
936
+ const tables = await this.listTables();
937
+ if (!tables.includes(safe)) {
938
+ log3(`table "${safe}" not found, creating`);
939
+ await this.createTableWithRetry(buildCreateTableSql(safe, RULES_COLUMNS), safe);
940
+ log3(`table "${safe}" created`);
941
+ if (!tables.includes(safe))
942
+ this._tablesCache = [...tables, safe];
943
+ }
944
+ await this.healSchema(safe, RULES_COLUMNS);
945
+ await this.ensureLookupIndex(safe, "rule_id_version", `("rule_id", "version")`);
946
+ }
947
+ /**
948
+ * Create the tasks table.
949
+ *
950
+ * Same write pattern as rules + skills. `kpis` is a nullable JSONB
951
+ * column with the agent's KPI metadata; KPI current values come from
952
+ * `task_events` (SUM(value)), not this snapshot.
953
+ */
954
+ async ensureTasksTable(name) {
955
+ const safe = sqlIdent(name);
956
+ const tables = await this.listTables();
957
+ if (!tables.includes(safe)) {
958
+ log3(`table "${safe}" not found, creating`);
959
+ await this.createTableWithRetry(buildCreateTableSql(safe, TASKS_COLUMNS), safe);
960
+ log3(`table "${safe}" created`);
961
+ if (!tables.includes(safe))
962
+ this._tablesCache = [...tables, safe];
963
+ }
964
+ await this.healSchema(safe, TASKS_COLUMNS);
965
+ await this.ensureLookupIndex(safe, "task_id_version", `("task_id", "version")`);
966
+ }
967
+ /**
968
+ * Create the task-events table.
969
+ *
970
+ * Append-only. Every INSERT is a fresh row; never UPDATE. KPI current
971
+ * value is `SUM(value) WHERE task_id=? AND kpi_id=?`. Index on
972
+ * (task_id, kpi_id) is the canonical aggregation key.
973
+ */
974
+ async ensureTaskEventsTable(name) {
975
+ const safe = sqlIdent(name);
976
+ const tables = await this.listTables();
977
+ if (!tables.includes(safe)) {
978
+ log3(`table "${safe}" not found, creating`);
979
+ await this.createTableWithRetry(buildCreateTableSql(safe, TASK_EVENTS_COLUMNS), safe);
980
+ log3(`table "${safe}" created`);
981
+ if (!tables.includes(safe))
982
+ this._tablesCache = [...tables, safe];
983
+ }
984
+ await this.healSchema(safe, TASK_EVENTS_COLUMNS);
985
+ await this.ensureLookupIndex(safe, "task_id_kpi_id", `("task_id", "kpi_id")`);
986
+ }
987
+ /**
988
+ * Create the goals table.
989
+ *
990
+ * Backed by the VFS path convention memory/goal/<owner>/<status>/<goal_id>.md.
991
+ * INSERT-only version-bumped: rm and mv operations translate to fresh
992
+ * v=N+1 rows (status flips for mv → closed; rm is the same soft-close).
993
+ * The (goal_id, version) index lets the VFS dispatch a cheap latest-row
994
+ * read on cat / Read of a single goal.
995
+ */
996
+ async ensureGoalsTable(name) {
997
+ const safe = sqlIdent(name);
998
+ const tables = await this.listTables();
999
+ if (!tables.includes(safe)) {
1000
+ log3(`table "${safe}" not found, creating`);
1001
+ await this.createTableWithRetry(buildCreateTableSql(safe, GOALS_COLUMNS), safe);
1002
+ log3(`table "${safe}" created`);
1003
+ if (!tables.includes(safe))
1004
+ this._tablesCache = [...tables, safe];
1005
+ }
1006
+ await this.healSchema(safe, GOALS_COLUMNS);
1007
+ await this.ensureLookupIndex(safe, "goal_id_version", `("goal_id", "version")`);
1008
+ await this.ensureLookupIndex(safe, "owner_status", `("owner", "status")`);
1009
+ }
1010
+ /**
1011
+ * Create the kpis table.
1012
+ *
1013
+ * Backed by memory/kpi/<goal_id>/<kpi_id>.md. KPI rows do NOT carry
1014
+ * owner — ownership derives from the parent goal via logical join on
1015
+ * goal_id. INSERT-only version-bumped. (goal_id, kpi_id) index is the
1016
+ * canonical lookup the VFS uses on Read and Write.
1017
+ */
1018
+ async ensureKpisTable(name) {
1019
+ const safe = sqlIdent(name);
1020
+ const tables = await this.listTables();
1021
+ if (!tables.includes(safe)) {
1022
+ log3(`table "${safe}" not found, creating`);
1023
+ await this.createTableWithRetry(buildCreateTableSql(safe, KPIS_COLUMNS), safe);
1024
+ log3(`table "${safe}" created`);
1025
+ if (!tables.includes(safe))
1026
+ this._tablesCache = [...tables, safe];
1027
+ }
1028
+ await this.healSchema(safe, KPIS_COLUMNS);
1029
+ await this.ensureLookupIndex(safe, "goal_id_kpi_id", `("goal_id", "kpi_id")`);
1030
+ }
803
1031
  };
804
1032
 
805
1033
  // dist/src/hooks/codex/spawn-wiki-worker.js
@@ -1097,9 +1325,54 @@ function spawnSkillifyWorker(opts) {
1097
1325
 
1098
1326
  // dist/src/skillify/state.js
1099
1327
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, writeSync, mkdirSync as mkdirSync7, renameSync as renameSync3, rmdirSync, existsSync as existsSync5, lstatSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2 } from "node:fs";
1328
+ import { join as join13 } from "node:path";
1329
+
1330
+ // dist/src/utils/repo-identity.js
1100
1331
  import { execSync as execSync2 } from "node:child_process";
1101
1332
  import { createHash } from "node:crypto";
1102
- import { join as join13, basename } from "node:path";
1333
+ import { basename, resolve as resolve2 } from "node:path";
1334
+ var DEFAULT_PORTS = {
1335
+ http: "80",
1336
+ https: "443",
1337
+ ssh: "22",
1338
+ git: "9418"
1339
+ };
1340
+ function normalizeGitRemoteUrl(url) {
1341
+ let s = url.trim();
1342
+ const schemeMatch = s.match(/^([a-z][a-z0-9+.-]*):\/\//i);
1343
+ const scheme = schemeMatch ? schemeMatch[1].toLowerCase() : null;
1344
+ if (schemeMatch)
1345
+ s = s.slice(schemeMatch[0].length);
1346
+ if (!scheme) {
1347
+ const scp = s.match(/^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/);
1348
+ if (scp)
1349
+ s = `${scp[1]}/${scp[2]}`;
1350
+ }
1351
+ s = s.replace(/^[^@/]+@/, "");
1352
+ if (scheme && DEFAULT_PORTS[scheme]) {
1353
+ s = s.replace(new RegExp(`^([^/]+):${DEFAULT_PORTS[scheme]}(/|$)`), "$1$2");
1354
+ }
1355
+ s = s.replace(/\.git\/?$/i, "");
1356
+ s = s.replace(/\/+$/, "");
1357
+ return s.toLowerCase();
1358
+ }
1359
+ function deriveProjectKey(cwd) {
1360
+ const absCwd = resolve2(cwd);
1361
+ const project = basename(absCwd) || "unknown";
1362
+ let signature = null;
1363
+ try {
1364
+ const raw = execSync2("git config --get remote.origin.url", {
1365
+ cwd: absCwd,
1366
+ encoding: "utf-8",
1367
+ stdio: ["ignore", "pipe", "ignore"]
1368
+ }).trim();
1369
+ signature = raw ? normalizeGitRemoteUrl(raw) : null;
1370
+ } catch {
1371
+ }
1372
+ const input = signature ?? absCwd;
1373
+ const key = createHash("sha1").update(input).digest("hex").slice(0, 16);
1374
+ return { key, project };
1375
+ }
1103
1376
 
1104
1377
  // dist/src/skillify/legacy-migration.js
1105
1378
  import { existsSync as existsSync4, renameSync as renameSync2 } from "node:fs";
@@ -1154,47 +1427,6 @@ function statePath(projectKey) {
1154
1427
  function lockPath2(projectKey) {
1155
1428
  return join13(getStateDir(), `${projectKey}.lock`);
1156
1429
  }
1157
- var DEFAULT_PORTS = {
1158
- http: "80",
1159
- https: "443",
1160
- ssh: "22",
1161
- git: "9418"
1162
- };
1163
- function normalizeGitRemoteUrl(url) {
1164
- let s = url.trim();
1165
- const schemeMatch = s.match(/^([a-z][a-z0-9+.-]*):\/\//i);
1166
- const scheme = schemeMatch ? schemeMatch[1].toLowerCase() : null;
1167
- if (schemeMatch)
1168
- s = s.slice(schemeMatch[0].length);
1169
- if (!scheme) {
1170
- const scp = s.match(/^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/);
1171
- if (scp)
1172
- s = `${scp[1]}/${scp[2]}`;
1173
- }
1174
- s = s.replace(/^[^@/]+@/, "");
1175
- if (scheme && DEFAULT_PORTS[scheme]) {
1176
- s = s.replace(new RegExp(`^([^/]+):${DEFAULT_PORTS[scheme]}(/|$)`), "$1$2");
1177
- }
1178
- s = s.replace(/\.git\/?$/i, "");
1179
- s = s.replace(/\/+$/, "");
1180
- return s.toLowerCase();
1181
- }
1182
- function deriveProjectKey(cwd) {
1183
- const project = basename(cwd) || "unknown";
1184
- let signature = null;
1185
- try {
1186
- const raw = execSync2("git config --get remote.origin.url", {
1187
- cwd,
1188
- encoding: "utf-8",
1189
- stdio: ["ignore", "pipe", "ignore"]
1190
- }).trim();
1191
- signature = raw ? normalizeGitRemoteUrl(raw) : null;
1192
- } catch {
1193
- }
1194
- const input = signature ?? cwd;
1195
- const key = createHash("sha1").update(input).digest("hex").slice(0, 16);
1196
- return { key, project };
1197
- }
1198
1430
  function readState(projectKey) {
1199
1431
  migrateLegacyStateDir();
1200
1432
  const p = statePath(projectKey);
@@ -1685,7 +1917,7 @@ var EmbedClient = class {
1685
1917
  }
1686
1918
  }
1687
1919
  connectOnce() {
1688
- return new Promise((resolve2, reject) => {
1920
+ return new Promise((resolve3, reject) => {
1689
1921
  const sock = connect(this.socketPath);
1690
1922
  const to = setTimeout(() => {
1691
1923
  sock.destroy();
@@ -1693,7 +1925,7 @@ var EmbedClient = class {
1693
1925
  }, this.timeoutMs);
1694
1926
  sock.once("connect", () => {
1695
1927
  clearTimeout(to);
1696
- resolve2(sock);
1928
+ resolve3(sock);
1697
1929
  });
1698
1930
  sock.once("error", (e) => {
1699
1931
  clearTimeout(to);
@@ -1775,7 +2007,7 @@ var EmbedClient = class {
1775
2007
  throw new Error("daemon did not become ready within spawnWaitMs");
1776
2008
  }
1777
2009
  sendAndWait(sock, req) {
1778
- return new Promise((resolve2, reject) => {
2010
+ return new Promise((resolve3, reject) => {
1779
2011
  let buf = "";
1780
2012
  const to = setTimeout(() => {
1781
2013
  sock.destroy();
@@ -1790,7 +2022,7 @@ var EmbedClient = class {
1790
2022
  const line = buf.slice(0, nl);
1791
2023
  clearTimeout(to);
1792
2024
  try {
1793
- resolve2(JSON.parse(line));
2025
+ resolve3(JSON.parse(line));
1794
2026
  } catch (e) {
1795
2027
  reject(e);
1796
2028
  }