sandstream-kit 1.1.0 → 1.3.0

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 (129) 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/check-web-search.js +37 -6
  9. package/dist/check-web-search.js.map +1 -1
  10. package/dist/cli-shared.d.ts +4 -0
  11. package/dist/cli-shared.js +11 -0
  12. package/dist/cli-shared.js.map +1 -0
  13. package/dist/cli.js +175 -1189
  14. package/dist/cli.js.map +1 -1
  15. package/dist/commands/audit.d.ts +1 -0
  16. package/dist/commands/audit.js +99 -0
  17. package/dist/commands/audit.js.map +1 -0
  18. package/dist/commands/auth.d.ts +1 -0
  19. package/dist/commands/auth.js +121 -0
  20. package/dist/commands/auth.js.map +1 -0
  21. package/dist/commands/env.d.ts +1 -0
  22. package/dist/commands/env.js +149 -0
  23. package/dist/commands/env.js.map +1 -0
  24. package/dist/commands/hooks.d.ts +1 -0
  25. package/dist/commands/hooks.js +146 -0
  26. package/dist/commands/hooks.js.map +1 -0
  27. package/dist/commands/mcp.d.ts +1 -0
  28. package/dist/commands/mcp.js +120 -0
  29. package/dist/commands/mcp.js.map +1 -0
  30. package/dist/commands/memory.d.ts +1 -0
  31. package/dist/commands/memory.js +534 -0
  32. package/dist/commands/memory.js.map +1 -0
  33. package/dist/config.d.ts +2 -0
  34. package/dist/config.js +4 -0
  35. package/dist/config.js.map +1 -1
  36. package/dist/mcp-server.js +59 -6
  37. package/dist/mcp-server.js.map +1 -1
  38. package/dist/memory/amazonq.d.ts +5 -0
  39. package/dist/memory/amazonq.js +161 -0
  40. package/dist/memory/amazonq.js.map +1 -0
  41. package/dist/memory/cline.d.ts +5 -0
  42. package/dist/memory/cline.js +117 -0
  43. package/dist/memory/cline.js.map +1 -0
  44. package/dist/memory/codex.d.ts +5 -0
  45. package/dist/memory/codex.js +150 -0
  46. package/dist/memory/codex.js.map +1 -0
  47. package/dist/memory/continue.d.ts +5 -0
  48. package/dist/memory/continue.js +116 -0
  49. package/dist/memory/continue.js.map +1 -0
  50. package/dist/memory/cursor.d.ts +4 -0
  51. package/dist/memory/cursor.js +116 -0
  52. package/dist/memory/cursor.js.map +1 -0
  53. package/dist/memory/db.d.ts +12 -1
  54. package/dist/memory/db.js +43 -1
  55. package/dist/memory/db.js.map +1 -1
  56. package/dist/memory/gemini.d.ts +5 -0
  57. package/dist/memory/gemini.js +176 -0
  58. package/dist/memory/gemini.js.map +1 -0
  59. package/dist/memory/hook.d.ts +9 -0
  60. package/dist/memory/hook.js +34 -1
  61. package/dist/memory/hook.js.map +1 -1
  62. package/dist/memory/install.js +1 -0
  63. package/dist/memory/install.js.map +1 -1
  64. package/dist/memory/merge.d.ts +18 -0
  65. package/dist/memory/merge.js +109 -0
  66. package/dist/memory/merge.js.map +1 -0
  67. package/dist/memory/parser.d.ts +9 -0
  68. package/dist/memory/parser.js +40 -3
  69. package/dist/memory/parser.js.map +1 -1
  70. package/dist/memory/suggest.d.ts +21 -0
  71. package/dist/memory/suggest.js +36 -0
  72. package/dist/memory/suggest.js.map +1 -0
  73. package/dist/onepassword.js +1 -1
  74. package/dist/onepassword.js.map +1 -1
  75. package/dist/open.js +8 -2
  76. package/dist/open.js.map +1 -1
  77. package/dist/run.js +1 -1
  78. package/dist/run.js.map +1 -1
  79. package/dist/service-auth.d.ts +31 -0
  80. package/dist/service-auth.js +47 -0
  81. package/dist/service-auth.js.map +1 -0
  82. package/dist/stack-detector.js +53 -76
  83. package/dist/stack-detector.js.map +1 -1
  84. package/dist/status.d.ts +9 -0
  85. package/dist/status.js +119 -0
  86. package/dist/status.js.map +1 -0
  87. package/package.json +9 -4
  88. package/dist/memory/backup 2.d.ts +0 -6
  89. package/dist/memory/backup 2.js +0 -80
  90. package/dist/memory/backup 2.js.map +0 -1
  91. package/dist/memory/db 2.d.ts +0 -40
  92. package/dist/memory/db 2.js +0 -233
  93. package/dist/memory/db 2.js.map +0 -1
  94. package/dist/memory/hook 2.d.ts +0 -6
  95. package/dist/memory/hook 2.js +0 -51
  96. package/dist/memory/hook 2.js.map +0 -1
  97. package/dist/memory/hook.test 2.d.ts +0 -1
  98. package/dist/memory/hook.test 2.js +0 -35
  99. package/dist/memory/hook.test 2.js.map +0 -1
  100. package/dist/memory/install 2.d.ts +0 -8
  101. package/dist/memory/install 2.js +0 -72
  102. package/dist/memory/install 2.js.map +0 -1
  103. package/dist/memory/install.test 2.d.ts +0 -1
  104. package/dist/memory/install.test 2.js +0 -59
  105. package/dist/memory/install.test 2.js.map +0 -1
  106. package/dist/memory/pal 2.d.ts +0 -47
  107. package/dist/memory/pal 2.js +0 -154
  108. package/dist/memory/pal 2.js.map +0 -1
  109. package/dist/memory/project 2.d.ts +0 -1
  110. package/dist/memory/project 2.js +0 -24
  111. package/dist/memory/project 2.js.map +0 -1
  112. package/dist/memory/scan 2.d.ts +0 -15
  113. package/dist/memory/scan 2.js +0 -94
  114. package/dist/memory/scan 2.js.map +0 -1
  115. package/dist/memory/scan.test 2.d.ts +0 -1
  116. package/dist/memory/scan.test 2.js +0 -55
  117. package/dist/memory/scan.test 2.js.map +0 -1
  118. package/dist/memory/shared 2.d.ts +0 -33
  119. package/dist/memory/shared 2.js +0 -120
  120. package/dist/memory/shared 2.js.map +0 -1
  121. package/dist/memory/threads 2.d.ts +0 -37
  122. package/dist/memory/threads 2.js +0 -50
  123. package/dist/memory/threads 2.js.map +0 -1
  124. package/dist/memory/threads.test 2.d.ts +0 -1
  125. package/dist/memory/threads.test 2.js +0 -66
  126. package/dist/memory/threads.test 2.js.map +0 -1
  127. package/dist/memory/types 2.d.ts +0 -52
  128. package/dist/memory/types 2.js +0 -5
  129. package/dist/memory/types 2.js.map +0 -1
@@ -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
@@ -1 +0,0 @@
1
- {"version":3,"file":"scan 2.js","sourceRoot":"","sources":["../../src/memory/scan 2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAwBxD,MAAM,OAAO,GAAa;IACxB;QACE,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,CAAC,SAAS,CAAC;QACpB,MAAM,EAAE,oDAAoD;KAC7D;IACD;QACE,KAAK,EAAE,WAAW;QAClB,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,CAAC,YAAY,CAAC;QACvB,MAAM,EACJ,oFAAoF;YACpF,wEAAwE;KAC3E;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC;QAC1C,MAAM,EAAE,+EAA+E;KACxF;IACD;QACE,KAAK,EAAE,eAAe;QACtB,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,CAAC,SAAS,CAAC;QACpB,MAAM,EAAE,oEAAoE;KAC7E;CACF,CAAC;AAEF,6EAA6E;AAC7E,kFAAkF;AAClF,sCAAsC;AACtC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;AAEjE,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,gBAAgB,CAAC,EAAgB;IAC/C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoD,CAAC;IAC1E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAA+B,CAAC;QAC1E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBACrB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG;oBAAE,SAAS;gBAC9C,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;oBACtC,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,KAAK,GAAG;4BACN,KAAK,EAAE,CAAC,CAAC,KAAK;4BACd,OAAO,EAAE,CAAC,CAAC,OAAO;4BAClB,UAAU,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM;4BAChE,KAAK,EAAE,CAAC;4BACR,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE;4BACrD,QAAQ,EAAE,EAAE;4BACZ,SAAS,EAAE,IAAI,GAAG,EAAU;yBAC7B,CAAC;wBACF,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBACxB,CAAC;oBACD,KAAK,CAAC,KAAK,EAAE,CAAC;oBACd,IAAI,IAAI;wBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;SACzE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU;YAAE,OAAO,CAAC,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,55 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { openMemoryDb, upsertSession, insertMessage } from "./db.js";
4
- import { scanDbForSecrets } from "./scan.js";
5
- describe("memory secret-scan", () => {
6
- it("flags a stored secret (masked, high-confidence) and locates it", () => {
7
- const db = openMemoryDb(":memory:");
8
- upsertSession(db, { sessionId: "s1", harness: "claude-code" });
9
- const fake = "sk_live_" + "A".repeat(24); // synthetic, non-real
10
- insertMessage(db, { uuid: "u1", sessionId: "s1", type: "user", content: `the key is ${fake}` });
11
- insertMessage(db, { uuid: "u2", sessionId: "s1", type: "user", content: "totally clean message" });
12
- const findings = scanDbForSecrets(db);
13
- assert.equal(findings.length, 1);
14
- assert.equal(findings[0]?.label, "stripe-key");
15
- assert.equal(findings[0]?.confidence, "high");
16
- assert.equal(findings[0]?.count, 1);
17
- assert.match(findings[0]?.sample ?? "", /^messages#\d+\.content$/);
18
- assert.ok(!findings[0]?.preview.includes("A".repeat(24)), "preview is masked, not the raw secret");
19
- db.close();
20
- });
21
- it("dedupes the same secret across rows with an occurrence count", () => {
22
- const db = openMemoryDb(":memory:");
23
- upsertSession(db, { sessionId: "s1", harness: "claude-code" });
24
- const fake = "sk_live_" + "B".repeat(24);
25
- insertMessage(db, { uuid: "u1", sessionId: "s1", type: "user", content: `key ${fake}` });
26
- insertMessage(db, { uuid: "u2", sessionId: "s1", type: "user", content: `again ${fake}` });
27
- const findings = scanDbForSecrets(db);
28
- assert.equal(findings.length, 1, "one unique finding, not two");
29
- assert.equal(findings[0]?.count, 2);
30
- db.close();
31
- });
32
- it("attributes a finding to the project it leaked in (via cwd)", () => {
33
- const db = openMemoryDb(":memory:");
34
- upsertSession(db, { sessionId: "s1", harness: "claude-code" });
35
- const fake = "sk_live_" + "C".repeat(24);
36
- insertMessage(db, {
37
- uuid: "u1",
38
- sessionId: "s1",
39
- type: "user",
40
- content: `key ${fake}`,
41
- cwd: "/Users/me/dev/app-a",
42
- });
43
- const findings = scanDbForSecrets(db);
44
- assert.deepEqual(findings[0]?.projects, ["app-a"]);
45
- db.close();
46
- });
47
- it("returns nothing for a clean db", () => {
48
- const db = openMemoryDb(":memory:");
49
- upsertSession(db, { sessionId: "s1", harness: "claude-code" });
50
- insertMessage(db, { uuid: "u1", sessionId: "s1", type: "user", content: "no secrets here" });
51
- assert.deepEqual(scanDbForSecrets(db), []);
52
- db.close();
53
- });
54
- });
55
- //# sourceMappingURL=scan.test%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scan.test 2.js","sourceRoot":"","sources":["../../src/memory/scan.test 2.ts"],"names":[],"mappings":"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"}
@@ -1,33 +0,0 @@
1
- export type SharedKind = "decision" | "convention" | "how-built" | "status" | "security" | "note";
2
- export interface SharedEntry {
3
- id: string;
4
- area: string;
5
- kind: SharedKind;
6
- title: string;
7
- body: string;
8
- refs: string[];
9
- author: string;
10
- ts: string;
11
- source_ref?: string;
12
- }
13
- export interface ShareInput {
14
- area: string;
15
- kind: SharedKind;
16
- title: string;
17
- body: string;
18
- refs?: string[];
19
- }
20
- export declare function getSharedPath(root: string): string;
21
- export declare function readShared(root: string): SharedEntry[];
22
- /**
23
- * Promote one entry into the shared store. Fail-closed: refuses (throws) if any
24
- * text field contains a secret. Only allow-listed fields are persisted — no raw
25
- * tool output / env dumps can sneak in. Author + source_ref give provenance.
26
- */
27
- export declare function shareEntry(root: string, input: ShareInput, now: string): SharedEntry;
28
- export declare function listAreas(root: string): {
29
- area: string;
30
- count: number;
31
- }[];
32
- export declare function queryArea(root: string, area: string): SharedEntry[];
33
- export declare function searchShared(root: string, query: string): SharedEntry[];
@@ -1,120 +0,0 @@
1
- /**
2
- * kit memory — shared project / responsibility-area memory (the curated tier).
3
- *
4
- * This is CONTEXT, not raw memory: durable, curated, intentional knowledge that
5
- * is safe to share with the team and travels with the repo. Treated LIKE CODE:
6
- * - committed TEXT (.kit/shared/memory.jsonl) → diffable, PR-reviewable, gitleaks-scannable;
7
- * - deny-by-default — nothing is auto-shared, you promote entries explicitly;
8
- * - allow-listed schema — only safe fields (no raw dumps);
9
- * - fail-closed secret-scan on write (reuses kit's SECRET_PATTERNS);
10
- * - provenance + receipts (author + source_ref) so colleagues can trust it.
11
- *
12
- * Organized by `area` (e.g. "stripe", "whatsapp", "plugins") so a growing system
13
- * stays navigable: "how did we build X, what's next, is it secure?" = that area's
14
- * entries (with receipts). Entries are few (curated) → plain JSONL + JS query; no
15
- * second database. Querying never calls a model.
16
- */
17
- import { randomBytes } from "node:crypto";
18
- import { execFileSync } from "node:child_process";
19
- import { existsSync, readFileSync, appendFileSync, mkdirSync } from "node:fs";
20
- import { join, dirname } from "node:path";
21
- import { findSecrets } from "../utils/redactSecrets.js";
22
- export function getSharedPath(root) {
23
- return join(root, ".kit", "shared", "memory.jsonl");
24
- }
25
- function gitAuthor(root) {
26
- const read = (key) => {
27
- try {
28
- return execFileSync("git", ["config", key], {
29
- cwd: root,
30
- encoding: "utf8",
31
- stdio: ["ignore", "pipe", "ignore"],
32
- }).trim();
33
- }
34
- catch {
35
- return "";
36
- }
37
- };
38
- const name = read("user.name");
39
- const email = read("user.email");
40
- if (name && email)
41
- return `${name} <${email}>`;
42
- return name || email || "unknown";
43
- }
44
- function gitHead(root) {
45
- try {
46
- const sha = execFileSync("git", ["rev-parse", "--short", "HEAD"], {
47
- cwd: root,
48
- encoding: "utf8",
49
- stdio: ["ignore", "pipe", "ignore"],
50
- }).trim();
51
- return sha || undefined;
52
- }
53
- catch {
54
- return undefined;
55
- }
56
- }
57
- export function readShared(root) {
58
- const path = getSharedPath(root);
59
- if (!existsSync(path))
60
- return [];
61
- const out = [];
62
- for (const line of readFileSync(path, "utf8").split("\n")) {
63
- const t = line.trim();
64
- if (!t)
65
- continue;
66
- try {
67
- out.push(JSON.parse(t));
68
- }
69
- catch {
70
- // skip malformed lines, keep the rest readable
71
- }
72
- }
73
- return out;
74
- }
75
- /**
76
- * Promote one entry into the shared store. Fail-closed: refuses (throws) if any
77
- * text field contains a secret. Only allow-listed fields are persisted — no raw
78
- * tool output / env dumps can sneak in. Author + source_ref give provenance.
79
- */
80
- export function shareEntry(root, input, now) {
81
- const refs = input.refs ?? [];
82
- const scanned = [input.title, input.body, ...refs].join("\n");
83
- const found = findSecrets(scanned);
84
- if (found.length) {
85
- throw new Error(`refused: entry contains ${found.length} secret(s) (${found
86
- .map((f) => f.label)
87
- .join(", ")}) — shared memory must be secret-clean`);
88
- }
89
- const entry = {
90
- id: randomBytes(3).toString("hex"),
91
- area: input.area,
92
- kind: input.kind,
93
- title: input.title,
94
- body: input.body,
95
- refs,
96
- author: gitAuthor(root),
97
- ts: now,
98
- source_ref: gitHead(root),
99
- };
100
- const path = getSharedPath(root);
101
- mkdirSync(dirname(path), { recursive: true });
102
- appendFileSync(path, JSON.stringify(entry) + "\n");
103
- return entry;
104
- }
105
- export function listAreas(root) {
106
- const counts = new Map();
107
- for (const e of readShared(root))
108
- counts.set(e.area, (counts.get(e.area) ?? 0) + 1);
109
- return [...counts.entries()]
110
- .map(([area, count]) => ({ area, count }))
111
- .sort((a, b) => a.area.localeCompare(b.area));
112
- }
113
- export function queryArea(root, area) {
114
- return readShared(root).filter((e) => e.area === area);
115
- }
116
- export function searchShared(root, query) {
117
- const q = query.toLowerCase();
118
- return readShared(root).filter((e) => e.title.toLowerCase().includes(q) || e.body.toLowerCase().includes(q));
119
- }
120
- //# sourceMappingURL=shared%202.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared 2.js","sourceRoot":"","sources":["../../src/memory/shared 2.ts"],"names":[],"mappings":"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"}
@@ -1,37 +0,0 @@
1
- /**
2
- * kit memory — named copilots (saved threads).
3
- *
4
- * Claude Code's resume list labels sessions by the first message you happened to
5
- * type, so the thread you want is unfindable. Here you bookmark the threads worth
6
- * keeping under a real name ("a fleet of named copilots"); a small curated list
7
- * replaces the scrap heap. Scoped per project by default (the personal store holds
8
- * all projects; this just filters). Pure read/write — no model calls.
9
- */
10
- import type { DatabaseSync } from "node:sqlite";
11
- export interface SavedThread {
12
- name: string;
13
- session_id: string;
14
- summary: string | null;
15
- project_path: string | null;
16
- saved_at: string | null;
17
- }
18
- export interface SaveThreadInput {
19
- name: string;
20
- sessionId: string;
21
- summary?: string;
22
- projectPath?: string;
23
- }
24
- export declare function saveThread(db: DatabaseSync, input: SaveThreadInput): void;
25
- export declare function listThreads(db: DatabaseSync, opts?: {
26
- projectPath?: string;
27
- }): SavedThread[];
28
- export declare function getThread(db: DatabaseSync, name: string): SavedThread | undefined;
29
- export declare function removeThread(db: DatabaseSync, name: string): boolean;
30
- /** Most recent session that touched this project (by message timestamp). */
31
- export declare function latestSessionId(db: DatabaseSync, opts?: {
32
- projectPath?: string;
33
- }): string | undefined;
34
- /** Resolve a thread by name, or by 1-based index into the (scoped) list. */
35
- export declare function resolveThread(db: DatabaseSync, ref: string, opts?: {
36
- projectPath?: string;
37
- }): SavedThread | undefined;