bikky 0.3.2 → 0.3.5

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 (145) hide show
  1. package/README.md +83 -34
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +6 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/config.test.d.ts +3 -2
  7. package/dist/config.test.d.ts.map +1 -1
  8. package/dist/config.test.js +12 -6
  9. package/dist/config.test.js.map +1 -1
  10. package/dist/daemon/capture-policy.d.ts +4 -4
  11. package/dist/daemon/capture-policy.d.ts.map +1 -1
  12. package/dist/daemon/capture-policy.js +8 -17
  13. package/dist/daemon/capture-policy.js.map +1 -1
  14. package/dist/daemon/capture-policy.test.js +2 -2
  15. package/dist/daemon/capture-policy.test.js.map +1 -1
  16. package/dist/daemon/entity-typing.d.ts +20 -0
  17. package/dist/daemon/entity-typing.d.ts.map +1 -0
  18. package/dist/daemon/entity-typing.js +166 -0
  19. package/dist/daemon/entity-typing.js.map +1 -0
  20. package/dist/daemon/episode-summary.d.ts +4 -6
  21. package/dist/daemon/episode-summary.d.ts.map +1 -1
  22. package/dist/daemon/episode-summary.js +24 -38
  23. package/dist/daemon/episode-summary.js.map +1 -1
  24. package/dist/daemon/episode-summary.test.js +5 -5
  25. package/dist/daemon/episode-summary.test.js.map +1 -1
  26. package/dist/daemon/extraction-quality.test.d.ts +2 -0
  27. package/dist/daemon/extraction-quality.test.d.ts.map +1 -0
  28. package/dist/daemon/extraction-quality.test.js +283 -0
  29. package/dist/daemon/extraction-quality.test.js.map +1 -0
  30. package/dist/daemon/extraction-rules.d.ts +131 -0
  31. package/dist/daemon/extraction-rules.d.ts.map +1 -0
  32. package/dist/daemon/extraction-rules.js +321 -0
  33. package/dist/daemon/extraction-rules.js.map +1 -0
  34. package/dist/daemon/extraction-rules.test.d.ts +2 -0
  35. package/dist/daemon/extraction-rules.test.d.ts.map +1 -0
  36. package/dist/daemon/extraction-rules.test.js +183 -0
  37. package/dist/daemon/extraction-rules.test.js.map +1 -0
  38. package/dist/daemon/extraction.d.ts +19 -1
  39. package/dist/daemon/extraction.d.ts.map +1 -1
  40. package/dist/daemon/extraction.js +169 -21
  41. package/dist/daemon/extraction.js.map +1 -1
  42. package/dist/daemon/extraction.test.js +96 -2
  43. package/dist/daemon/extraction.test.js.map +1 -1
  44. package/dist/daemon/loop.d.ts.map +1 -1
  45. package/dist/daemon/loop.js +14 -0
  46. package/dist/daemon/loop.js.map +1 -1
  47. package/dist/daemon/qdrant.d.ts +15 -1
  48. package/dist/daemon/qdrant.d.ts.map +1 -1
  49. package/dist/daemon/qdrant.js +45 -2
  50. package/dist/daemon/qdrant.js.map +1 -1
  51. package/dist/daemon/relations-vocab.d.ts +44 -0
  52. package/dist/daemon/relations-vocab.d.ts.map +1 -0
  53. package/dist/daemon/relations-vocab.js +168 -0
  54. package/dist/daemon/relations-vocab.js.map +1 -0
  55. package/dist/daemon/relations-vocab.test.d.ts +2 -0
  56. package/dist/daemon/relations-vocab.test.d.ts.map +1 -0
  57. package/dist/daemon/relations-vocab.test.js +69 -0
  58. package/dist/daemon/relations-vocab.test.js.map +1 -0
  59. package/dist/daemon/relations.d.ts +2 -0
  60. package/dist/daemon/relations.d.ts.map +1 -1
  61. package/dist/daemon/relations.js +15 -5
  62. package/dist/daemon/relations.js.map +1 -1
  63. package/dist/daemon/session-index.test.js +1 -1
  64. package/dist/daemon/session-index.test.js.map +1 -1
  65. package/dist/daemon/watcher-health.d.ts +20 -0
  66. package/dist/daemon/watcher-health.d.ts.map +1 -0
  67. package/dist/daemon/watcher-health.js +78 -0
  68. package/dist/daemon/watcher-health.js.map +1 -0
  69. package/dist/daemon/watcher-health.test.d.ts +5 -0
  70. package/dist/daemon/watcher-health.test.d.ts.map +1 -0
  71. package/dist/daemon/watcher-health.test.js +96 -0
  72. package/dist/daemon/watcher-health.test.js.map +1 -0
  73. package/dist/daemon/watcher.test.d.ts +3 -2
  74. package/dist/daemon/watcher.test.d.ts.map +1 -1
  75. package/dist/daemon/watcher.test.js +9 -19
  76. package/dist/daemon/watcher.test.js.map +1 -1
  77. package/dist/daemon/workstream-resolver.d.ts +76 -0
  78. package/dist/daemon/workstream-resolver.d.ts.map +1 -0
  79. package/dist/daemon/workstream-resolver.js +180 -0
  80. package/dist/daemon/workstream-resolver.js.map +1 -0
  81. package/dist/daemon/workstream-resolver.test.d.ts +2 -0
  82. package/dist/daemon/workstream-resolver.test.d.ts.map +1 -0
  83. package/dist/daemon/workstream-resolver.test.js +128 -0
  84. package/dist/daemon/workstream-resolver.test.js.map +1 -0
  85. package/dist/daemon/workstream-summary.d.ts +1 -8
  86. package/dist/daemon/workstream-summary.d.ts.map +1 -1
  87. package/dist/daemon/workstream-summary.js +4 -37
  88. package/dist/daemon/workstream-summary.js.map +1 -1
  89. package/dist/daemon/workstream-summary.test.js +4 -4
  90. package/dist/daemon/workstream-summary.test.js.map +1 -1
  91. package/dist/mcp/helpers.d.ts.map +1 -1
  92. package/dist/mcp/helpers.js +17 -2
  93. package/dist/mcp/helpers.js.map +1 -1
  94. package/dist/mcp/index.d.ts.map +1 -1
  95. package/dist/mcp/index.js +8 -1
  96. package/dist/mcp/index.js.map +1 -1
  97. package/dist/mcp/taxonomy.d.ts +20 -18
  98. package/dist/mcp/taxonomy.d.ts.map +1 -1
  99. package/dist/mcp/taxonomy.js +75 -25
  100. package/dist/mcp/taxonomy.js.map +1 -1
  101. package/dist/mcp/taxonomy.test.js +10 -5
  102. package/dist/mcp/taxonomy.test.js.map +1 -1
  103. package/dist/mcp/tools.d.ts.map +1 -1
  104. package/dist/mcp/tools.js +457 -93
  105. package/dist/mcp/tools.js.map +1 -1
  106. package/dist/mcp/tools.test.js +209 -0
  107. package/dist/mcp/tools.test.js.map +1 -1
  108. package/dist/prompts/distill.d.ts.map +1 -1
  109. package/dist/prompts/distill.js +36 -17
  110. package/dist/prompts/distill.js.map +1 -1
  111. package/dist/prompts/entity-typing.d.ts +18 -0
  112. package/dist/prompts/entity-typing.d.ts.map +1 -0
  113. package/dist/prompts/entity-typing.js +60 -0
  114. package/dist/prompts/entity-typing.js.map +1 -0
  115. package/dist/prompts/episode-summary.d.ts +15 -0
  116. package/dist/prompts/episode-summary.d.ts.map +1 -0
  117. package/dist/prompts/episode-summary.js +74 -0
  118. package/dist/prompts/episode-summary.js.map +1 -0
  119. package/dist/prompts/extraction.d.ts.map +1 -1
  120. package/dist/prompts/extraction.js +138 -6
  121. package/dist/prompts/extraction.js.map +1 -1
  122. package/dist/prompts/index.d.ts +3 -0
  123. package/dist/prompts/index.d.ts.map +1 -1
  124. package/dist/prompts/index.js +3 -0
  125. package/dist/prompts/index.js.map +1 -1
  126. package/dist/prompts/prompts.test.js +1 -1
  127. package/dist/prompts/prompts.test.js.map +1 -1
  128. package/dist/prompts/relations.d.ts.map +1 -1
  129. package/dist/prompts/relations.js +26 -4
  130. package/dist/prompts/relations.js.map +1 -1
  131. package/dist/prompts/workstream-summary.d.ts +17 -0
  132. package/dist/prompts/workstream-summary.d.ts.map +1 -0
  133. package/dist/prompts/workstream-summary.js +72 -0
  134. package/dist/prompts/workstream-summary.js.map +1 -0
  135. package/dist/render.d.ts.map +1 -1
  136. package/dist/render.js +19 -1
  137. package/dist/render.js.map +1 -1
  138. package/dist/render.test.js +37 -5
  139. package/dist/render.test.js.map +1 -1
  140. package/docs/diagrams/architecture.svg +87 -0
  141. package/docs/diagrams/team-memory.svg +250 -0
  142. package/docs/screenshots/dashboard.png +0 -0
  143. package/docs/screenshots/graph.png +0 -0
  144. package/docs/screenshots/memory.png +0 -0
  145. package/package.json +4 -2
@@ -1 +1 @@
1
- {"version":3,"file":"session-index.test.js","sourceRoot":"","sources":["../../src/daemon/session-index.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-index.test.js","sourceRoot":"","sources":["../../src/daemon/session-index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Watcher path sanity check — flags configurations that will silently
3
+ * produce no extraction work (vanished tempdirs, missing dirs, paths that
4
+ * look like leftover test fixtures).
5
+ *
6
+ * The fix lives outside the watcher itself so daemon startup can warn
7
+ * even before the first extraction tick runs.
8
+ */
9
+ import type { BikkyConfig } from "../config.js";
10
+ export interface WatcherPathIssue {
11
+ watcher: string;
12
+ configuredPath: string;
13
+ reasons: string[];
14
+ canonicalDefault: string;
15
+ }
16
+ export declare function looksLikeTempdir(p: string): boolean;
17
+ export declare function inspectWatcherPaths(cfg: BikkyConfig): WatcherPathIssue[];
18
+ /** Format an issue as a multi-line WARN log message. */
19
+ export declare function formatIssue(issue: WatcherPathIssue): string;
20
+ //# sourceMappingURL=watcher-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher-health.d.ts","sourceRoot":"","sources":["../../src/daemon/watcher-health.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAeD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAMnD;AAOD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,gBAAgB,EAAE,CAiCxE;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAO3D"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Watcher path sanity check — flags configurations that will silently
3
+ * produce no extraction work (vanished tempdirs, missing dirs, paths that
4
+ * look like leftover test fixtures).
5
+ *
6
+ * The fix lives outside the watcher itself so daemon startup can warn
7
+ * even before the first extraction tick runs.
8
+ */
9
+ import fs from "node:fs";
10
+ import os from "node:os";
11
+ import path from "node:path";
12
+ const TEMPDIR_PREFIXES = [
13
+ os.tmpdir(),
14
+ "/tmp/",
15
+ "/var/folders/",
16
+ "/private/var/folders/",
17
+ "/private/tmp/",
18
+ ];
19
+ const TEMPDIR_NAME_PATTERNS = [
20
+ /bikky-test-/i,
21
+ /\/T\/TemporaryItems\//,
22
+ ];
23
+ export function looksLikeTempdir(p) {
24
+ if (!p)
25
+ return false;
26
+ const norm = path.resolve(p);
27
+ if (TEMPDIR_PREFIXES.some(prefix => norm.startsWith(prefix)))
28
+ return true;
29
+ if (TEMPDIR_NAME_PATTERNS.some(re => re.test(norm)))
30
+ return true;
31
+ return false;
32
+ }
33
+ function canonicalDefault(watcher) {
34
+ if (watcher === "copilot")
35
+ return path.join(os.homedir(), ".copilot", "session-state");
36
+ return path.join(os.homedir(), ".claude", "projects");
37
+ }
38
+ export function inspectWatcherPaths(cfg) {
39
+ const issues = [];
40
+ const entries = [
41
+ ["copilot", cfg.watchers.copilot],
42
+ ["claude", cfg.watchers.claude],
43
+ ];
44
+ for (const [name, w] of entries) {
45
+ if (!w.enabled)
46
+ continue;
47
+ const reasons = [];
48
+ const def = canonicalDefault(name);
49
+ const isDefault = path.resolve(w.path) === path.resolve(def);
50
+ if (looksLikeTempdir(w.path)) {
51
+ reasons.push("path is under an OS tempdir — likely leftover from a test run");
52
+ }
53
+ if (!fs.existsSync(w.path)) {
54
+ reasons.push("path does not exist on disk");
55
+ }
56
+ // Only flag as an issue if the path is non-default. A missing default path
57
+ // is normal (e.g. user doesn't use Claude) and not worth warning about.
58
+ if (reasons.length > 0 && !isDefault) {
59
+ issues.push({
60
+ watcher: name,
61
+ configuredPath: w.path,
62
+ reasons,
63
+ canonicalDefault: def,
64
+ });
65
+ }
66
+ }
67
+ return issues;
68
+ }
69
+ /** Format an issue as a multi-line WARN log message. */
70
+ export function formatIssue(issue) {
71
+ return [
72
+ `Watcher '${issue.watcher}' path looks broken: ${issue.configuredPath}`,
73
+ ` reasons: ${issue.reasons.join("; ")}`,
74
+ ` canonical default: ${issue.canonicalDefault}`,
75
+ ` fix: edit ~/.bikky/config.json watchers.${issue.watcher}.path, or delete that key to fall back to the default`,
76
+ ].join("\n");
77
+ }
78
+ //# sourceMappingURL=watcher-health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher-health.js","sourceRoot":"","sources":["../../src/daemon/watcher-health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for watcher-health (issue #58).
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=watcher-health.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher-health.test.d.ts","sourceRoot":"","sources":["../../src/daemon/watcher-health.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Tests for watcher-health (issue #58).
3
+ */
4
+ import { describe, it } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import fs from "node:fs";
7
+ import os from "node:os";
8
+ import path from "node:path";
9
+ import { looksLikeTempdir, inspectWatcherPaths, formatIssue } from "./watcher-health.js";
10
+ import { CONFIG_DEFAULTS } from "../config.js";
11
+ describe("looksLikeTempdir", () => {
12
+ it("flags /tmp paths", () => {
13
+ assert.strictEqual(looksLikeTempdir("/tmp/foo"), true);
14
+ });
15
+ it("flags /var/folders paths (macOS)", () => {
16
+ assert.strictEqual(looksLikeTempdir("/var/folders/0z/abc/T/bikky-test-sessions-XYZ"), true);
17
+ });
18
+ it("flags os.tmpdir() prefixed paths", () => {
19
+ assert.strictEqual(looksLikeTempdir(path.join(os.tmpdir(), "anything")), true);
20
+ });
21
+ it("flags bikky-test-* names anywhere", () => {
22
+ assert.strictEqual(looksLikeTempdir("/Users/x/bikky-test-sessions-foo"), true);
23
+ });
24
+ it("does not flag canonical home paths", () => {
25
+ assert.strictEqual(looksLikeTempdir(path.join(os.homedir(), ".copilot", "session-state")), false);
26
+ });
27
+ it("returns false for empty string", () => {
28
+ assert.strictEqual(looksLikeTempdir(""), false);
29
+ });
30
+ });
31
+ describe("inspectWatcherPaths", () => {
32
+ it("returns empty when both watchers point at canonical defaults", () => {
33
+ const cfg = structuredClone(CONFIG_DEFAULTS);
34
+ const issues = inspectWatcherPaths(cfg);
35
+ assert.strictEqual(issues.length, 0);
36
+ });
37
+ it("flags non-default tempdir paths", () => {
38
+ const cfg = structuredClone(CONFIG_DEFAULTS);
39
+ cfg.watchers.copilot.path = "/var/folders/0z/abc/T/bikky-test-sessions-XYZ/mixed-sessions";
40
+ const issues = inspectWatcherPaths(cfg);
41
+ assert.strictEqual(issues.length, 1);
42
+ assert.strictEqual(issues[0].watcher, "copilot");
43
+ assert.ok(issues[0].reasons.some(r => r.includes("tempdir")));
44
+ });
45
+ it("flags non-default missing paths", () => {
46
+ const cfg = structuredClone(CONFIG_DEFAULTS);
47
+ cfg.watchers.copilot.path = "/nonexistent/path/for/test/abc123xyz";
48
+ const issues = inspectWatcherPaths(cfg);
49
+ assert.strictEqual(issues.length, 1);
50
+ assert.ok(issues[0].reasons.some(r => r.includes("does not exist")));
51
+ });
52
+ it("does NOT flag a non-default but valid path", () => {
53
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "bikky-valid-"));
54
+ try {
55
+ const cfg = structuredClone(CONFIG_DEFAULTS);
56
+ // Custom path that exists — but it IS a tempdir, so it WILL be flagged.
57
+ // To test the "valid" case, pick a real homedir path.
58
+ cfg.watchers.copilot.path = path.join(os.homedir());
59
+ const issues = inspectWatcherPaths(cfg);
60
+ assert.strictEqual(issues.length, 0);
61
+ }
62
+ finally {
63
+ fs.rmSync(dir, { recursive: true, force: true });
64
+ }
65
+ });
66
+ it("ignores disabled watchers", () => {
67
+ const cfg = structuredClone(CONFIG_DEFAULTS);
68
+ cfg.watchers.copilot.enabled = false;
69
+ cfg.watchers.copilot.path = "/var/folders/whatever/bikky-test-bad";
70
+ const issues = inspectWatcherPaths(cfg);
71
+ assert.strictEqual(issues.length, 0);
72
+ });
73
+ it("does NOT flag missing default paths (e.g. user without Claude installed)", () => {
74
+ const cfg = structuredClone(CONFIG_DEFAULTS);
75
+ // Both default paths — claude almost certainly absent in CI; that's fine.
76
+ const issues = inspectWatcherPaths(cfg);
77
+ for (const i of issues) {
78
+ assert.notStrictEqual(i.watcher, "claude", `claude default path should not be flagged: ${JSON.stringify(i)}`);
79
+ }
80
+ });
81
+ });
82
+ describe("formatIssue", () => {
83
+ it("includes path, reasons, default, and fix instruction", () => {
84
+ const msg = formatIssue({
85
+ watcher: "copilot",
86
+ configuredPath: "/tmp/bad",
87
+ reasons: ["a", "b"],
88
+ canonicalDefault: "/Users/x/.copilot/session-state",
89
+ });
90
+ assert.ok(msg.includes("/tmp/bad"));
91
+ assert.ok(msg.includes("a; b"));
92
+ assert.ok(msg.includes("/Users/x/.copilot/session-state"));
93
+ assert.ok(msg.includes("fix:"));
94
+ });
95
+ });
96
+ //# sourceMappingURL=watcher-health.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher-health.test.js","sourceRoot":"","sources":["../../src/daemon/watcher-health.test.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Tests for the session watcher.
3
3
  *
4
- * Creates a temporary directory structure mimicking ~/.copilot/session-state/
5
- * and verifies discoverSessions() behavior.
4
+ * Uses BIKKY_HOME to point bikky at an isolated tempdir for the entire test
5
+ * file this prevents saveConfig() from clobbering the user's real
6
+ * ~/.bikky/config.json if a test crashes mid-run (root cause of issue #58).
6
7
  */
7
8
  export {};
8
9
  //# sourceMappingURL=watcher.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.test.d.ts","sourceRoot":"","sources":["../../src/daemon/watcher.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
1
+ {"version":3,"file":"watcher.test.d.ts","sourceRoot":"","sources":["../../src/daemon/watcher.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,44 +1,34 @@
1
1
  /**
2
2
  * Tests for the session watcher.
3
3
  *
4
- * Creates a temporary directory structure mimicking ~/.copilot/session-state/
5
- * and verifies discoverSessions() behavior.
4
+ * Uses BIKKY_HOME to point bikky at an isolated tempdir for the entire test
5
+ * file this prevents saveConfig() from clobbering the user's real
6
+ * ~/.bikky/config.json if a test crashes mid-run (root cause of issue #58).
6
7
  */
7
8
  import { describe, it, before, after, beforeEach } from "node:test";
8
9
  import assert from "node:assert/strict";
9
10
  import fs from "node:fs";
10
11
  import path from "node:path";
11
12
  import os from "node:os";
12
- import { resetConfig, saveConfig, CONFIG_DEFAULTS } from "../config.js";
13
- import { discoverSessions } from "./watcher.js";
13
+ // Set BIKKY_HOME *before* importing config so all derived paths use it.
14
+ const TEST_BIKKY_HOME = fs.mkdtempSync(path.join(os.tmpdir(), "bikky-home-watcher-"));
15
+ process.env.BIKKY_HOME = TEST_BIKKY_HOME;
16
+ const { resetConfig, loadConfig, saveConfig, CONFIG_DEFAULTS } = await import("../config.js");
17
+ const { discoverSessions } = await import("./watcher.js");
14
18
  // ---------------------------------------------------------------------------
15
19
  // Test directory setup
16
20
  // ---------------------------------------------------------------------------
17
21
  let testDir;
18
- let savedConfig = null;
19
22
  function createTestDir() {
20
23
  return fs.mkdtempSync(path.join(os.tmpdir(), "bikky-test-sessions-"));
21
24
  }
22
25
  describe("discoverSessions", () => {
23
26
  before(() => {
24
- // Save existing config state
25
- const configPath = path.join(os.homedir(), ".bikky", "config.json");
26
- if (fs.existsSync(configPath)) {
27
- savedConfig = fs.readFileSync(configPath, "utf-8");
28
- }
29
27
  testDir = createTestDir();
30
28
  });
31
29
  after(() => {
32
- // Clean up test directory
33
30
  fs.rmSync(testDir, { recursive: true, force: true });
34
- // Restore original config
35
- const configPath = path.join(os.homedir(), ".bikky", "config.json");
36
- if (savedConfig !== null) {
37
- fs.writeFileSync(configPath, savedConfig);
38
- }
39
- else if (fs.existsSync(configPath)) {
40
- fs.unlinkSync(configPath);
41
- }
31
+ fs.rmSync(TEST_BIKKY_HOME, { recursive: true, force: true });
42
32
  resetConfig();
43
33
  });
44
34
  beforeEach(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.test.js","sourceRoot":"","sources":["../../src/daemon/watcher.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watcher.test.js","sourceRoot":"","sources":["../../src/daemon/watcher.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Workstream key resolver.
3
+ *
4
+ * The episode-summary LLM emits a free-form `workstream_key` string. Without
5
+ * normalisation, "fix wa-cron", "fix-wa-cron", and "Fix WA Cron" become three
6
+ * different workstreams. This module fixes two problems:
7
+ *
8
+ * 1. **Deterministic extraction.** Many transcripts contain high-precision
9
+ * keys we shouldn't ask the LLM to find: GitHub issue/PR numbers, JIRA
10
+ * keys, branch names, task-folder slugs. We extract those first and let
11
+ * the LLM fall back only when they're absent.
12
+ *
13
+ * 2. **Canonicalization + alias absorption.** Whatever key we end up with
14
+ * (deterministic or LLM) is canonicalised (lowercase, ascii-fold,
15
+ * kebab-case) and matched against an alias registry so trivial rephrasings
16
+ * collapse onto the same canonical key.
17
+ *
18
+ * The registry is in-memory v1 — the daemon seeds it from a Qdrant scroll once
19
+ * per inference cycle and discards it. Persisting the alias graph back to
20
+ * Qdrant is a follow-up.
21
+ */
22
+ export type WorkstreamSource = "deterministic" | "alias" | "llm-new" | "none";
23
+ export interface DeterministicKey {
24
+ key: string;
25
+ source: "issue" | "jira" | "branch" | "task-folder";
26
+ confidence: number;
27
+ }
28
+ export interface ResolvedWorkstream {
29
+ key: string | null;
30
+ source: WorkstreamSource;
31
+ reason: string;
32
+ }
33
+ export interface WorkstreamRegistry {
34
+ /** Canonical → set of aliases (including the canonical itself). */
35
+ canonicalToAliases: Map<string, Set<string>>;
36
+ /** Alias → canonical (reverse index). */
37
+ aliasToCanonical: Map<string, string>;
38
+ }
39
+ /** Empty in-memory registry. */
40
+ export declare const emptyRegistry: () => WorkstreamRegistry;
41
+ /**
42
+ * Canonicalise a raw key:
43
+ * - lowercase
44
+ * - strip leading '#'
45
+ * - ascii-fold (best-effort: replace non-[a-z0-9] runs with '-')
46
+ * - collapse repeated '-'
47
+ * - trim leading/trailing '-'
48
+ *
49
+ * Returns empty string for inputs that contain no usable characters.
50
+ */
51
+ export declare const canonicalizeKey: (raw: string) => string;
52
+ /**
53
+ * Scan the transcript for high-precision durable keys. Returns the first match
54
+ * by pattern priority order; null if none found. We intentionally do not return
55
+ * all matches — picking *one* canonical key is the whole point.
56
+ */
57
+ export declare const extractDeterministicKey: (transcript: string) => DeterministicKey | null;
58
+ /** Add a canonical key to the registry, optionally with extra aliases. */
59
+ export declare const registerCanonical: (registry: WorkstreamRegistry, canonical: string, aliases?: string[]) => void;
60
+ /**
61
+ * Resolve a workstream key for an episode.
62
+ *
63
+ * Decision order:
64
+ * 1. Deterministic extraction from the transcript wins outright.
65
+ * 2. Otherwise, canonicalise the LLM-proposed key. If it matches an existing
66
+ * alias in the registry, return the canonical for that alias.
67
+ * 3. Otherwise, accept the canonicalised LLM key as a brand-new canonical
68
+ * (caller is responsible for registering it if desired).
69
+ * 4. If neither source provides a usable key, return null.
70
+ */
71
+ export declare const resolveWorkstreamKey: (input: {
72
+ transcript: string;
73
+ llmKey?: string | null;
74
+ registry?: WorkstreamRegistry;
75
+ }) => ResolvedWorkstream;
76
+ //# sourceMappingURL=workstream-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workstream-resolver.d.ts","sourceRoot":"","sources":["../../src/daemon/workstream-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,aAAa,CAAC;IACpD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,yCAAyC;IACzC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED,gCAAgC;AAChC,eAAO,MAAM,aAAa,QAAO,kBAG/B,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MAU7C,CAAC;AA0DF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,KAAG,gBAAgB,GAAG,IAa/E,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,GAC5B,UAAU,kBAAkB,EAC5B,WAAW,MAAM,EACjB,UAAS,MAAM,EAAO,KACrB,IAaF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,KAAG,kBAsCH,CAAC"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Workstream key resolver.
3
+ *
4
+ * The episode-summary LLM emits a free-form `workstream_key` string. Without
5
+ * normalisation, "fix wa-cron", "fix-wa-cron", and "Fix WA Cron" become three
6
+ * different workstreams. This module fixes two problems:
7
+ *
8
+ * 1. **Deterministic extraction.** Many transcripts contain high-precision
9
+ * keys we shouldn't ask the LLM to find: GitHub issue/PR numbers, JIRA
10
+ * keys, branch names, task-folder slugs. We extract those first and let
11
+ * the LLM fall back only when they're absent.
12
+ *
13
+ * 2. **Canonicalization + alias absorption.** Whatever key we end up with
14
+ * (deterministic or LLM) is canonicalised (lowercase, ascii-fold,
15
+ * kebab-case) and matched against an alias registry so trivial rephrasings
16
+ * collapse onto the same canonical key.
17
+ *
18
+ * The registry is in-memory v1 — the daemon seeds it from a Qdrant scroll once
19
+ * per inference cycle and discards it. Persisting the alias graph back to
20
+ * Qdrant is a follow-up.
21
+ */
22
+ /** Empty in-memory registry. */
23
+ export const emptyRegistry = () => ({
24
+ canonicalToAliases: new Map(),
25
+ aliasToCanonical: new Map(),
26
+ });
27
+ /**
28
+ * Canonicalise a raw key:
29
+ * - lowercase
30
+ * - strip leading '#'
31
+ * - ascii-fold (best-effort: replace non-[a-z0-9] runs with '-')
32
+ * - collapse repeated '-'
33
+ * - trim leading/trailing '-'
34
+ *
35
+ * Returns empty string for inputs that contain no usable characters.
36
+ */
37
+ export const canonicalizeKey = (raw) => {
38
+ if (typeof raw !== "string")
39
+ return "";
40
+ return raw
41
+ .normalize("NFKD")
42
+ .replace(/[\u0300-\u036f]/g, "")
43
+ .toLowerCase()
44
+ .replace(/^#+/, "")
45
+ .replace(/[^a-z0-9]+/g, "-")
46
+ .replace(/-+/g, "-")
47
+ .replace(/^-+|-+$/g, "");
48
+ };
49
+ /**
50
+ * Tokens that look like JIRA keys but never are. Common protocol/encoding/
51
+ * convention names that follow the same `LETTERS-DIGITS` shape.
52
+ */
53
+ const JIRA_DENYLIST = new Set([
54
+ "http", "https", "utf", "ascii", "iso", "rfc", "ietf", "ipv",
55
+ "gh", "pr", "tcp", "udp", "sha", "md", "h2", "h3", "ws",
56
+ "feat", "fix", "chore", "docs", "test", "perf", "ci", "build", "refactor",
57
+ ]);
58
+ const DETERMINISTIC_PATTERNS = [
59
+ // Task folder slug — highest precision (we created it ourselves).
60
+ {
61
+ re: /\btasks\/(\d{3}-[a-z0-9][a-z0-9-]*)/i,
62
+ source: "task-folder",
63
+ confidence: 0.95,
64
+ format: (m) => m[1].toLowerCase(),
65
+ },
66
+ // GitHub issue/PR refs: #123, GH-123, gh-123. Checked BEFORE JIRA so
67
+ // `GH-44` doesn't get misclassified as a JIRA project key.
68
+ {
69
+ re: /(?:^|[^A-Za-z0-9_])(?:#|gh-|GH-)(\d{1,6})\b/,
70
+ source: "issue",
71
+ confidence: 0.9,
72
+ format: (m) => `gh-${m[1]}`,
73
+ },
74
+ {
75
+ re: /\b(?:issue|pr|pull\s+request)\s*#?(\d{1,6})\b/i,
76
+ source: "issue",
77
+ confidence: 0.85,
78
+ format: (m) => `gh-${m[1]}`,
79
+ },
80
+ // JIRA-style key: 3-6 uppercase letters + dash + digits (≥2 to avoid
81
+ // matching things like `H2-1`). Reject known protocol/encoding tokens.
82
+ {
83
+ re: /\b([A-Z]{3,6})-(\d{2,})\b/,
84
+ source: "jira",
85
+ confidence: 0.95,
86
+ format: (m) => `${m[1].toLowerCase()}-${m[2]}`,
87
+ reject: (m) => JIRA_DENYLIST.has(m[1].toLowerCase()),
88
+ },
89
+ // Conventional branch names.
90
+ {
91
+ re: /\b(?:feat|fix|chore|refactor|docs|test|perf|ci|build)\/([a-z0-9][a-z0-9-]{2,40})\b/i,
92
+ source: "branch",
93
+ confidence: 0.85,
94
+ format: (m) => m[1].toLowerCase(),
95
+ },
96
+ ];
97
+ /**
98
+ * Scan the transcript for high-precision durable keys. Returns the first match
99
+ * by pattern priority order; null if none found. We intentionally do not return
100
+ * all matches — picking *one* canonical key is the whole point.
101
+ */
102
+ export const extractDeterministicKey = (transcript) => {
103
+ if (!transcript || typeof transcript !== "string")
104
+ return null;
105
+ for (const pattern of DETERMINISTIC_PATTERNS) {
106
+ const m = transcript.match(pattern.re);
107
+ if (m) {
108
+ const key = pattern.format(m);
109
+ if (pattern.reject?.(m))
110
+ continue;
111
+ if (key.length > 0) {
112
+ return { key, source: pattern.source, confidence: pattern.confidence };
113
+ }
114
+ }
115
+ }
116
+ return null;
117
+ };
118
+ /** Add a canonical key to the registry, optionally with extra aliases. */
119
+ export const registerCanonical = (registry, canonical, aliases = []) => {
120
+ const c = canonicalizeKey(canonical);
121
+ if (!c)
122
+ return;
123
+ const set = registry.canonicalToAliases.get(c) ?? new Set();
124
+ set.add(c);
125
+ registry.aliasToCanonical.set(c, c);
126
+ for (const a of aliases) {
127
+ const ac = canonicalizeKey(a);
128
+ if (!ac)
129
+ continue;
130
+ set.add(ac);
131
+ registry.aliasToCanonical.set(ac, c);
132
+ }
133
+ registry.canonicalToAliases.set(c, set);
134
+ };
135
+ /**
136
+ * Resolve a workstream key for an episode.
137
+ *
138
+ * Decision order:
139
+ * 1. Deterministic extraction from the transcript wins outright.
140
+ * 2. Otherwise, canonicalise the LLM-proposed key. If it matches an existing
141
+ * alias in the registry, return the canonical for that alias.
142
+ * 3. Otherwise, accept the canonicalised LLM key as a brand-new canonical
143
+ * (caller is responsible for registering it if desired).
144
+ * 4. If neither source provides a usable key, return null.
145
+ */
146
+ export const resolveWorkstreamKey = (input) => {
147
+ const registry = input.registry ?? emptyRegistry();
148
+ const deterministic = extractDeterministicKey(input.transcript);
149
+ if (deterministic) {
150
+ const canonical = canonicalizeKey(deterministic.key);
151
+ const known = registry.aliasToCanonical.get(canonical);
152
+ return {
153
+ key: known ?? canonical,
154
+ source: known ? "alias" : "deterministic",
155
+ reason: `deterministic ${deterministic.source} match (${deterministic.key})`,
156
+ };
157
+ }
158
+ const llm = (input.llmKey ?? "").trim();
159
+ if (!llm) {
160
+ return { key: null, source: "none", reason: "no deterministic key found and LLM returned no key" };
161
+ }
162
+ const canonical = canonicalizeKey(llm);
163
+ if (!canonical) {
164
+ return { key: null, source: "none", reason: `LLM key "${llm}" canonicalised to empty string` };
165
+ }
166
+ const known = registry.aliasToCanonical.get(canonical);
167
+ if (known) {
168
+ return {
169
+ key: known,
170
+ source: "alias",
171
+ reason: `LLM key "${llm}" matched existing canonical "${known}"`,
172
+ };
173
+ }
174
+ return {
175
+ key: canonical,
176
+ source: "llm-new",
177
+ reason: `LLM key "${llm}" registered as new canonical "${canonical}"`,
178
+ };
179
+ };
180
+ //# sourceMappingURL=workstream-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workstream-resolver.js","sourceRoot":"","sources":["../../src/daemon/workstream-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=workstream-resolver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workstream-resolver.test.d.ts","sourceRoot":"","sources":["../../src/daemon/workstream-resolver.test.ts"],"names":[],"mappings":""}