@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
@@ -104,6 +104,23 @@ function loadConfig() {
104
104
  tableName: process.env.HIVEMIND_TABLE ?? "memory",
105
105
  sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
106
106
  skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
107
+ // Defaults match the table name written into the SQL — keep aligned
108
+ // with RULES_COLUMNS / TASKS_COLUMNS / TASK_EVENTS_COLUMNS in
109
+ // deeplake-schema.ts and with the e2e test-org override convention
110
+ // (memory_test / sessions_test → goals_test, etc.) documented in
111
+ // CLAUDE.md.
112
+ rulesTableName: process.env.HIVEMIND_RULES_TABLE ?? "hivemind_rules",
113
+ tasksTableName: process.env.HIVEMIND_TASKS_TABLE ?? "hivemind_tasks",
114
+ taskEventsTableName: process.env.HIVEMIND_TASK_EVENTS_TABLE ?? "hivemind_task_events",
115
+ // Goals + KPIs (refined design — VFS path classifier maps
116
+ // memory/goal/<user>/<status>/<uuid>.md → hivemind_goals row
117
+ // memory/kpi/<uuid>/<kpi_id>.md → hivemind_kpis row
118
+ // See src/shell/deeplake-fs.ts for the translation logic and
119
+ // GOALS_COLUMNS / KPIS_COLUMNS in deeplake-schema.ts for the
120
+ // table shape.
121
+ goalsTableName: process.env.HIVEMIND_GOALS_TABLE ?? "hivemind_goals",
122
+ kpisTableName: process.env.HIVEMIND_KPIS_TABLE ?? "hivemind_kpis",
123
+ codebaseTableName: process.env.HIVEMIND_CODEBASE_TABLE ?? "codebase",
107
124
  memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join(home, ".deeplake", "memory")
108
125
  };
109
126
  }
@@ -204,6 +221,65 @@ var SKILLS_COLUMNS = Object.freeze([
204
221
  { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
205
222
  { name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
206
223
  ]);
224
+ var RULES_COLUMNS = Object.freeze([
225
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
226
+ { name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
227
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
228
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
229
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
230
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
231
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
232
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
233
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
234
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
235
+ ]);
236
+ var TASKS_COLUMNS = Object.freeze([
237
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
238
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
239
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
240
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
241
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
242
+ { name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
243
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
244
+ { name: "kpis", sql: "JSONB" },
245
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
246
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
247
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
248
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
249
+ ]);
250
+ var TASK_EVENTS_COLUMNS = Object.freeze([
251
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
252
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
253
+ { name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
254
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
255
+ { name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
256
+ { name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
257
+ { name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
258
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
259
+ { name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
260
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
261
+ ]);
262
+ var GOALS_COLUMNS = Object.freeze([
263
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
264
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
265
+ { name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
266
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
267
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
268
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
269
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
270
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
271
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
272
+ ]);
273
+ var KPIS_COLUMNS = Object.freeze([
274
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
275
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
276
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
277
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
278
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
279
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
280
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
281
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
282
+ ]);
207
283
  function validateSchema(label, cols) {
208
284
  const seen = /* @__PURE__ */ new Set();
209
285
  for (const col of cols) {
@@ -221,9 +297,38 @@ function validateSchema(label, cols) {
221
297
  }
222
298
  }
223
299
  }
300
+ var CODEBASE_COLUMNS = Object.freeze([
301
+ // Identity key (matches the PK below)
302
+ { name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
303
+ { name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
304
+ { name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
305
+ { name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
306
+ { name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
307
+ { name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
308
+ // Observation metadata
309
+ { name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
310
+ { name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
311
+ { name: "ts", sql: "TIMESTAMP" },
312
+ { name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
313
+ // Snapshot payload
314
+ { name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
315
+ { name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
316
+ { name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
317
+ { name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
318
+ // Generator metadata (for drift diagnostics — what hivemind version produced this?)
319
+ { name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
320
+ { name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
321
+ { name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
322
+ ]);
224
323
  validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
225
324
  validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
226
325
  validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
326
+ validateSchema("RULES_COLUMNS", RULES_COLUMNS);
327
+ validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
328
+ validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
329
+ validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
330
+ validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
331
+ validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
227
332
  function buildCreateTableSql(tableName, cols) {
228
333
  const safe = sqlIdent(tableName);
229
334
  const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
@@ -788,6 +893,24 @@ var DeeplakeApi = class {
788
893
  * This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
789
894
  * worker.
790
895
  */
896
+ /**
897
+ * Create the codebase table. One row per (org, workspace, repo, user,
898
+ * worktree, commit) — see CODEBASE_COLUMNS for the schema. Healing
899
+ * + index follow the same pattern as ensureSessionsTable.
900
+ */
901
+ async ensureCodebaseTable(name) {
902
+ const safe = sqlIdent(name);
903
+ const tables = await this.listTables();
904
+ if (!tables.includes(safe)) {
905
+ log3(`table "${safe}" not found, creating`);
906
+ await this.createTableWithRetry(buildCreateTableSql(safe, CODEBASE_COLUMNS), safe);
907
+ log3(`table "${safe}" created`);
908
+ if (!tables.includes(safe))
909
+ this._tablesCache = [...tables, safe];
910
+ }
911
+ await this.healSchema(safe, CODEBASE_COLUMNS);
912
+ await this.ensureLookupIndex(safe, "codebase_identity", `("org_id", "workspace_id", "repo_slug", "user_id", "worktree_id", "commit_sha")`);
913
+ }
791
914
  async ensureSkillsTable(name) {
792
915
  const safe = sqlIdent(name);
793
916
  const tables = await this.listTables();
@@ -801,6 +924,111 @@ var DeeplakeApi = class {
801
924
  await this.healSchema(safe, SKILLS_COLUMNS);
802
925
  await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
803
926
  }
927
+ /**
928
+ * Create the rules table.
929
+ *
930
+ * One row per rule version (same write pattern as skills): edits INSERT
931
+ * a fresh row with version+1, reads pick latest per rule_id via
932
+ * `ORDER BY version DESC LIMIT 1`. Sidesteps the Deeplake
933
+ * UPDATE-coalescing quirk by never UPDATEing.
934
+ */
935
+ async ensureRulesTable(name) {
936
+ const safe = sqlIdent(name);
937
+ const tables = await this.listTables();
938
+ if (!tables.includes(safe)) {
939
+ log3(`table "${safe}" not found, creating`);
940
+ await this.createTableWithRetry(buildCreateTableSql(safe, RULES_COLUMNS), safe);
941
+ log3(`table "${safe}" created`);
942
+ if (!tables.includes(safe))
943
+ this._tablesCache = [...tables, safe];
944
+ }
945
+ await this.healSchema(safe, RULES_COLUMNS);
946
+ await this.ensureLookupIndex(safe, "rule_id_version", `("rule_id", "version")`);
947
+ }
948
+ /**
949
+ * Create the tasks table.
950
+ *
951
+ * Same write pattern as rules + skills. `kpis` is a nullable JSONB
952
+ * column with the agent's KPI metadata; KPI current values come from
953
+ * `task_events` (SUM(value)), not this snapshot.
954
+ */
955
+ async ensureTasksTable(name) {
956
+ const safe = sqlIdent(name);
957
+ const tables = await this.listTables();
958
+ if (!tables.includes(safe)) {
959
+ log3(`table "${safe}" not found, creating`);
960
+ await this.createTableWithRetry(buildCreateTableSql(safe, TASKS_COLUMNS), safe);
961
+ log3(`table "${safe}" created`);
962
+ if (!tables.includes(safe))
963
+ this._tablesCache = [...tables, safe];
964
+ }
965
+ await this.healSchema(safe, TASKS_COLUMNS);
966
+ await this.ensureLookupIndex(safe, "task_id_version", `("task_id", "version")`);
967
+ }
968
+ /**
969
+ * Create the task-events table.
970
+ *
971
+ * Append-only. Every INSERT is a fresh row; never UPDATE. KPI current
972
+ * value is `SUM(value) WHERE task_id=? AND kpi_id=?`. Index on
973
+ * (task_id, kpi_id) is the canonical aggregation key.
974
+ */
975
+ async ensureTaskEventsTable(name) {
976
+ const safe = sqlIdent(name);
977
+ const tables = await this.listTables();
978
+ if (!tables.includes(safe)) {
979
+ log3(`table "${safe}" not found, creating`);
980
+ await this.createTableWithRetry(buildCreateTableSql(safe, TASK_EVENTS_COLUMNS), safe);
981
+ log3(`table "${safe}" created`);
982
+ if (!tables.includes(safe))
983
+ this._tablesCache = [...tables, safe];
984
+ }
985
+ await this.healSchema(safe, TASK_EVENTS_COLUMNS);
986
+ await this.ensureLookupIndex(safe, "task_id_kpi_id", `("task_id", "kpi_id")`);
987
+ }
988
+ /**
989
+ * Create the goals table.
990
+ *
991
+ * Backed by the VFS path convention memory/goal/<owner>/<status>/<goal_id>.md.
992
+ * INSERT-only version-bumped: rm and mv operations translate to fresh
993
+ * v=N+1 rows (status flips for mv → closed; rm is the same soft-close).
994
+ * The (goal_id, version) index lets the VFS dispatch a cheap latest-row
995
+ * read on cat / Read of a single goal.
996
+ */
997
+ async ensureGoalsTable(name) {
998
+ const safe = sqlIdent(name);
999
+ const tables = await this.listTables();
1000
+ if (!tables.includes(safe)) {
1001
+ log3(`table "${safe}" not found, creating`);
1002
+ await this.createTableWithRetry(buildCreateTableSql(safe, GOALS_COLUMNS), safe);
1003
+ log3(`table "${safe}" created`);
1004
+ if (!tables.includes(safe))
1005
+ this._tablesCache = [...tables, safe];
1006
+ }
1007
+ await this.healSchema(safe, GOALS_COLUMNS);
1008
+ await this.ensureLookupIndex(safe, "goal_id_version", `("goal_id", "version")`);
1009
+ await this.ensureLookupIndex(safe, "owner_status", `("owner", "status")`);
1010
+ }
1011
+ /**
1012
+ * Create the kpis table.
1013
+ *
1014
+ * Backed by memory/kpi/<goal_id>/<kpi_id>.md. KPI rows do NOT carry
1015
+ * owner — ownership derives from the parent goal via logical join on
1016
+ * goal_id. INSERT-only version-bumped. (goal_id, kpi_id) index is the
1017
+ * canonical lookup the VFS uses on Read and Write.
1018
+ */
1019
+ async ensureKpisTable(name) {
1020
+ const safe = sqlIdent(name);
1021
+ const tables = await this.listTables();
1022
+ if (!tables.includes(safe)) {
1023
+ log3(`table "${safe}" not found, creating`);
1024
+ await this.createTableWithRetry(buildCreateTableSql(safe, KPIS_COLUMNS), safe);
1025
+ log3(`table "${safe}" created`);
1026
+ if (!tables.includes(safe))
1027
+ this._tablesCache = [...tables, safe];
1028
+ }
1029
+ await this.healSchema(safe, KPIS_COLUMNS);
1030
+ await this.ensureLookupIndex(safe, "goal_id_kpi_id", `("goal_id", "kpi_id")`);
1031
+ }
804
1032
  };
805
1033
 
806
1034
  // dist/src/shell/grep-core.js
@@ -126,6 +126,23 @@ function loadConfig() {
126
126
  tableName: process.env.HIVEMIND_TABLE ?? "memory",
127
127
  sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
128
128
  skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
129
+ // Defaults match the table name written into the SQL — keep aligned
130
+ // with RULES_COLUMNS / TASKS_COLUMNS / TASK_EVENTS_COLUMNS in
131
+ // deeplake-schema.ts and with the e2e test-org override convention
132
+ // (memory_test / sessions_test → goals_test, etc.) documented in
133
+ // CLAUDE.md.
134
+ rulesTableName: process.env.HIVEMIND_RULES_TABLE ?? "hivemind_rules",
135
+ tasksTableName: process.env.HIVEMIND_TASKS_TABLE ?? "hivemind_tasks",
136
+ taskEventsTableName: process.env.HIVEMIND_TASK_EVENTS_TABLE ?? "hivemind_task_events",
137
+ // Goals + KPIs (refined design — VFS path classifier maps
138
+ // memory/goal/<user>/<status>/<uuid>.md → hivemind_goals row
139
+ // memory/kpi/<uuid>/<kpi_id>.md → hivemind_kpis row
140
+ // See src/shell/deeplake-fs.ts for the translation logic and
141
+ // GOALS_COLUMNS / KPIS_COLUMNS in deeplake-schema.ts for the
142
+ // table shape.
143
+ goalsTableName: process.env.HIVEMIND_GOALS_TABLE ?? "hivemind_goals",
144
+ kpisTableName: process.env.HIVEMIND_KPIS_TABLE ?? "hivemind_kpis",
145
+ codebaseTableName: process.env.HIVEMIND_CODEBASE_TABLE ?? "codebase",
129
146
  memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join3(home, ".deeplake", "memory")
130
147
  };
131
148
  }
@@ -217,6 +234,65 @@ var SKILLS_COLUMNS = Object.freeze([
217
234
  { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
218
235
  { name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
219
236
  ]);
237
+ var RULES_COLUMNS = Object.freeze([
238
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
239
+ { name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
240
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
241
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
242
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
243
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
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 TASKS_COLUMNS = Object.freeze([
250
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
251
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
252
+ { name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
253
+ { name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
254
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
255
+ { name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
256
+ { name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
257
+ { name: "kpis", sql: "JSONB" },
258
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
259
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
260
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
261
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
262
+ ]);
263
+ var TASK_EVENTS_COLUMNS = Object.freeze([
264
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
265
+ { name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
266
+ { name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
267
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
268
+ { name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
269
+ { name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
270
+ { name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
271
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
272
+ { name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
273
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
274
+ ]);
275
+ var GOALS_COLUMNS = Object.freeze([
276
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
277
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
278
+ { name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
279
+ { name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
280
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
281
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
282
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
283
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
284
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
285
+ ]);
286
+ var KPIS_COLUMNS = Object.freeze([
287
+ { name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
288
+ { name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
289
+ { name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
290
+ { name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
291
+ { name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
292
+ { name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
293
+ { name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
294
+ { name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
295
+ ]);
220
296
  function validateSchema(label, cols) {
221
297
  const seen = /* @__PURE__ */ new Set();
222
298
  for (const col of cols) {
@@ -234,9 +310,38 @@ function validateSchema(label, cols) {
234
310
  }
235
311
  }
236
312
  }
313
+ var CODEBASE_COLUMNS = Object.freeze([
314
+ // Identity key (matches the PK below)
315
+ { name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
316
+ { name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
317
+ { name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
318
+ { name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
319
+ { name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
320
+ { name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
321
+ // Observation metadata
322
+ { name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
323
+ { name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
324
+ { name: "ts", sql: "TIMESTAMP" },
325
+ { name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
326
+ // Snapshot payload
327
+ { name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
328
+ { name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
329
+ { name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
330
+ { name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
331
+ // Generator metadata (for drift diagnostics — what hivemind version produced this?)
332
+ { name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
333
+ { name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
334
+ { name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
335
+ ]);
237
336
  validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
238
337
  validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
239
338
  validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
339
+ validateSchema("RULES_COLUMNS", RULES_COLUMNS);
340
+ validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
341
+ validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
342
+ validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
343
+ validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
344
+ validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
240
345
  function buildCreateTableSql(tableName, cols) {
241
346
  const safe = sqlIdent(tableName);
242
347
  const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
@@ -783,6 +888,24 @@ var DeeplakeApi = class {
783
888
  * This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
784
889
  * worker.
785
890
  */
891
+ /**
892
+ * Create the codebase table. One row per (org, workspace, repo, user,
893
+ * worktree, commit) — see CODEBASE_COLUMNS for the schema. Healing
894
+ * + index follow the same pattern as ensureSessionsTable.
895
+ */
896
+ async ensureCodebaseTable(name) {
897
+ const safe = sqlIdent(name);
898
+ const tables = await this.listTables();
899
+ if (!tables.includes(safe)) {
900
+ log3(`table "${safe}" not found, creating`);
901
+ await this.createTableWithRetry(buildCreateTableSql(safe, CODEBASE_COLUMNS), safe);
902
+ log3(`table "${safe}" created`);
903
+ if (!tables.includes(safe))
904
+ this._tablesCache = [...tables, safe];
905
+ }
906
+ await this.healSchema(safe, CODEBASE_COLUMNS);
907
+ await this.ensureLookupIndex(safe, "codebase_identity", `("org_id", "workspace_id", "repo_slug", "user_id", "worktree_id", "commit_sha")`);
908
+ }
786
909
  async ensureSkillsTable(name) {
787
910
  const safe = sqlIdent(name);
788
911
  const tables = await this.listTables();
@@ -796,6 +919,111 @@ var DeeplakeApi = class {
796
919
  await this.healSchema(safe, SKILLS_COLUMNS);
797
920
  await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
798
921
  }
922
+ /**
923
+ * Create the rules table.
924
+ *
925
+ * One row per rule version (same write pattern as skills): edits INSERT
926
+ * a fresh row with version+1, reads pick latest per rule_id via
927
+ * `ORDER BY version DESC LIMIT 1`. Sidesteps the Deeplake
928
+ * UPDATE-coalescing quirk by never UPDATEing.
929
+ */
930
+ async ensureRulesTable(name) {
931
+ const safe = sqlIdent(name);
932
+ const tables = await this.listTables();
933
+ if (!tables.includes(safe)) {
934
+ log3(`table "${safe}" not found, creating`);
935
+ await this.createTableWithRetry(buildCreateTableSql(safe, RULES_COLUMNS), safe);
936
+ log3(`table "${safe}" created`);
937
+ if (!tables.includes(safe))
938
+ this._tablesCache = [...tables, safe];
939
+ }
940
+ await this.healSchema(safe, RULES_COLUMNS);
941
+ await this.ensureLookupIndex(safe, "rule_id_version", `("rule_id", "version")`);
942
+ }
943
+ /**
944
+ * Create the tasks table.
945
+ *
946
+ * Same write pattern as rules + skills. `kpis` is a nullable JSONB
947
+ * column with the agent's KPI metadata; KPI current values come from
948
+ * `task_events` (SUM(value)), not this snapshot.
949
+ */
950
+ async ensureTasksTable(name) {
951
+ const safe = sqlIdent(name);
952
+ const tables = await this.listTables();
953
+ if (!tables.includes(safe)) {
954
+ log3(`table "${safe}" not found, creating`);
955
+ await this.createTableWithRetry(buildCreateTableSql(safe, TASKS_COLUMNS), safe);
956
+ log3(`table "${safe}" created`);
957
+ if (!tables.includes(safe))
958
+ this._tablesCache = [...tables, safe];
959
+ }
960
+ await this.healSchema(safe, TASKS_COLUMNS);
961
+ await this.ensureLookupIndex(safe, "task_id_version", `("task_id", "version")`);
962
+ }
963
+ /**
964
+ * Create the task-events table.
965
+ *
966
+ * Append-only. Every INSERT is a fresh row; never UPDATE. KPI current
967
+ * value is `SUM(value) WHERE task_id=? AND kpi_id=?`. Index on
968
+ * (task_id, kpi_id) is the canonical aggregation key.
969
+ */
970
+ async ensureTaskEventsTable(name) {
971
+ const safe = sqlIdent(name);
972
+ const tables = await this.listTables();
973
+ if (!tables.includes(safe)) {
974
+ log3(`table "${safe}" not found, creating`);
975
+ await this.createTableWithRetry(buildCreateTableSql(safe, TASK_EVENTS_COLUMNS), safe);
976
+ log3(`table "${safe}" created`);
977
+ if (!tables.includes(safe))
978
+ this._tablesCache = [...tables, safe];
979
+ }
980
+ await this.healSchema(safe, TASK_EVENTS_COLUMNS);
981
+ await this.ensureLookupIndex(safe, "task_id_kpi_id", `("task_id", "kpi_id")`);
982
+ }
983
+ /**
984
+ * Create the goals table.
985
+ *
986
+ * Backed by the VFS path convention memory/goal/<owner>/<status>/<goal_id>.md.
987
+ * INSERT-only version-bumped: rm and mv operations translate to fresh
988
+ * v=N+1 rows (status flips for mv → closed; rm is the same soft-close).
989
+ * The (goal_id, version) index lets the VFS dispatch a cheap latest-row
990
+ * read on cat / Read of a single goal.
991
+ */
992
+ async ensureGoalsTable(name) {
993
+ const safe = sqlIdent(name);
994
+ const tables = await this.listTables();
995
+ if (!tables.includes(safe)) {
996
+ log3(`table "${safe}" not found, creating`);
997
+ await this.createTableWithRetry(buildCreateTableSql(safe, GOALS_COLUMNS), safe);
998
+ log3(`table "${safe}" created`);
999
+ if (!tables.includes(safe))
1000
+ this._tablesCache = [...tables, safe];
1001
+ }
1002
+ await this.healSchema(safe, GOALS_COLUMNS);
1003
+ await this.ensureLookupIndex(safe, "goal_id_version", `("goal_id", "version")`);
1004
+ await this.ensureLookupIndex(safe, "owner_status", `("owner", "status")`);
1005
+ }
1006
+ /**
1007
+ * Create the kpis table.
1008
+ *
1009
+ * Backed by memory/kpi/<goal_id>/<kpi_id>.md. KPI rows do NOT carry
1010
+ * owner — ownership derives from the parent goal via logical join on
1011
+ * goal_id. INSERT-only version-bumped. (goal_id, kpi_id) index is the
1012
+ * canonical lookup the VFS uses on Read and Write.
1013
+ */
1014
+ async ensureKpisTable(name) {
1015
+ const safe = sqlIdent(name);
1016
+ const tables = await this.listTables();
1017
+ if (!tables.includes(safe)) {
1018
+ log3(`table "${safe}" not found, creating`);
1019
+ await this.createTableWithRetry(buildCreateTableSql(safe, KPIS_COLUMNS), safe);
1020
+ log3(`table "${safe}" created`);
1021
+ if (!tables.includes(safe))
1022
+ this._tablesCache = [...tables, safe];
1023
+ }
1024
+ await this.healSchema(safe, KPIS_COLUMNS);
1025
+ await this.ensureLookupIndex(safe, "goal_id_kpi_id", `("goal_id", "kpi_id")`);
1026
+ }
799
1027
  };
800
1028
 
801
1029
  // dist/src/utils/stdin.js