sandstream-kit 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +101 -92
  2. package/dist/adapters/expo-eas.js +1 -1
  3. package/dist/adapters/expo-eas.js.map +1 -1
  4. package/dist/audit-logging-service.js +1 -1
  5. package/dist/audit-logging-service.js.map +1 -1
  6. package/dist/author-verification.js +1 -1
  7. package/dist/author-verification.js.map +1 -1
  8. package/dist/cli-shared.d.ts +4 -0
  9. package/dist/cli-shared.js +11 -0
  10. package/dist/cli-shared.js.map +1 -0
  11. package/dist/cli.js +156 -1232
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/audit.d.ts +1 -0
  14. package/dist/commands/audit.js +99 -0
  15. package/dist/commands/audit.js.map +1 -0
  16. package/dist/commands/auth.d.ts +1 -0
  17. package/dist/commands/auth.js +121 -0
  18. package/dist/commands/auth.js.map +1 -0
  19. package/dist/commands/env.d.ts +1 -0
  20. package/dist/commands/env.js +149 -0
  21. package/dist/commands/env.js.map +1 -0
  22. package/dist/commands/hooks.d.ts +1 -0
  23. package/dist/commands/hooks.js +146 -0
  24. package/dist/commands/hooks.js.map +1 -0
  25. package/dist/commands/mcp.d.ts +1 -0
  26. package/dist/commands/mcp.js +120 -0
  27. package/dist/commands/mcp.js.map +1 -0
  28. package/dist/commands/memory.d.ts +1 -0
  29. package/dist/commands/memory.js +534 -0
  30. package/dist/commands/memory.js.map +1 -0
  31. package/dist/config.js +3 -0
  32. package/dist/config.js.map +1 -1
  33. package/dist/mcp-server.js +59 -6
  34. package/dist/mcp-server.js.map +1 -1
  35. package/dist/memory/amazonq.d.ts +5 -0
  36. package/dist/memory/amazonq.js +161 -0
  37. package/dist/memory/amazonq.js.map +1 -0
  38. package/dist/memory/cline.d.ts +5 -0
  39. package/dist/memory/cline.js +117 -0
  40. package/dist/memory/cline.js.map +1 -0
  41. package/dist/memory/cursor.d.ts +4 -0
  42. package/dist/memory/cursor.js +116 -0
  43. package/dist/memory/cursor.js.map +1 -0
  44. package/dist/memory/merge.js +7 -1
  45. package/dist/memory/merge.js.map +1 -1
  46. package/dist/memory/pal.js +8 -2
  47. package/dist/memory/pal.js.map +1 -1
  48. package/dist/memory/parser.js +6 -0
  49. package/dist/memory/parser.js.map +1 -1
  50. package/dist/memory/suggest.d.ts +21 -0
  51. package/dist/memory/suggest.js +36 -0
  52. package/dist/memory/suggest.js.map +1 -0
  53. package/dist/onepassword.js +1 -1
  54. package/dist/onepassword.js.map +1 -1
  55. package/dist/open.js +8 -2
  56. package/dist/open.js.map +1 -1
  57. package/dist/run.js +1 -1
  58. package/dist/run.js.map +1 -1
  59. package/dist/service-auth.d.ts +31 -0
  60. package/dist/service-auth.js +47 -0
  61. package/dist/service-auth.js.map +1 -0
  62. package/dist/stack-detector.js +53 -76
  63. package/dist/stack-detector.js.map +1 -1
  64. package/package.json +9 -4
  65. package/dist/memory/backup 2.d.ts +0 -6
  66. package/dist/memory/backup 2.js +0 -80
  67. package/dist/memory/backup 2.js.map +0 -1
  68. package/dist/memory/db 2.d.ts +0 -40
  69. package/dist/memory/db 2.js +0 -233
  70. package/dist/memory/db 2.js.map +0 -1
  71. package/dist/memory/hook 2.d.ts +0 -6
  72. package/dist/memory/hook 2.js +0 -51
  73. package/dist/memory/hook 2.js.map +0 -1
  74. package/dist/memory/hook.test 2.d.ts +0 -1
  75. package/dist/memory/hook.test 2.js +0 -35
  76. package/dist/memory/hook.test 2.js.map +0 -1
  77. package/dist/memory/install 2.d.ts +0 -8
  78. package/dist/memory/install 2.js +0 -72
  79. package/dist/memory/install 2.js.map +0 -1
  80. package/dist/memory/install.test 2.d.ts +0 -1
  81. package/dist/memory/install.test 2.js +0 -59
  82. package/dist/memory/install.test 2.js.map +0 -1
  83. package/dist/memory/pal 2.d.ts +0 -47
  84. package/dist/memory/pal 2.js +0 -154
  85. package/dist/memory/pal 2.js.map +0 -1
  86. package/dist/memory/project 2.d.ts +0 -1
  87. package/dist/memory/project 2.js +0 -24
  88. package/dist/memory/project 2.js.map +0 -1
  89. package/dist/memory/scan 2.d.ts +0 -15
  90. package/dist/memory/scan 2.js +0 -94
  91. package/dist/memory/scan 2.js.map +0 -1
  92. package/dist/memory/scan.test 2.d.ts +0 -1
  93. package/dist/memory/scan.test 2.js +0 -55
  94. package/dist/memory/scan.test 2.js.map +0 -1
  95. package/dist/memory/shared 2.d.ts +0 -33
  96. package/dist/memory/shared 2.js +0 -120
  97. package/dist/memory/shared 2.js.map +0 -1
  98. package/dist/memory/threads 2.d.ts +0 -37
  99. package/dist/memory/threads 2.js +0 -50
  100. package/dist/memory/threads 2.js.map +0 -1
  101. package/dist/memory/threads.test 2.d.ts +0 -1
  102. package/dist/memory/threads.test 2.js +0 -66
  103. package/dist/memory/threads.test 2.js.map +0 -1
  104. package/dist/memory/types 2.d.ts +0 -52
  105. package/dist/memory/types 2.js +0 -5
  106. package/dist/memory/types 2.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"db 2.js","sourceRoot":"","sources":["../../src/memory/db 2.ts"],"names":[],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- /** Reminder injected before every prompt. Empty string on any error (fail-open). */
2
- export declare function userPromptSubmitReminder(): string;
3
- /** Index the just-ended session. Returns count of newly indexed messages (fail-open). */
4
- export declare function runSessionEndIndex(): {
5
- messages: number;
6
- };
@@ -1,51 +0,0 @@
1
- /**
2
- * kit memory — Claude Code hook entry points (the "whole system is two hooks").
3
- *
4
- * - UserPromptSubmit → a short reminder that searchable memory exists. The agent
5
- * pulls on demand (`kit memory search`) instead of pre-loading everything.
6
- * - SessionEnd → index the just-ended session into the store (incremental sync).
7
- *
8
- * Both are FAIL-OPEN: any error yields an empty/no-op result so a hook can never
9
- * block a prompt or break a session. Deterministic, zero model calls.
10
- */
11
- import { basename } from "node:path";
12
- import { openMemoryDb, getStats } from "./db.js";
13
- import { indexClaudeTranscripts } from "./parser.js";
14
- import { palList } from "./pal.js";
15
- import { getCurrentProjectRoot } from "./project.js";
16
- /** Reminder injected before every prompt. Empty string on any error (fail-open). */
17
- export function userPromptSubmitReminder() {
18
- try {
19
- const db = openMemoryDb();
20
- const s = getStats(db);
21
- // Only surface THIS project's open items (plus globally-scoped) — no cross-project noise.
22
- const openItems = palList(db, { scope: basename(getCurrentProjectRoot()) });
23
- db.close();
24
- let pending = "";
25
- if (openItems.length > 0) {
26
- const shown = openItems.slice(0, 3);
27
- const titles = shown.map((p) => `${p.id} ${p.title}`).join("; ");
28
- const more = openItems.length > shown.length ? " …" : "";
29
- pending = ` ${openItems.length} open action item(s) blocked on you: ${titles}${more}.`;
30
- }
31
- return (`You have local conversation memory: ${s.messages} messages indexed. ` +
32
- "Before answering anything project-specific, run `kit memory search <terms>` " +
33
- `to retrieve what was actually said instead of reconstructing it.${pending}`);
34
- }
35
- catch {
36
- return ""; // fail-open: never block a prompt
37
- }
38
- }
39
- /** Index the just-ended session. Returns count of newly indexed messages (fail-open). */
40
- export function runSessionEndIndex() {
41
- try {
42
- const db = openMemoryDb();
43
- const res = indexClaudeTranscripts(db);
44
- db.close();
45
- return { messages: res.messages };
46
- }
47
- catch {
48
- return { messages: 0 }; // fail-open
49
- }
50
- }
51
- //# sourceMappingURL=hook%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hook 2.js","sourceRoot":"","sources":["../../src/memory/hook 2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,oFAAoF;AACpF,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvB,0FAA0F;QAC1F,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,qBAAqB,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5E,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,GAAG,IAAI,SAAS,CAAC,MAAM,wCAAwC,MAAM,GAAG,IAAI,GAAG,CAAC;QACzF,CAAC;QACD,OAAO,CACL,uCAAuC,CAAC,CAAC,QAAQ,qBAAqB;YACtE,8EAA8E;YAC9E,mEAAmE,OAAO,EAAE,CAC7E,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,kCAAkC;IAC/C,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,sBAAsB,CAAC,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,YAAY;IACtC,CAAC;AACH,CAAC"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,35 +0,0 @@
1
- import { describe, it, before, after } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { mkdtempSync, rmSync } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { openMemoryDb, upsertSession, insertMessage } from "./db.js";
7
- import { userPromptSubmitReminder } from "./hook.js";
8
- describe("memory hook — UserPromptSubmit reminder", () => {
9
- let tmp;
10
- const prev = process.env.KIT_MEMORY_DB;
11
- before(() => {
12
- tmp = mkdtempSync(join(tmpdir(), "kit-hook-"));
13
- process.env.KIT_MEMORY_DB = join(tmp, "memory.db");
14
- const db = openMemoryDb();
15
- upsertSession(db, { sessionId: "s1", harness: "claude-code" });
16
- insertMessage(db, { uuid: "u1", sessionId: "s1", type: "user", content: "hi" });
17
- db.close();
18
- });
19
- after(() => {
20
- if (prev === undefined)
21
- delete process.env.KIT_MEMORY_DB;
22
- else
23
- process.env.KIT_MEMORY_DB = prev;
24
- rmSync(tmp, { recursive: true, force: true });
25
- });
26
- it("nudges the agent to search and reports the message count", () => {
27
- const text = userPromptSubmitReminder();
28
- assert.match(text, /kit memory search/);
29
- assert.match(text, /1 messages/);
30
- });
31
- it("never throws (fail-open)", () => {
32
- assert.doesNotThrow(() => userPromptSubmitReminder());
33
- });
34
- });
35
- //# sourceMappingURL=hook.test%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hook.test 2.js","sourceRoot":"","sources":["../../src/memory/hook.test 2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAErD,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,IAAI,GAAW,CAAC;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAEvC,MAAM,CAAC,GAAG,EAAE;QACV,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACnD,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;QAC1B,aAAa,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;QAC/D,aAAa,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,EAAE;QACT,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;;YACpD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;QACtC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,IAAI,GAAG,wBAAwB,EAAE,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,wBAAwB,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,8 +0,0 @@
1
- export declare function getClaudeSettingsPath(): string;
2
- export declare function installMemoryHooks(path?: string): {
3
- added: string[];
4
- alreadyPresent: string[];
5
- };
6
- export declare function uninstallMemoryHooks(path?: string): {
7
- removed: string[];
8
- };
@@ -1,72 +0,0 @@
1
- /**
2
- * kit memory — install/remove the two Claude Code hooks in ~/.claude/settings.json.
3
- *
4
- * Idempotent and non-destructive: merges our hook entries into the existing
5
- * settings without touching the user's other hooks. Re-running adds nothing.
6
- * Honors KIT_CLAUDE_SETTINGS for tests.
7
- */
8
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
9
- import { homedir } from "node:os";
10
- import { join, dirname } from "node:path";
11
- const MEMORY_HOOKS = [
12
- { event: "UserPromptSubmit", command: "kit memory hook user-prompt-submit" },
13
- { event: "SessionEnd", command: "kit memory hook session-end" },
14
- ];
15
- export function getClaudeSettingsPath() {
16
- return process.env.KIT_CLAUDE_SETTINGS ?? join(homedir(), ".claude", "settings.json");
17
- }
18
- function readSettings(path) {
19
- if (!existsSync(path))
20
- return {};
21
- try {
22
- return JSON.parse(readFileSync(path, "utf8"));
23
- }
24
- catch {
25
- return {}; // corrupt/unreadable → start fresh rather than crash
26
- }
27
- }
28
- function writeSettings(path, s) {
29
- mkdirSync(dirname(path), { recursive: true });
30
- writeFileSync(path, JSON.stringify(s, null, 2) + "\n");
31
- }
32
- function groupsHaveCommand(groups, command) {
33
- return groups.some((g) => g.hooks?.some((h) => h.command === command));
34
- }
35
- export function installMemoryHooks(path = getClaudeSettingsPath()) {
36
- const s = readSettings(path);
37
- const hooks = (s.hooks ??= {});
38
- const added = [];
39
- const alreadyPresent = [];
40
- for (const { event, command } of MEMORY_HOOKS) {
41
- const groups = (hooks[event] ??= []);
42
- if (groupsHaveCommand(groups, command)) {
43
- alreadyPresent.push(event);
44
- continue;
45
- }
46
- groups.push({ hooks: [{ type: "command", command }] });
47
- added.push(event);
48
- }
49
- if (added.length)
50
- writeSettings(path, s);
51
- return { added, alreadyPresent };
52
- }
53
- export function uninstallMemoryHooks(path = getClaudeSettingsPath()) {
54
- const s = readSettings(path);
55
- if (!s.hooks)
56
- return { removed: [] };
57
- const removed = [];
58
- for (const { event, command } of MEMORY_HOOKS) {
59
- const groups = s.hooks[event];
60
- if (!Array.isArray(groups))
61
- continue;
62
- const filtered = groups.filter((g) => !g.hooks?.some((h) => h.command === command));
63
- if (filtered.length !== groups.length) {
64
- s.hooks[event] = filtered;
65
- removed.push(event);
66
- }
67
- }
68
- if (removed.length)
69
- writeSettings(path, s);
70
- return { removed };
71
- }
72
- //# sourceMappingURL=install%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install 2.js","sourceRoot":"","sources":["../../src/memory/install 2.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,59 +0,0 @@
1
- import { describe, it, before, after, beforeEach } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { mkdtempSync, rmSync, writeFileSync, readFileSync } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { installMemoryHooks, uninstallMemoryHooks } from "./install.js";
7
- describe("memory hook installer", () => {
8
- let tmp;
9
- let settingsPath;
10
- const prev = process.env.KIT_CLAUDE_SETTINGS;
11
- before(() => {
12
- tmp = mkdtempSync(join(tmpdir(), "kit-install-"));
13
- settingsPath = join(tmp, "settings.json");
14
- process.env.KIT_CLAUDE_SETTINGS = settingsPath;
15
- });
16
- beforeEach(() => {
17
- // Start each test from a settings file with an unrelated, pre-existing hook.
18
- writeFileSync(settingsPath, JSON.stringify({
19
- hooks: {
20
- UserPromptSubmit: [{ hooks: [{ type: "command", command: "some-other-tool" }] }],
21
- },
22
- }));
23
- });
24
- after(() => {
25
- if (prev === undefined)
26
- delete process.env.KIT_CLAUDE_SETTINGS;
27
- else
28
- process.env.KIT_CLAUDE_SETTINGS = prev;
29
- rmSync(tmp, { recursive: true, force: true });
30
- });
31
- it("installs both hooks without clobbering existing ones", () => {
32
- const res = installMemoryHooks();
33
- assert.deepEqual(res.added.sort(), ["SessionEnd", "UserPromptSubmit"]);
34
- const s = JSON.parse(readFileSync(settingsPath, "utf8"));
35
- const ups = s.hooks.UserPromptSubmit.flatMap((g) => g.hooks.map((h) => h.command));
36
- assert.ok(ups.includes("some-other-tool"), "preserves the pre-existing hook");
37
- assert.ok(ups.includes("kit memory hook user-prompt-submit"));
38
- assert.ok(s.hooks.SessionEnd.some((g) => g.hooks.some((h) => h.command === "kit memory hook session-end")));
39
- });
40
- it("is idempotent — re-install adds nothing and creates no duplicates", () => {
41
- installMemoryHooks();
42
- const res2 = installMemoryHooks();
43
- assert.deepEqual(res2.added, []);
44
- assert.deepEqual(res2.alreadyPresent.sort(), ["SessionEnd", "UserPromptSubmit"]);
45
- const s = JSON.parse(readFileSync(settingsPath, "utf8"));
46
- const ours = s.hooks.UserPromptSubmit.filter((g) => g.hooks.some((h) => h.command === "kit memory hook user-prompt-submit"));
47
- assert.equal(ours.length, 1);
48
- });
49
- it("uninstall removes only our hooks, leaving others intact", () => {
50
- installMemoryHooks();
51
- const res = uninstallMemoryHooks();
52
- assert.deepEqual(res.removed.sort(), ["SessionEnd", "UserPromptSubmit"]);
53
- const s = JSON.parse(readFileSync(settingsPath, "utf8"));
54
- const ups = s.hooks.UserPromptSubmit.flatMap((g) => g.hooks.map((h) => h.command));
55
- assert.ok(ups.includes("some-other-tool"), "unrelated hook survives uninstall");
56
- assert.ok(!ups.includes("kit memory hook user-prompt-submit"));
57
- });
58
- });
59
- //# sourceMappingURL=install.test%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install.test 2.js","sourceRoot":"","sources":["../../src/memory/install.test 2.ts"],"names":[],"mappings":"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"}
@@ -1,47 +0,0 @@
1
- import type { DatabaseSync } from "node:sqlite";
2
- export interface PendingAction {
3
- id: string;
4
- status: string;
5
- title: string;
6
- detail: string | null;
7
- scope: string | null;
8
- kind: string;
9
- verify_cmd: string | null;
10
- created_at: string | null;
11
- next_check: string | null;
12
- snooze_until: string | null;
13
- closed_at: string | null;
14
- verify_passes: number;
15
- }
16
- export interface PalAddInput {
17
- title: string;
18
- detail?: string;
19
- scope?: string;
20
- kind?: "manual" | "auto";
21
- verifyCmd?: string;
22
- }
23
- export declare function palAdd(db: DatabaseSync, input: PalAddInput): string;
24
- export interface PalListOptions {
25
- status?: string;
26
- /** Restrict to this scope plus globally-scoped (NULL) items. Omit = every scope. */
27
- scope?: string;
28
- }
29
- export declare function palList(db: DatabaseSync, opts?: PalListOptions): PendingAction[];
30
- export declare function palDone(db: DatabaseSync, id: string): boolean;
31
- export declare function palSnooze(db: DatabaseSync, id: string, days: number): boolean;
32
- export interface AutoVerifyResult {
33
- checked: number;
34
- closed: string[];
35
- reopened: string[];
36
- }
37
- /**
38
- * Auto-verify `auto` items. An OPEN item that passes `confirmPasses` consecutive
39
- * times is closed (a pass increments the streak, a fail resets it). A CLOSED item
40
- * whose verify now FAILS is reopened (reopen-on-regress). No-info leaves it alone.
41
- */
42
- export declare function palAutoVerify(db: DatabaseSync, confirmPasses?: number): AutoVerifyResult;
43
- export declare function getLegacyLedgerPath(): string;
44
- /** Import the old `~/.claude/pal/ledger.jsonl` into pending_actions. Idempotent (by id). */
45
- export declare function importLegacyLedger(db: DatabaseSync, path?: string): {
46
- imported: number;
47
- };
@@ -1,154 +0,0 @@
1
- /**
2
- * kit memory — PAL (Pending Action Ledger), folded into the memory store.
3
- *
4
- * PAL is the STRUCTURED, actionable layer on top of raw conversation memory:
5
- * "blocked-on-you" items that survive sessions and auto-close when their verify
6
- * command starts passing. It lives in the `pending_actions` table of the same
7
- * SQLite store. Deterministic; the only side effect is running operator-defined
8
- * verify commands (local shell, with a timeout). Fail-open / no-info aware.
9
- */
10
- import { randomBytes } from "node:crypto";
11
- import { execSync } from "node:child_process";
12
- import { readFileSync, existsSync } from "node:fs";
13
- import { homedir } from "node:os";
14
- import { join } from "node:path";
15
- function newId(db) {
16
- for (let i = 0; i < 100; i++) {
17
- const id = randomBytes(2).toString("hex"); // 4 hex chars, e.g. "ec95"
18
- if (!db.prepare("SELECT 1 FROM pending_actions WHERE id = ?").get(id))
19
- return id;
20
- }
21
- throw new Error("could not allocate a unique pending-action id");
22
- }
23
- export function palAdd(db, input) {
24
- const id = newId(db);
25
- const kind = input.kind ?? (input.verifyCmd ? "auto" : "manual");
26
- db.prepare(`INSERT INTO pending_actions (id, status, title, detail, scope, kind, verify_cmd)
27
- VALUES (?, 'open', ?, ?, ?, ?, ?)`).run(id, input.title, input.detail ?? null, input.scope ?? null, kind, input.verifyCmd ?? null);
28
- return id;
29
- }
30
- export function palList(db, opts = {}) {
31
- const status = opts.status ?? "open";
32
- if (opts.scope !== undefined) {
33
- return db
34
- .prepare("SELECT * FROM pending_actions WHERE status = ? AND (scope = ? OR scope IS NULL) ORDER BY created_at, id")
35
- .all(status, opts.scope);
36
- }
37
- return db
38
- .prepare("SELECT * FROM pending_actions WHERE status = ? ORDER BY created_at, id")
39
- .all(status);
40
- }
41
- export function palDone(db, id) {
42
- const res = db
43
- .prepare("UPDATE pending_actions SET status='closed', closed_at=datetime('now') WHERE id=? AND status!='closed'")
44
- .run(id);
45
- return Number(res.changes) > 0;
46
- }
47
- export function palSnooze(db, id, days) {
48
- const d = Math.max(1, Math.floor(days));
49
- const res = db
50
- .prepare("UPDATE pending_actions SET status='snoozed', snooze_until=datetime('now', ?) WHERE id=?")
51
- .run(`+${d} days`, id);
52
- return Number(res.changes) > 0;
53
- }
54
- /**
55
- * Run a verify command. true = pass (exit 0), false = ran but failed, null = no-info.
56
- *
57
- * SECURITY: this runs `cmd` through a shell on purpose — verify commands routinely
58
- * need pipes / `&&` (e.g. `curl -fsS … | grep 200`). The trust boundary: `verify_cmd`
59
- * is OPERATOR-AUTHORED and lives only in the PERSONAL store (~/.kit/memory.db); running
60
- * it is equivalent to the operator running their own command — no untrusted data is
61
- * interpolated, so this is not a command-injection sink. INVARIANT for Track D (shared
62
- * memory): shared/synced items must NEVER carry an executable `verify_cmd` that runs
63
- * unreviewed — only manual items or review-gated verifies cross the sharing boundary.
64
- */
65
- function runVerify(cmd) {
66
- try {
67
- execSync(cmd, { stdio: "ignore", timeout: 15_000 });
68
- return true;
69
- }
70
- catch (err) {
71
- const status = err.status;
72
- if (typeof status === "number")
73
- return false; // ran, non-zero exit
74
- return null; // spawn error / timeout → no-info, leave state unchanged
75
- }
76
- }
77
- /**
78
- * Auto-verify `auto` items. An OPEN item that passes `confirmPasses` consecutive
79
- * times is closed (a pass increments the streak, a fail resets it). A CLOSED item
80
- * whose verify now FAILS is reopened (reopen-on-regress). No-info leaves it alone.
81
- */
82
- export function palAutoVerify(db, confirmPasses = 2) {
83
- const out = { checked: 0, closed: [], reopened: [] };
84
- const rows = db
85
- .prepare("SELECT * FROM pending_actions WHERE kind='auto' AND verify_cmd IS NOT NULL AND status IN ('open','closed')")
86
- .all();
87
- for (const r of rows) {
88
- const result = runVerify(r.verify_cmd);
89
- if (result === null)
90
- continue; // no-info
91
- out.checked++;
92
- if (r.status === "open") {
93
- if (result) {
94
- const passes = r.verify_passes + 1;
95
- if (passes >= confirmPasses) {
96
- db.prepare("UPDATE pending_actions SET status='closed', closed_at=datetime('now'), verify_passes=? WHERE id=?").run(passes, r.id);
97
- out.closed.push(r.id);
98
- }
99
- else {
100
- db.prepare("UPDATE pending_actions SET verify_passes=? WHERE id=?").run(passes, r.id);
101
- }
102
- }
103
- else if (r.verify_passes !== 0) {
104
- db.prepare("UPDATE pending_actions SET verify_passes=0 WHERE id=?").run(r.id);
105
- }
106
- }
107
- else if (r.status === "closed" && !result) {
108
- db.prepare("UPDATE pending_actions SET status='open', verify_passes=0, closed_at=NULL WHERE id=?").run(r.id);
109
- out.reopened.push(r.id);
110
- }
111
- }
112
- return out;
113
- }
114
- // ── Migration from the legacy python PAL ledger ───────────────────────────────
115
- export function getLegacyLedgerPath() {
116
- return process.env.KIT_PAL_LEDGER ?? join(homedir(), ".claude", "pal", "ledger.jsonl");
117
- }
118
- /** Import the old `~/.claude/pal/ledger.jsonl` into pending_actions. Idempotent (by id). */
119
- export function importLegacyLedger(db, path = getLegacyLedgerPath()) {
120
- if (!existsSync(path))
121
- return { imported: 0 };
122
- let raw;
123
- try {
124
- raw = readFileSync(path, "utf8");
125
- }
126
- catch {
127
- return { imported: 0 };
128
- }
129
- const insert = db.prepare(`INSERT OR IGNORE INTO pending_actions
130
- (id, status, title, detail, scope, kind, verify_cmd, created_at, next_check, verify_passes)
131
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
132
- let imported = 0;
133
- for (const line of raw.split("\n")) {
134
- const t = line.trim();
135
- if (!t)
136
- continue;
137
- let e;
138
- try {
139
- e = JSON.parse(t);
140
- }
141
- catch {
142
- continue;
143
- }
144
- if (!e.id || !e.title)
145
- continue;
146
- const status = e.status === "done" ? "closed" : (e.status ?? "open");
147
- const kind = e.verify ? "auto" : "manual";
148
- const res = insert.run(e.id, status, e.title, e.why ?? null, e.repo ?? null, kind, e.verify ?? null, e.ts ?? null, e.next_check ?? null, e.pass_streak ?? 0);
149
- if (Number(res.changes) > 0)
150
- imported++;
151
- }
152
- return { imported };
153
- }
154
- //# sourceMappingURL=pal%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pal 2.js","sourceRoot":"","sources":["../../src/memory/pal 2.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export declare function getCurrentProjectRoot(cwd?: string): string;
@@ -1,24 +0,0 @@
1
- /**
2
- * kit memory — current-project resolution.
3
- *
4
- * Memory search defaults to the current project (relevance + blast-radius
5
- * containment); the repo root is the project boundary. Falls back to cwd when not
6
- * inside a git repo. Pure read — no model calls, no writes.
7
- */
8
- import { execFileSync } from "node:child_process";
9
- export function getCurrentProjectRoot(cwd = process.cwd()) {
10
- try {
11
- const root = execFileSync("git", ["rev-parse", "--show-toplevel"], {
12
- cwd,
13
- encoding: "utf8",
14
- stdio: ["ignore", "pipe", "ignore"],
15
- }).trim();
16
- if (root)
17
- return root;
18
- }
19
- catch {
20
- // not a git repo (or git unavailable) — fall back to cwd
21
- }
22
- return cwd;
23
- }
24
- //# sourceMappingURL=project%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project 2.js","sourceRoot":"","sources":["../../src/memory/project 2.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,qBAAqB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE;YACjE,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,15 +0,0 @@
1
- import type { DatabaseSync } from "node:sqlite";
2
- export type ScanConfidence = "high" | "heuristic";
3
- export interface ScanFinding {
4
- label: string;
5
- preview: string;
6
- confidence: ScanConfidence;
7
- /** How many cells matched this (label, preview). */
8
- count: number;
9
- /** One example location, e.g. "messages#23839.content". */
10
- sample: string;
11
- /** Distinct project hints (which repo the secret leaked in), e.g. ["acme-app"]. */
12
- projects: string[];
13
- }
14
- /** Scan every text cell for stored secrets. Deduped, confidence-tiered, project-attributed. */
15
- export declare function scanDbForSecrets(db: DatabaseSync): ScanFinding[];
@@ -1,94 +0,0 @@
1
- /**
2
- * kit memory — secret scan over the store.
3
- *
4
- * The memory DB is secret-dense (it indexes raw transcripts). gitleaks and most
5
- * scanners only see text files, not SQLite cell contents — so this scans the text
6
- * columns directly, reusing kit's SECRET_PATTERNS via findSecrets (DRY). Findings
7
- * are MASKED (label + short preview), never the raw secret.
8
- *
9
- * Findings are DEDUPED by (label, preview) with an occurrence count, split by
10
- * CONFIDENCE so the genuinely dangerous keys (sk_live, AIzaSy, AKIA, ghp_, …) are
11
- * not buried under the over-eager `KEY=value` heuristic, and ATTRIBUTED to the
12
- * project(s) they leaked in (via each row's cwd) so you know which provider account
13
- * to rotate. Only high-confidence findings make `kit memory scan` exit non-zero.
14
- */
15
- import { basename } from "node:path";
16
- import { findSecrets } from "../utils/redactSecrets.js";
17
- const TARGETS = [
18
- {
19
- table: "messages",
20
- idCol: "id",
21
- columns: ["content"],
22
- select: "SELECT id, content, cwd AS __project FROM messages",
23
- },
24
- {
25
- table: "tool_uses",
26
- idCol: "id",
27
- columns: ["tool_input"],
28
- select: "SELECT tool_uses.id AS id, tool_uses.tool_input AS tool_input, m.cwd AS __project " +
29
- "FROM tool_uses LEFT JOIN messages m ON m.uuid = tool_uses.message_uuid",
30
- },
31
- {
32
- table: "pending_actions",
33
- idCol: "id",
34
- columns: ["title", "detail", "verify_cmd"],
35
- select: "SELECT id, title, detail, verify_cmd, scope AS __project FROM pending_actions",
36
- },
37
- {
38
- table: "saved_threads",
39
- idCol: "name",
40
- columns: ["summary"],
41
- select: "SELECT name, summary, project_path AS __project FROM saved_threads",
42
- },
43
- ];
44
- // Heuristic labels are pattern-based guesses (KEY=value, tfstate blobs) that
45
- // frequently match benign env vars / file paths. Everything else is a structured,
46
- // high-confidence credential pattern.
47
- const HEURISTIC_LABELS = new Set(["kv-secret", "tfstate-value"]);
48
- function projectName(raw) {
49
- if (typeof raw !== "string" || !raw)
50
- return null;
51
- return raw.includes("/") ? basename(raw) : raw;
52
- }
53
- /** Scan every text cell for stored secrets. Deduped, confidence-tiered, project-attributed. */
54
- export function scanDbForSecrets(db) {
55
- const byKey = new Map();
56
- for (const target of TARGETS) {
57
- const rows = db.prepare(target.select).all();
58
- for (const row of rows) {
59
- const proj = projectName(row.__project);
60
- for (const col of target.columns) {
61
- const val = row[col];
62
- if (typeof val !== "string" || !val)
63
- continue;
64
- for (const f of findSecrets(val)) {
65
- const key = `${f.label} ${f.preview}`;
66
- let entry = byKey.get(key);
67
- if (!entry) {
68
- entry = {
69
- label: f.label,
70
- preview: f.preview,
71
- confidence: HEURISTIC_LABELS.has(f.label) ? "heuristic" : "high",
72
- count: 0,
73
- sample: `${target.table}#${row[target.idCol]}.${col}`,
74
- projects: [],
75
- _projects: new Set(),
76
- };
77
- byKey.set(key, entry);
78
- }
79
- entry.count++;
80
- if (proj)
81
- entry._projects.add(proj);
82
- }
83
- }
84
- }
85
- }
86
- return [...byKey.values()]
87
- .map(({ _projects, ...f }) => ({ ...f, projects: [..._projects].sort() }))
88
- .sort((a, b) => {
89
- if (a.confidence !== b.confidence)
90
- return a.confidence === "high" ? -1 : 1;
91
- return b.count - a.count;
92
- });
93
- }
94
- //# sourceMappingURL=scan%202.js.map