bikky 0.4.2 → 0.4.4

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 (62) hide show
  1. package/README.md +64 -37
  2. package/dist/config.d.ts +15 -1
  3. package/dist/config.js +116 -20
  4. package/dist/daemon/capture-policy.d.ts +0 -1
  5. package/dist/daemon/capture-policy.js +0 -2
  6. package/dist/daemon/consolidation.d.ts +2 -1
  7. package/dist/daemon/consolidation.js +32 -15
  8. package/dist/daemon/entity-typing.js +10 -0
  9. package/dist/daemon/episode-summary.d.ts +4 -0
  10. package/dist/daemon/episode-summary.js +39 -8
  11. package/dist/daemon/extraction.d.ts +2 -2
  12. package/dist/daemon/extraction.js +65 -22
  13. package/dist/daemon/loop.js +8 -0
  14. package/dist/daemon/maintenance-state.d.ts +1 -1
  15. package/dist/daemon/maintenance-state.js +2 -0
  16. package/dist/daemon/qdrant.d.ts +32 -10
  17. package/dist/daemon/qdrant.js +199 -60
  18. package/dist/daemon/quality-rollups.d.ts +51 -0
  19. package/dist/daemon/quality-rollups.js +378 -0
  20. package/dist/daemon/relations.d.ts +3 -3
  21. package/dist/daemon/relations.js +28 -16
  22. package/dist/daemon/session-index.d.ts +5 -0
  23. package/dist/daemon/session-index.js +36 -9
  24. package/dist/daemon/session-summary.d.ts +3 -0
  25. package/dist/daemon/session-summary.js +48 -15
  26. package/dist/daemon/staleness.js +3 -3
  27. package/dist/daemon/transcript-sources.js +3 -2
  28. package/dist/daemon/watcher.js +2 -0
  29. package/dist/daemon/workstream-summary.d.ts +4 -0
  30. package/dist/daemon/workstream-summary.js +58 -16
  31. package/dist/install.d.ts +11 -0
  32. package/dist/install.js +38 -0
  33. package/dist/lifecycle.js +7 -5
  34. package/dist/llm/embedding/index.js +2 -1
  35. package/dist/llm/embedding/providers/openai.js +8 -2
  36. package/dist/llm/embedding/providers/portkey.js +9 -2
  37. package/dist/llm/inference/index.js +2 -1
  38. package/dist/llm/util.d.ts +12 -0
  39. package/dist/llm/util.js +18 -0
  40. package/dist/mcp/helpers.d.ts +8 -0
  41. package/dist/mcp/helpers.js +36 -3
  42. package/dist/mcp/taxonomy.d.ts +9 -13
  43. package/dist/mcp/taxonomy.js +59 -42
  44. package/dist/mcp/tools.js +351 -83
  45. package/dist/mcp/types.d.ts +35 -0
  46. package/dist/package-verifier.d.ts +19 -0
  47. package/dist/package-verifier.js +83 -0
  48. package/dist/prompts/brief.d.ts +2 -2
  49. package/dist/prompts/brief.js +0 -1
  50. package/dist/prompts/extraction.js +9 -11
  51. package/dist/provenance/origin.d.ts +57 -0
  52. package/dist/provenance/origin.js +254 -0
  53. package/dist/routing-context.d.ts +16 -0
  54. package/dist/routing-context.js +55 -0
  55. package/dist/status.d.ts +1 -0
  56. package/dist/status.js +7 -1
  57. package/docs/config/fully-hosted.md +33 -13
  58. package/docs/config/hosted-models.md +33 -13
  59. package/docs/config/hosted-qdrant-local-models.md +1 -0
  60. package/docs/config/local.md +1 -0
  61. package/docs/configuration.md +42 -17
  62. package/package.json +2 -2
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import crypto from "node:crypto";
7
7
  import { DEFAULT_DOMAIN, getDecayHalfLife, STALENESS_DAYS } from "./taxonomy.js";
8
+ import { isOperationOrigin } from "../provenance/origin.js";
8
9
  // ---------------------------------------------------------------------------
9
10
  // Hashing
10
11
  // ---------------------------------------------------------------------------
@@ -97,7 +98,7 @@ export function isStale(payload) {
97
98
  export const MEMORY_RECALL_EXCLUDED_KINDS = ["telemetry"];
98
99
  /** Build a Qdrant filter object from optional params. */
99
100
  export function buildFilter(params = {}) {
100
- const { category, domain, kind, memory_subtype, actor_id, entity, session_id, episode_id, workstream_key, task_key, repo, branch, review_status, since, until, excludeSuperseded = true, excludeKinds = [], metadata, } = params;
101
+ const { category, domain, kind, memory_subtype, origin_user_id, origin_agent_id, origin_interface, actor_id, entity, session_id, episode_id, workstream_key, task_key, repo, branch, review_status, since, until, excludeSuperseded = true, excludeKinds = [], metadata, } = params;
101
102
  const must = [];
102
103
  const must_not = [];
103
104
  if (excludeSuperseded) {
@@ -115,8 +116,23 @@ export function buildFilter(params = {}) {
115
116
  if (memory_subtype) {
116
117
  must.push({ key: "memory_subtype", match: { value: memory_subtype } });
117
118
  }
119
+ if (origin_user_id) {
120
+ must.push({ key: "origin.user.id", match: { value: origin_user_id } });
121
+ }
122
+ if (origin_agent_id) {
123
+ must.push({ key: "origin.agent.id", match: { value: origin_agent_id } });
124
+ }
125
+ if (origin_interface) {
126
+ must.push({ key: "origin.interface", match: { value: origin_interface } });
127
+ }
118
128
  if (actor_id) {
119
- must.push({ key: "actor_id", match: { value: actor_id } });
129
+ must.push({
130
+ should: [
131
+ { key: "origin.user.id", match: { value: actor_id } },
132
+ { key: "origin.agent.id", match: { value: actor_id } },
133
+ { key: "actor_id", match: { value: actor_id } },
134
+ ],
135
+ });
120
136
  }
121
137
  if (entity) {
122
138
  must.push({ key: "entities", match: { value: entity.toLowerCase() } });
@@ -173,8 +189,14 @@ export function formatFact(point) {
173
189
  parts.push(`kind: ${p.kind}`);
174
190
  if (p.memory_subtype)
175
191
  parts.push(`subtype: ${p.memory_subtype}`);
176
- if (p.actor_id)
192
+ if (isOperationOrigin(p.origin)) {
193
+ const user = p.origin.user?.name ?? p.origin.user?.id;
194
+ const agent = p.origin.agent.name ?? p.origin.agent.id ?? p.origin.agent.type;
195
+ parts.push(`origin: ${user ? `${user} via ` : ""}${agent} (${p.origin.interface}/${p.origin.operation.action})`);
196
+ }
197
+ else if (p.actor_id) {
177
198
  parts.push(`actor: ${p.actor_id}`);
199
+ }
178
200
  if (p.workstream_key)
179
201
  parts.push(`workstream: ${p.workstream_key}`);
180
202
  if (p.episode_id)
@@ -195,6 +217,12 @@ export function formatFact(point) {
195
217
  parts.push(`useful: ${p.useful_count}x`);
196
218
  if ((p.not_useful_count ?? 0) > 0)
197
219
  parts.push(`not useful: ${p.not_useful_count}x`);
220
+ if ((p.misleading_count ?? 0) > 0)
221
+ parts.push(`misleading: ${p.misleading_count}x`);
222
+ if ((p.wrong_count ?? 0) > 0)
223
+ parts.push(`wrong: ${p.wrong_count}x`);
224
+ if ((p.irrelevant_count ?? 0) > 0)
225
+ parts.push(`irrelevant: ${p.irrelevant_count}x`);
198
226
  if (p.redaction?.redacted)
199
227
  parts.push(`redacted: ${p.redaction.summary}`);
200
228
  if (p.metadata && Object.keys(p.metadata).length > 0) {
@@ -234,6 +262,8 @@ export function structuredFact(point) {
234
262
  ...(p.domain ? { domain: p.domain } : {}),
235
263
  ...(p.kind ? { kind: p.kind } : {}),
236
264
  ...(p.memory_subtype ? { memory_subtype: p.memory_subtype } : {}),
265
+ ...(isOperationOrigin(p.origin) ? { origin: p.origin } : {}),
266
+ ...(isOperationOrigin(p.last_operation_origin) ? { last_operation_origin: p.last_operation_origin } : {}),
237
267
  ...(p.actor_id ? { actor_id: p.actor_id } : {}),
238
268
  ...(p.source ? { source: p.source } : {}),
239
269
  entities: p.entities ?? [],
@@ -244,6 +274,9 @@ export function structuredFact(point) {
244
274
  ...(p.verification_count !== undefined ? { verification_count: p.verification_count } : {}),
245
275
  ...(p.useful_count !== undefined ? { useful_count: p.useful_count } : {}),
246
276
  ...(p.not_useful_count !== undefined ? { not_useful_count: p.not_useful_count } : {}),
277
+ ...(p.misleading_count !== undefined ? { misleading_count: p.misleading_count } : {}),
278
+ ...(p.wrong_count !== undefined ? { wrong_count: p.wrong_count } : {}),
279
+ ...(p.irrelevant_count !== undefined ? { irrelevant_count: p.irrelevant_count } : {}),
247
280
  ...(p.redaction ? { redaction: p.redaction } : {}),
248
281
  ...(p.metadata && Object.keys(p.metadata).length > 0 ? { metadata: p.metadata } : {}),
249
282
  ...(p.workstream_key ? { workstream_key: p.workstream_key } : {}),
@@ -13,10 +13,6 @@ export declare const CATEGORIES: {
13
13
  readonly description: "Product context: domain rules, product decisions, requirements, user workflows, roadmap, success metrics, and market or community insight.";
14
14
  readonly examples: readonly ["Bikky should show categories and concrete subtype chips directly, with no extra sub-tab layer.", "Activation should be measured by whether agents successfully reuse recalled memory."];
15
15
  };
16
- readonly human: {
17
- readonly description: "Human context: explicit preferences, people and roles, ownership, working agreements, and durable actor-action activity events.";
18
- readonly examples: readonly ["Saber prefers concise implementation plans before code changes.", "Alex approved PR #85 for merge."];
19
- };
20
16
  readonly system: {
21
17
  readonly description: "System context: Bikky-owned lifecycle memory, session indexes, episodes, workstreams, recall/feedback/outcome telemetry, and aggregate rollups.";
22
18
  readonly examples: readonly ["Session indexes are routing/audit artifacts rather than durable project boundaries.", "Recall telemetry is excluded from normal semantic recall."];
@@ -27,15 +23,15 @@ export declare const DEFAULT_CATEGORY: Category;
27
23
  export declare const DOMAINS: {
28
24
  readonly software_engineering: {
29
25
  readonly description: "Coding-agent work: repositories, code changes, architecture, infrastructure, debugging, tests, CI, and developer workflow.";
30
- readonly defaultCategories: readonly ["engineering", "product", "human", "system"];
26
+ readonly defaultCategories: readonly ["engineering", "product", "system"];
31
27
  };
32
28
  readonly product_strategy: {
33
29
  readonly description: "Product direction, positioning, roadmap tradeoffs, customer problems, metrics, and market learning.";
34
- readonly defaultCategories: readonly ["product", "human", "system"];
30
+ readonly defaultCategories: readonly ["product", "engineering", "system"];
35
31
  };
36
32
  readonly business_operations: {
37
33
  readonly description: "Business process, vendors, finance, legal/admin operations, recurring procedures, and ownership.";
38
- readonly defaultCategories: readonly ["product", "human", "system"];
34
+ readonly defaultCategories: readonly ["product", "engineering", "system"];
39
35
  };
40
36
  readonly research: {
41
37
  readonly description: "Research questions, sources, hypotheses, experiment findings, synthesis, and reusable insights.";
@@ -43,7 +39,7 @@ export declare const DOMAINS: {
43
39
  };
44
40
  readonly personal_productivity: {
45
41
  readonly description: "Individual productivity, habits, planning preferences, reminders, and personal operating context.";
46
- readonly defaultCategories: readonly ["human", "product", "system"];
42
+ readonly defaultCategories: readonly ["engineering", "product", "system"];
47
43
  };
48
44
  };
49
45
  export type Domain = keyof typeof DOMAINS;
@@ -121,11 +117,11 @@ export declare const MEMORY_SUBTYPE_DEFAULT_CATEGORY: {
121
117
  readonly success_metric: "product";
122
118
  readonly market_insight: "product";
123
119
  readonly troubleshooting_gotcha: "engineering";
124
- readonly preference: "human";
125
- readonly person_profile: "human";
126
- readonly ownership_note: "human";
127
- readonly working_agreement: "human";
128
- readonly activity_event: "human";
120
+ readonly preference: "engineering";
121
+ readonly person_profile: "engineering";
122
+ readonly ownership_note: "engineering";
123
+ readonly working_agreement: "engineering";
124
+ readonly activity_event: "engineering";
129
125
  readonly session_index: "system";
130
126
  readonly episode: "system";
131
127
  readonly workstream: "system";
@@ -22,13 +22,6 @@ export const CATEGORIES = {
22
22
  "Activation should be measured by whether agents successfully reuse recalled memory.",
23
23
  ],
24
24
  },
25
- human: {
26
- description: "Human context: explicit preferences, people and roles, ownership, working agreements, and durable actor-action activity events.",
27
- examples: [
28
- "Saber prefers concise implementation plans before code changes.",
29
- "Alex approved PR #85 for merge.",
30
- ],
31
- },
32
25
  system: {
33
26
  description: "System context: Bikky-owned lifecycle memory, session indexes, episodes, workstreams, recall/feedback/outcome telemetry, and aggregate rollups.",
34
27
  examples: [
@@ -47,7 +40,6 @@ export const DOMAINS = {
47
40
  defaultCategories: [
48
41
  "engineering",
49
42
  "product",
50
- "human",
51
43
  "system",
52
44
  ],
53
45
  },
@@ -55,7 +47,7 @@ export const DOMAINS = {
55
47
  description: "Product direction, positioning, roadmap tradeoffs, customer problems, metrics, and market learning.",
56
48
  defaultCategories: [
57
49
  "product",
58
- "human",
50
+ "engineering",
59
51
  "system",
60
52
  ],
61
53
  },
@@ -63,7 +55,7 @@ export const DOMAINS = {
63
55
  description: "Business process, vendors, finance, legal/admin operations, recurring procedures, and ownership.",
64
56
  defaultCategories: [
65
57
  "product",
66
- "human",
58
+ "engineering",
67
59
  "system",
68
60
  ],
69
61
  },
@@ -78,7 +70,7 @@ export const DOMAINS = {
78
70
  personal_productivity: {
79
71
  description: "Individual productivity, habits, planning preferences, reminders, and personal operating context.",
80
72
  defaultCategories: [
81
- "human",
73
+ "engineering",
82
74
  "product",
83
75
  "system",
84
76
  ],
@@ -195,11 +187,11 @@ export const MEMORY_SUBTYPE_DEFAULT_CATEGORY = {
195
187
  success_metric: "product",
196
188
  market_insight: "product",
197
189
  troubleshooting_gotcha: "engineering",
198
- preference: "human",
199
- person_profile: "human",
200
- ownership_note: "human",
201
- working_agreement: "human",
202
- activity_event: "human",
190
+ preference: "engineering",
191
+ person_profile: "engineering",
192
+ ownership_note: "engineering",
193
+ working_agreement: "engineering",
194
+ activity_event: "engineering",
203
195
  session_index: "system",
204
196
  episode: "system",
205
197
  workstream: "system",
@@ -267,19 +259,18 @@ export const DECAY_HALF_LIFE = {
267
259
  // Software-engineering defaults.
268
260
  "engineering.software_engineering": 120,
269
261
  "product.software_engineering": 120,
270
- "human.software_engineering": 180,
271
262
  "system.software_engineering": 45,
272
263
  // Other domain profiles.
264
+ "engineering.product_strategy": 180,
273
265
  "product.product_strategy": 180,
274
- "human.product_strategy": 180,
275
266
  "system.product_strategy": 60,
267
+ "engineering.business_operations": 180,
276
268
  "product.business_operations": 120,
277
- "human.business_operations": 180,
278
269
  "system.business_operations": 90,
279
270
  "product.research": 120,
280
271
  "engineering.research": 120,
281
272
  "system.research": 90,
282
- "human.personal_productivity": 180,
273
+ "engineering.personal_productivity": 180,
283
274
  "product.personal_productivity": 90,
284
275
  "system.personal_productivity": 45,
285
276
  };
@@ -291,11 +282,22 @@ export const QDRANT_INDEXES = [
291
282
  { field_name: "domain", field_schema: "keyword" },
292
283
  { field_name: "kind", field_schema: "keyword" },
293
284
  { field_name: "memory_subtype", field_schema: "keyword" },
294
- { field_name: "source", field_schema: "keyword" },
295
285
  { field_name: "content_hash", field_schema: "keyword" },
296
286
  { field_name: "entities", field_schema: "keyword" },
297
287
  { field_name: "workspace_id", field_schema: "keyword" },
288
+ // Deprecated legacy provenance fields remain indexed for fresh collections
289
+ // that still need to browse/filter records written before origin metadata.
290
+ { field_name: "source", field_schema: "keyword" },
298
291
  { field_name: "actor_id", field_schema: "keyword" },
292
+ { field_name: "origin.user.id", field_schema: "keyword" },
293
+ { field_name: "origin.user.source", field_schema: "keyword" },
294
+ { field_name: "origin.agent.id", field_schema: "keyword" },
295
+ { field_name: "origin.agent.type", field_schema: "keyword" },
296
+ { field_name: "origin.agent.source", field_schema: "keyword" },
297
+ { field_name: "origin.interface", field_schema: "keyword" },
298
+ { field_name: "origin.operation.action", field_schema: "keyword" },
299
+ { field_name: "last_operation_origin.agent.id", field_schema: "keyword" },
300
+ { field_name: "last_operation_origin.operation.action", field_schema: "keyword" },
299
301
  { field_name: "entity_name", field_schema: "keyword" },
300
302
  { field_name: "from_entity", field_schema: "keyword" },
301
303
  { field_name: "to_entity", field_schema: "keyword" },
@@ -318,6 +320,22 @@ export const QDRANT_INDEXES = [
318
320
  { field_name: "superseded", field_schema: "bool" },
319
321
  { field_name: "superseded_by", field_schema: "keyword" },
320
322
  { field_name: "is_bad_exemplar", field_schema: "bool" },
323
+ { field_name: "target_fact_id", field_schema: "keyword" },
324
+ { field_name: "feedback_kind", field_schema: "keyword" },
325
+ { field_name: "outcome", field_schema: "keyword" },
326
+ { field_name: "result_count", field_schema: "integer" },
327
+ { field_name: "scope_type", field_schema: "keyword" },
328
+ { field_name: "scope_value", field_schema: "keyword" },
329
+ { field_name: "rollup_type", field_schema: "keyword" },
330
+ { field_name: "rollup_generated_at", field_schema: "datetime" },
331
+ { field_name: "active_fact_count", field_schema: "integer" },
332
+ { field_name: "useful_count", field_schema: "integer" },
333
+ { field_name: "not_useful_count", field_schema: "integer" },
334
+ { field_name: "misleading_count", field_schema: "integer" },
335
+ { field_name: "wrong_count", field_schema: "integer" },
336
+ { field_name: "irrelevant_count", field_schema: "integer" },
337
+ { field_name: "stale_count", field_schema: "integer" },
338
+ { field_name: "low_confidence_count", field_schema: "integer" },
321
339
  { field_name: "useful_feedback_count", field_schema: "integer" },
322
340
  { field_name: "not_useful_feedback_count", field_schema: "integer" },
323
341
  { field_name: "recall_count", field_schema: "integer" },
@@ -347,16 +365,6 @@ export function normalizeCategory(category) {
347
365
  normalized.includes("customer") ||
348
366
  normalized === "projects")
349
367
  return "product";
350
- if (normalized.includes("human") ||
351
- normalized.includes("people") ||
352
- normalized.includes("person") ||
353
- normalized.includes("owner") ||
354
- normalized.includes("team") ||
355
- normalized.includes("preference") ||
356
- normalized.includes("agreement") ||
357
- normalized.includes("activity") ||
358
- normalized.includes("actor"))
359
- return "human";
360
368
  if (normalized.includes("system") ||
361
369
  normalized.includes("session") ||
362
370
  normalized.includes("episode") ||
@@ -374,7 +382,16 @@ export function normalizeCategory(category) {
374
382
  normalized.includes("code") ||
375
383
  normalized.includes("architecture") ||
376
384
  normalized.includes("troubleshoot") ||
377
- normalized.includes("observation"))
385
+ normalized.includes("observation") ||
386
+ normalized.includes("human") ||
387
+ normalized.includes("people") ||
388
+ normalized.includes("person") ||
389
+ normalized.includes("owner") ||
390
+ normalized.includes("team") ||
391
+ normalized.includes("preference") ||
392
+ normalized.includes("agreement") ||
393
+ normalized.includes("activity") ||
394
+ normalized.includes("actor"))
378
395
  return "engineering";
379
396
  return DEFAULT_CATEGORY;
380
397
  }
@@ -503,15 +520,6 @@ export function getDecayHalfLife(input) {
503
520
  rawCategory.includes("market") ||
504
521
  rawCategory.includes("customer") ||
505
522
  rawCategory === "projects" ||
506
- rawCategory.includes("human") ||
507
- rawCategory.includes("people") ||
508
- rawCategory.includes("person") ||
509
- rawCategory.includes("owner") ||
510
- rawCategory.includes("team") ||
511
- rawCategory.includes("preference") ||
512
- rawCategory.includes("agreement") ||
513
- rawCategory.includes("activity") ||
514
- rawCategory.includes("actor") ||
515
523
  rawCategory.includes("system") ||
516
524
  rawCategory.includes("session") ||
517
525
  rawCategory.includes("episode") ||
@@ -528,7 +536,16 @@ export function getDecayHalfLife(input) {
528
536
  rawCategory.includes("code") ||
529
537
  rawCategory.includes("architecture") ||
530
538
  rawCategory.includes("troubleshoot") ||
531
- rawCategory.includes("observation");
539
+ rawCategory.includes("observation") ||
540
+ rawCategory.includes("human") ||
541
+ rawCategory.includes("people") ||
542
+ rawCategory.includes("person") ||
543
+ rawCategory.includes("owner") ||
544
+ rawCategory.includes("team") ||
545
+ rawCategory.includes("preference") ||
546
+ rawCategory.includes("agreement") ||
547
+ rawCategory.includes("activity") ||
548
+ rawCategory.includes("actor");
532
549
  if (categoryWasProvided && !categoryIsKnown) {
533
550
  return DECAY_DEFAULT_HALF_LIFE;
534
551
  }