@pcircle/footprint 1.3.0 → 1.5.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 (134) hide show
  1. package/README.md +136 -160
  2. package/SKILL.md +7 -7
  3. package/dist/src/analyzers/content-analyzer.d.ts.map +1 -1
  4. package/dist/src/analyzers/content-analyzer.js +20 -4
  5. package/dist/src/analyzers/content-analyzer.js.map +1 -1
  6. package/dist/src/cli/index.js +0 -0
  7. package/dist/src/cli/setup.d.ts.map +1 -1
  8. package/dist/src/cli/setup.js +34 -12
  9. package/dist/src/cli/setup.js.map +1 -1
  10. package/dist/src/cli/utils/env.d.ts +7 -2
  11. package/dist/src/cli/utils/env.d.ts.map +1 -1
  12. package/dist/src/cli/utils/env.js +37 -6
  13. package/dist/src/cli/utils/env.js.map +1 -1
  14. package/dist/src/index.d.ts +0 -1
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +41 -28
  17. package/dist/src/index.js.map +1 -1
  18. package/dist/src/lib/crypto/decrypt.d.ts.map +1 -1
  19. package/dist/src/lib/crypto/decrypt.js +12 -8
  20. package/dist/src/lib/crypto/decrypt.js.map +1 -1
  21. package/dist/src/lib/crypto/encrypt.d.ts.map +1 -1
  22. package/dist/src/lib/crypto/encrypt.js +6 -3
  23. package/dist/src/lib/crypto/encrypt.js.map +1 -1
  24. package/dist/src/lib/crypto/key-derivation.d.ts +1 -1
  25. package/dist/src/lib/crypto/key-derivation.d.ts.map +1 -1
  26. package/dist/src/lib/crypto/key-derivation.js +11 -11
  27. package/dist/src/lib/crypto/key-derivation.js.map +1 -1
  28. package/dist/src/lib/storage/database.d.ts +46 -3
  29. package/dist/src/lib/storage/database.d.ts.map +1 -1
  30. package/dist/src/lib/storage/database.js +175 -80
  31. package/dist/src/lib/storage/database.js.map +1 -1
  32. package/dist/src/lib/storage/export.d.ts +1 -2
  33. package/dist/src/lib/storage/export.d.ts.map +1 -1
  34. package/dist/src/lib/storage/export.js +46 -33
  35. package/dist/src/lib/storage/export.js.map +1 -1
  36. package/dist/src/lib/storage/salt-storage.d.ts +1 -1
  37. package/dist/src/lib/storage/salt-storage.d.ts.map +1 -1
  38. package/dist/src/lib/storage/salt-storage.js +26 -18
  39. package/dist/src/lib/storage/salt-storage.js.map +1 -1
  40. package/dist/src/lib/storage/schema.d.ts +1 -1
  41. package/dist/src/lib/storage/schema.d.ts.map +1 -1
  42. package/dist/src/lib/storage/schema.js +29 -47
  43. package/dist/src/lib/storage/schema.js.map +1 -1
  44. package/dist/src/lib/tool-wrapper.d.ts.map +1 -1
  45. package/dist/src/lib/tool-wrapper.js +2 -2
  46. package/dist/src/lib/tool-wrapper.js.map +1 -1
  47. package/dist/src/prompts/skill-prompt.d.ts +6 -0
  48. package/dist/src/prompts/skill-prompt.d.ts.map +1 -0
  49. package/dist/src/prompts/skill-prompt.js +125 -0
  50. package/dist/src/prompts/skill-prompt.js.map +1 -0
  51. package/dist/src/tools/capture-footprint.d.ts +2 -2
  52. package/dist/src/tools/capture-footprint.d.ts.map +1 -1
  53. package/dist/src/tools/capture-footprint.js +52 -11
  54. package/dist/src/tools/capture-footprint.js.map +1 -1
  55. package/dist/src/tools/delete-footprints.d.ts +18 -1
  56. package/dist/src/tools/delete-footprints.d.ts.map +1 -1
  57. package/dist/src/tools/delete-footprints.js +53 -5
  58. package/dist/src/tools/delete-footprints.js.map +1 -1
  59. package/dist/src/tools/export-footprints.d.ts +11 -3
  60. package/dist/src/tools/export-footprints.d.ts.map +1 -1
  61. package/dist/src/tools/export-footprints.js +48 -9
  62. package/dist/src/tools/export-footprints.js.map +1 -1
  63. package/dist/src/tools/get-footprint.d.ts +1 -7
  64. package/dist/src/tools/get-footprint.d.ts.map +1 -1
  65. package/dist/src/tools/get-footprint.js +7 -3
  66. package/dist/src/tools/get-footprint.js.map +1 -1
  67. package/dist/src/tools/index.d.ts +1 -3
  68. package/dist/src/tools/index.d.ts.map +1 -1
  69. package/dist/src/tools/index.js +1 -3
  70. package/dist/src/tools/index.js.map +1 -1
  71. package/dist/src/tools/list-footprints.d.ts +1 -15
  72. package/dist/src/tools/list-footprints.d.ts.map +1 -1
  73. package/dist/src/tools/list-footprints.js +17 -6
  74. package/dist/src/tools/list-footprints.js.map +1 -1
  75. package/dist/src/tools/manage-tags.d.ts +47 -0
  76. package/dist/src/tools/manage-tags.d.ts.map +1 -0
  77. package/dist/src/tools/manage-tags.js +109 -0
  78. package/dist/src/tools/manage-tags.js.map +1 -0
  79. package/dist/src/tools/search-footprints.d.ts +2 -16
  80. package/dist/src/tools/search-footprints.d.ts.map +1 -1
  81. package/dist/src/tools/search-footprints.js +23 -7
  82. package/dist/src/tools/search-footprints.js.map +1 -1
  83. package/dist/src/tools/suggest-capture.d.ts +1 -1
  84. package/dist/src/tools/suggest-capture.d.ts.map +1 -1
  85. package/dist/src/tools/suggest-capture.js +6 -2
  86. package/dist/src/tools/suggest-capture.js.map +1 -1
  87. package/dist/src/tools/verify-footprint.d.ts +7 -54
  88. package/dist/src/tools/verify-footprint.d.ts.map +1 -1
  89. package/dist/src/tools/verify-footprint.js +11 -8
  90. package/dist/src/tools/verify-footprint.js.map +1 -1
  91. package/dist/src/types.d.ts +4 -4
  92. package/dist/src/types.d.ts.map +1 -1
  93. package/dist/src/ui/register.js +1 -1
  94. package/dist/src/ui/register.js.map +1 -1
  95. package/dist/ui/dashboard.html +80 -67
  96. package/dist/ui/detail.html +62 -49
  97. package/dist/ui/export.html +64 -51
  98. package/package.json +18 -13
  99. package/dist/src/lib/errors/base-error.d.ts +0 -15
  100. package/dist/src/lib/errors/base-error.d.ts.map +0 -1
  101. package/dist/src/lib/errors/base-error.js +0 -34
  102. package/dist/src/lib/errors/base-error.js.map +0 -1
  103. package/dist/src/lib/errors/crypto-error.d.ts +0 -29
  104. package/dist/src/lib/errors/crypto-error.d.ts.map +0 -1
  105. package/dist/src/lib/errors/crypto-error.js +0 -43
  106. package/dist/src/lib/errors/crypto-error.js.map +0 -1
  107. package/dist/src/lib/errors/index.d.ts +0 -26
  108. package/dist/src/lib/errors/index.d.ts.map +0 -1
  109. package/dist/src/lib/errors/index.js +0 -26
  110. package/dist/src/lib/errors/index.js.map +0 -1
  111. package/dist/src/lib/errors/storage-error.d.ts +0 -25
  112. package/dist/src/lib/errors/storage-error.d.ts.map +0 -1
  113. package/dist/src/lib/errors/storage-error.js +0 -38
  114. package/dist/src/lib/errors/storage-error.js.map +0 -1
  115. package/dist/src/lib/errors/validation-error.d.ts +0 -21
  116. package/dist/src/lib/errors/validation-error.d.ts.map +0 -1
  117. package/dist/src/lib/errors/validation-error.js +0 -29
  118. package/dist/src/lib/errors/validation-error.js.map +0 -1
  119. package/dist/src/test-helpers.d.ts +0 -33
  120. package/dist/src/test-helpers.d.ts.map +0 -1
  121. package/dist/src/test-helpers.js +0 -108
  122. package/dist/src/test-helpers.js.map +0 -1
  123. package/dist/src/tools/get-tag-stats.d.ts +0 -30
  124. package/dist/src/tools/get-tag-stats.d.ts.map +0 -1
  125. package/dist/src/tools/get-tag-stats.js +0 -33
  126. package/dist/src/tools/get-tag-stats.js.map +0 -1
  127. package/dist/src/tools/remove-tag.d.ts +0 -22
  128. package/dist/src/tools/remove-tag.d.ts.map +0 -1
  129. package/dist/src/tools/remove-tag.js +0 -30
  130. package/dist/src/tools/remove-tag.js.map +0 -1
  131. package/dist/src/tools/rename-tag.d.ts +0 -24
  132. package/dist/src/tools/rename-tag.d.ts.map +0 -1
  133. package/dist/src/tools/rename-tag.js +0 -34
  134. package/dist/src/tools/rename-tag.js.map +0 -1
@@ -8,26 +8,32 @@
8
8
  */
9
9
  export function storeSalt(db, salt) {
10
10
  if (salt.length !== 16) {
11
- throw new Error('Salt must be 16 bytes');
11
+ throw new Error("Salt must be 16 bytes");
12
12
  }
13
13
  try {
14
- // Check if salt already exists (should only be set once)
15
- const existing = db.prepare('SELECT id FROM crypto_keys WHERE id = 1').get();
16
- if (existing) {
17
- throw new Error('Salt already exists in database');
18
- }
19
- // Store salt (id=1 ensures singleton via PRIMARY KEY constraint)
20
- const stmt = db.prepare(`
21
- INSERT INTO crypto_keys (id, salt)
22
- VALUES (1, ?)
23
- `);
24
- stmt.run(Buffer.from(salt));
14
+ // Atomic check-and-insert within a transaction to prevent TOCTOU race
15
+ const insertSalt = db.transaction(() => {
16
+ const existing = db
17
+ .prepare("SELECT id FROM crypto_keys WHERE id = 1")
18
+ .get();
19
+ if (existing) {
20
+ throw new Error("Salt already exists in database");
21
+ }
22
+ // Store salt (id=1 ensures singleton via PRIMARY KEY + CHECK constraint)
23
+ const stmt = db.prepare(`
24
+ INSERT INTO crypto_keys (id, salt)
25
+ VALUES (1, ?)
26
+ `);
27
+ stmt.run(Buffer.from(salt));
28
+ });
29
+ insertSalt();
25
30
  }
26
31
  catch (error) {
27
- if (error instanceof Error && error.message === 'Salt already exists in database') {
32
+ if (error instanceof Error &&
33
+ error.message === "Salt already exists in database") {
28
34
  throw error;
29
35
  }
30
- throw new Error(`Failed to store salt: ${error instanceof Error ? error.message : 'Unknown error'}`);
36
+ throw new Error(`Failed to store salt: ${error instanceof Error ? error.message : "Unknown error"}`);
31
37
  }
32
38
  }
33
39
  /**
@@ -38,14 +44,16 @@ export function storeSalt(db, salt) {
38
44
  */
39
45
  export function retrieveSalt(db) {
40
46
  try {
41
- const row = db.prepare('SELECT salt FROM crypto_keys WHERE id = 1').get();
47
+ const row = db
48
+ .prepare("SELECT salt FROM crypto_keys WHERE id = 1")
49
+ .get();
42
50
  if (!row) {
43
51
  return null;
44
52
  }
45
53
  return new Uint8Array(row.salt);
46
54
  }
47
55
  catch (error) {
48
- throw new Error(`Failed to retrieve salt: ${error instanceof Error ? error.message : 'Unknown error'}`);
56
+ throw new Error(`Failed to retrieve salt: ${error instanceof Error ? error.message : "Unknown error"}`);
49
57
  }
50
58
  }
51
59
  /**
@@ -56,10 +64,10 @@ export function retrieveSalt(db) {
56
64
  */
57
65
  export function hasSalt(db) {
58
66
  try {
59
- const row = db.prepare('SELECT id FROM crypto_keys WHERE id = 1').get();
67
+ const row = db.prepare("SELECT id FROM crypto_keys WHERE id = 1").get();
60
68
  return row !== undefined;
61
69
  }
62
- catch (error) {
70
+ catch {
63
71
  return false;
64
72
  }
65
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"salt-storage.js","sourceRoot":"","sources":["../../../../src/lib/storage/salt-storage.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,EAAqB,EAAE,IAAgB;IAC/D,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC;QACH,yDAAyD;QACzD,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAAE,CAAC;QAC7E,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,iEAAiE;QACjE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;KAGvB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,iCAAiC,EAAE,CAAC;YAClF,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,EAAkC,CAAC;QAC1G,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1G,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EAAqB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAAE,CAAC;QACxE,OAAO,GAAG,KAAK,SAAS,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"salt-storage.js","sourceRoot":"","sources":["../../../../src/lib/storage/salt-storage.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,EAAqB,EAAE,IAAgB;IAC/D,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC;QACH,sEAAsE;QACtE,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YACrC,MAAM,QAAQ,GAAG,EAAE;iBAChB,OAAO,CAAC,yCAAyC,CAAC;iBAClD,GAAG,EAAE,CAAC;YACT,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACrD,CAAC;YAED,yEAAyE;YACzE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;OAGvB,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,UAAU,EAAE,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK,YAAY,KAAK;YACtB,KAAK,CAAC,OAAO,KAAK,iCAAiC,EACnD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,KAAK,CACb,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CAAC,2CAA2C,CAAC;aACpD,GAAG,EAAkC,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,4BAA4B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACvF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EAAqB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAAE,CAAC;QACxE,OAAO,GAAG,KAAK,SAAS,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import type Database from 'better-sqlite3';
1
+ import type Database from "better-sqlite3";
2
2
  /**
3
3
  * Creates the database schema (tables and indexes)
4
4
  * This function is idempotent - safe to run multiple times
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAuExD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CA2C3D"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CA8DxD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAoD3D"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Current schema version
3
3
  */
4
- const SCHEMA_VERSION = '1';
4
+ const SCHEMA_VERSION = "1";
5
5
  /**
6
6
  * Creates the database schema (tables and indexes)
7
7
  * This function is idempotent - safe to run multiple times
@@ -9,16 +9,16 @@ const SCHEMA_VERSION = '1';
9
9
  * @param db - SQLite database instance
10
10
  */
11
11
  export function createSchema(db) {
12
- try {
13
- // Enable WAL mode for better concurrency and crash safety
14
- db.pragma('journal_mode = WAL');
15
- // NORMAL synchronous is safe with WAL and much faster
16
- db.pragma('synchronous = NORMAL');
17
- // Wait 5 seconds before returning SQLITE_BUSY error
18
- db.pragma('busy_timeout = 5000');
19
- // Enable foreign key constraints
20
- db.pragma('foreign_keys = ON');
21
- // Create evidences table
12
+ // Note: No try/catch here — on failure, the caller (EvidenceDatabase constructor)
13
+ // owns the db lifecycle and handles cleanup. Previously this function closed the db
14
+ // on error, causing a double-close when the constructor's catch also called db.close().
15
+ // Pragmas must be set outside transactions
16
+ db.pragma("journal_mode = WAL");
17
+ db.pragma("synchronous = NORMAL");
18
+ db.pragma("busy_timeout = 5000");
19
+ db.pragma("foreign_keys = ON");
20
+ // Wrap DDL + DML in transaction for atomicity (prevents partial schema on failure)
21
+ const initSchema = db.transaction(() => {
22
22
  db.exec(`
23
23
  CREATE TABLE IF NOT EXISTS evidences (
24
24
  id TEXT PRIMARY KEY,
@@ -36,14 +36,12 @@ export function createSchema(db) {
36
36
  updatedAt TEXT NOT NULL DEFAULT (datetime('now'))
37
37
  );
38
38
  `);
39
- // Create metadata table for schema versioning and configuration
40
39
  db.exec(`
41
40
  CREATE TABLE IF NOT EXISTS metadata (
42
41
  key TEXT PRIMARY KEY,
43
42
  value TEXT NOT NULL
44
43
  );
45
44
  `);
46
- // Create crypto_keys table for master salt storage
47
45
  db.exec(`
48
46
  CREATE TABLE IF NOT EXISTS crypto_keys (
49
47
  id INTEGER PRIMARY KEY CHECK (id = 1),
@@ -51,28 +49,12 @@ export function createSchema(db) {
51
49
  createdAt TEXT NOT NULL DEFAULT (datetime('now'))
52
50
  );
53
51
  `);
54
- // Create indexes for common queries
55
- db.exec(`
56
- CREATE INDEX IF NOT EXISTS idx_timestamp ON evidences(timestamp);
57
- `);
58
- db.exec(`
59
- CREATE INDEX IF NOT EXISTS idx_conversation_id ON evidences(conversationId);
60
- `);
61
- db.exec(`
62
- CREATE INDEX IF NOT EXISTS idx_content_hash ON evidences(contentHash);
63
- `);
64
- // Set schema version (use INSERT OR IGNORE to make it idempotent)
65
- const stmt = db.prepare(`
66
- INSERT OR IGNORE INTO metadata (key, value)
67
- VALUES ('schema_version', ?)
68
- `);
69
- stmt.run(SCHEMA_VERSION);
70
- }
71
- catch (error) {
72
- // Clean up database connection on failure to prevent resource leaks
73
- db.close();
74
- throw error;
75
- }
52
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_timestamp ON evidences(timestamp);`);
53
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_conversation_id ON evidences(conversationId);`);
54
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_content_hash ON evidences(contentHash);`);
55
+ db.prepare(`INSERT OR IGNORE INTO metadata (key, value) VALUES ('schema_version', ?)`).run(SCHEMA_VERSION);
56
+ });
57
+ initSchema();
76
58
  }
77
59
  /**
78
60
  * Verifies that the database schema is valid
@@ -84,31 +66,31 @@ export function createSchema(db) {
84
66
  export function verifySchema(db) {
85
67
  try {
86
68
  // Check if evidences table exists
87
- const evidencesTableInfo = db.pragma('table_info(evidences)');
69
+ const evidencesTableInfo = db.pragma("table_info(evidences)");
88
70
  if (!evidencesTableInfo || evidencesTableInfo.length === 0) {
89
71
  return false;
90
72
  }
91
73
  // Check if metadata table exists
92
- const metadataTableInfo = db.pragma('table_info(metadata)');
74
+ const metadataTableInfo = db.pragma("table_info(metadata)");
93
75
  if (!metadataTableInfo || metadataTableInfo.length === 0) {
94
76
  return false;
95
77
  }
96
78
  // Check if crypto_keys table exists
97
- const cryptoKeysTableInfo = db.pragma('table_info(crypto_keys)');
79
+ const cryptoKeysTableInfo = db.pragma("table_info(crypto_keys)");
98
80
  if (!cryptoKeysTableInfo || cryptoKeysTableInfo.length === 0) {
99
81
  return false;
100
82
  }
101
83
  // Verify required columns exist in evidences table
102
84
  const evidencesColumns = evidencesTableInfo.map((col) => col.name);
103
85
  const requiredColumns = [
104
- 'id',
105
- 'timestamp',
106
- 'encryptedContent',
107
- 'nonce',
108
- 'contentHash',
109
- 'messageCount',
110
- 'createdAt',
111
- 'updatedAt'
86
+ "id",
87
+ "timestamp",
88
+ "encryptedContent",
89
+ "nonce",
90
+ "contentHash",
91
+ "messageCount",
92
+ "createdAt",
93
+ "updatedAt",
112
94
  ];
113
95
  for (const col of requiredColumns) {
114
96
  if (!evidencesColumns.includes(col)) {
@@ -117,7 +99,7 @@ export function verifySchema(db) {
117
99
  }
118
100
  return true;
119
101
  }
120
- catch (error) {
102
+ catch {
121
103
  return false;
122
104
  }
123
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,0DAA0D;QAC1D,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAChC,sDAAsD;QACtD,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAClC,oDAAoD;QACpD,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACjC,iCAAiC;QACjC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAE/B,yBAAyB;QACzB,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;KAgBP,CAAC,CAAC;QAEH,gEAAgE;QAChE,EAAE,CAAC,IAAI,CAAC;;;;;KAKP,CAAC,CAAC;QAEH,mDAAmD;QACnD,EAAE,CAAC,IAAI,CAAC;;;;;;KAMP,CAAC,CAAC;QAEH,oCAAoC;QACpC,EAAE,CAAC,IAAI,CAAC;;KAEP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CAAC;;KAEP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CAAC;;KAEP,CAAC,CAAC;QAEH,kEAAkE;QAClE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;KAGvB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oEAAoE;QACpE,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,kBAAkB,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAA0C,CAAC;QACvG,IAAI,CAAC,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,iCAAiC;QACjC,MAAM,iBAAiB,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAA0C,CAAC;QACrG,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,oCAAoC;QACpC,MAAM,mBAAmB,GAAG,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAA0C,CAAC;QAC1G,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mDAAmD;QACnD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,eAAe,GAAG;YACtB,IAAI;YACJ,WAAW;YACX,kBAAkB;YAClB,OAAO;YACP,aAAa;YACb,cAAc;YACd,WAAW;YACX,WAAW;SACZ,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,kFAAkF;IAClF,oFAAoF;IACpF,wFAAwF;IAExF,2CAA2C;IAC3C,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAClC,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IACjC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,mFAAmF;IACnF,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QACrC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;KAgBP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CAAC;;;;;KAKP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CAAC;;;;;;KAMP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CACL,mEAAmE,CACpE,CAAC;QACF,EAAE,CAAC,IAAI,CACL,8EAA8E,CAC/E,CAAC;QACF,EAAE,CAAC,IAAI,CACL,wEAAwE,CACzE,CAAC;QAEF,EAAE,CAAC,OAAO,CACR,0EAA0E,CAC3E,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,UAAU,EAAE,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,kBAAkB,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAG1D,CAAC;QACH,IAAI,CAAC,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,iCAAiC;QACjC,MAAM,iBAAiB,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAGxD,CAAC;QACH,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,oCAAoC;QACpC,MAAM,mBAAmB,GAAG,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAG7D,CAAC;QACH,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mDAAmD;QACnD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,eAAe,GAAG;YACtB,IAAI;YACJ,WAAW;YACX,kBAAkB;YAClB,OAAO;YACP,aAAa;YACb,cAAc;YACd,WAAW;YACX,WAAW;SACZ,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-wrapper.d.ts","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAC9C,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAC7C,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAWvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAClD,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,GACpC,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAW9B"}
1
+ {"version":3,"file":"tool-wrapper.d.ts","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAC9C,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAC7C,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAYvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAClD,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,GACpC,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAY9B"}
@@ -46,7 +46,7 @@ export function wrapToolHandler(toolName, suggestedAction, handler) {
46
46
  }
47
47
  catch (error) {
48
48
  const errorMessage = getErrorMessage(error);
49
- throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}`);
49
+ throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}`, { cause: error });
50
50
  }
51
51
  };
52
52
  }
@@ -66,7 +66,7 @@ export function wrapSyncToolHandler(toolName, suggestedAction, handler) {
66
66
  }
67
67
  catch (error) {
68
68
  const errorMessage = getErrorMessage(error);
69
- throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}`);
69
+ throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}`, { cause: error });
70
70
  }
71
71
  };
72
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool-wrapper.js","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,eAAuB,EACvB,OAA8C;IAE9C,OAAO,KAAK,EAAE,MAAe,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,eAAuB,EACvB,OAAqC;IAErC,OAAO,CAAC,MAAe,EAAE,EAAE;QACzB,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"tool-wrapper.js","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,eAAuB,EACvB,OAA8C;IAE9C,OAAO,KAAK,EAAE,MAAe,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,EAC3E,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,eAAuB,EACvB,OAAqC;IAErC,OAAO,CAAC,MAAe,EAAE,EAAE;QACzB,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,EAC3E,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Register all Footprint MCP prompts on the server.
4
+ */
5
+ export declare function registerSkillPrompts(server: McpServer): void;
6
+ //# sourceMappingURL=skill-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-prompt.d.ts","sourceRoot":"","sources":["../../../src/prompts/skill-prompt.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiDzE;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyF5D"}
@@ -0,0 +1,125 @@
1
+ import { fileURLToPath } from "url";
2
+ import * as path from "path";
3
+ import * as fs from "fs";
4
+ import * as z from "zod";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ /**
8
+ * Resolve SKILL.md from the package root.
9
+ * Handles both dev (src/prompts/) and built (dist/prompts/) paths.
10
+ */
11
+ function findSkillMd() {
12
+ const candidates = [
13
+ path.resolve(__dirname, "../../SKILL.md"), // from dist/prompts/ or src/prompts/
14
+ path.resolve(__dirname, "../../../SKILL.md"), // fallback
15
+ ];
16
+ for (const p of candidates) {
17
+ if (fs.existsSync(p))
18
+ return fs.readFileSync(p, "utf-8");
19
+ }
20
+ throw new Error("SKILL.md not found");
21
+ }
22
+ const QUICK_REFERENCE = `# Footprint Quick Reference
23
+
24
+ ## Decision Tree
25
+ Should I capture this conversation?
26
+ \u251C\u2500 User explicitly asked \u2192 YES (capture immediately)
27
+ \u251C\u2500 High-value content (IP/Legal/Business/Research/Compliance) \u2192 SUGGEST to user
28
+ \u251C\u2500 Casual chat/small talk \u2192 NO
29
+ \u2514\u2500 Uncertain \u2192 ASK user
30
+
31
+ ## Tool Selection
32
+ - Save conversation \u2192 capture-footprint
33
+ - Browse/overview \u2192 list-footprints
34
+ - Full content retrieval \u2192 get-footprint
35
+ - Find by query/tags/dates \u2192 search-footprints
36
+ - Legal/audit export \u2192 export-footprints
37
+ - Verify integrity \u2192 verify-footprint
38
+ - Tag management \u2192 manage-tags (stats/rename/remove)
39
+ - Keyword pre-filter \u2192 suggest-capture
40
+ - Semantic assessment \u2192 Use footprint-should-capture prompt
41
+
42
+ ## Tag Conventions
43
+ Format: 3-6 tags, comma-separated
44
+ Types: decision, milestone, research, review, approval
45
+ Domains: api, ui, database, security, legal, business
46
+ Status: draft, finalized, approved, rejected
47
+
48
+ ## conversationId Format
49
+ {topic-type}-{descriptive-name}-{YYYY-MM-DD}`;
50
+ /**
51
+ * Register all Footprint MCP prompts on the server.
52
+ */
53
+ export function registerSkillPrompts(server) {
54
+ const skillContent = findSkillMd();
55
+ // Full SKILL.md content
56
+ server.registerPrompt("footprint-skill", {
57
+ description: "Complete Footprint agent skill guide — decision tree, tool reference, best practices, error recovery, and workflow examples",
58
+ }, async () => ({
59
+ messages: [
60
+ {
61
+ role: "user",
62
+ content: { type: "text", text: skillContent },
63
+ },
64
+ ],
65
+ }));
66
+ // Condensed quick reference
67
+ server.registerPrompt("footprint-quick-ref", {
68
+ description: "Condensed quick reference for Footprint — decision tree, tool selection, tag conventions",
69
+ }, async () => ({
70
+ messages: [
71
+ {
72
+ role: "user",
73
+ content: { type: "text", text: QUICK_REFERENCE },
74
+ },
75
+ ],
76
+ }));
77
+ // Semantic capture decision framework
78
+ server.registerPrompt("footprint-should-capture", {
79
+ description: "Semantic decision framework for whether to capture a conversation as evidence. Provides structured criteria for the AI to assess, unlike suggest-capture which uses keyword matching.",
80
+ argsSchema: {
81
+ conversationSummary: z
82
+ .string()
83
+ .min(1, "Conversation summary cannot be empty")
84
+ .max(10000, "Conversation summary too long (max 10000 characters)")
85
+ .describe("Brief summary of the conversation content to evaluate"),
86
+ },
87
+ }, async ({ conversationSummary }) => ({
88
+ messages: [
89
+ {
90
+ role: "user",
91
+ content: {
92
+ type: "text",
93
+ text: `Evaluate whether this conversation should be captured as evidence using Footprint.
94
+
95
+ ## Conversation Summary
96
+ ${conversationSummary}
97
+
98
+ ## Decision Criteria
99
+ Rate each category 0-3 (0=none, 1=low, 2=medium, 3=high):
100
+
101
+ 1. **Intellectual Property Value**: Does it contain inventions, algorithms, novel approaches, patents, trade secrets?
102
+ 2. **Legal Significance**: Does it involve contracts, agreements, licenses, legal obligations, regulatory requirements?
103
+ 3. **Business Decision Impact**: Does it record decisions, approvals, milestones, deliverables, strategic direction?
104
+ 4. **Research Value**: Does it contain hypotheses, findings, experimental results, data analysis, methodology?
105
+ 5. **Compliance/Audit Need**: Does it need to be documented for audit trails, regulatory compliance, evidence preservation?
106
+
107
+ ## Decision Rules
108
+ - Any category >= 2 \u2192 RECOMMEND CAPTURE
109
+ - Multiple categories >= 1 \u2192 RECOMMEND CAPTURE
110
+ - All categories = 0 \u2192 DO NOT CAPTURE
111
+ - Uncertain \u2192 ASK USER
112
+
113
+ ## Response Format
114
+ Respond with:
115
+ - **Capture**: yes/no/ask
116
+ - **Confidence**: 0.0-1.0
117
+ - **Primary Reason**: One sentence
118
+ - **Suggested Tags**: comma-separated
119
+ - **Suggested conversationId**: {topic}-{descriptor}-{YYYY-MM-DD} format`,
120
+ },
121
+ },
122
+ ],
123
+ }));
124
+ }
125
+ //# sourceMappingURL=skill-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-prompt.js","sourceRoot":"","sources":["../../../src/prompts/skill-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAGzB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;;GAGG;AACH,SAAS,WAAW;IAClB,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,qCAAqC;QAChF,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,mBAAmB,CAAC,EAAE,WAAW;KAC1D,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;6CA2BqB,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;IAEnC,wBAAwB;IACxB,MAAM,CAAC,cAAc,CACnB,iBAAiB,EACjB;QACE,WAAW,EACT,6HAA6H;KAChI,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,YAAY,EAAE;aACvD;SACF;KACF,CAAC,CACH,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,cAAc,CACnB,qBAAqB,EACrB;QACE,WAAW,EACT,0FAA0F;KAC7F,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,EAAE;aAC1D;SACF;KACF,CAAC,CACH,CAAC;IAEF,sCAAsC;IACtC,MAAM,CAAC,cAAc,CACnB,0BAA0B,EAC1B;QACE,WAAW,EACT,uLAAuL;QACzL,UAAU,EAAE;YACV,mBAAmB,EAAE,CAAC;iBACnB,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,EAAE,sCAAsC,CAAC;iBAC9C,GAAG,CAAC,KAAK,EAAE,sDAAsD,CAAC;iBAClE,QAAQ,CAAC,uDAAuD,CAAC;SACrE;KACF,EACD,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE,CAAC,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;EAGhB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;yEAuBoD;iBAC9D;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -4,9 +4,9 @@ import type { CaptureEvidenceParams } from "../types.js";
4
4
  export declare const captureFootprintSchema: {
5
5
  inputSchema: {
6
6
  conversationId: z.ZodString;
7
- llmProvider: z.ZodString;
7
+ llmProvider: z.ZodDefault<z.ZodString>;
8
8
  content: z.ZodString;
9
- messageCount: z.ZodNumber;
9
+ messageCount: z.ZodOptional<z.ZodNumber>;
10
10
  tags: z.ZodOptional<z.ZodString>;
11
11
  };
12
12
  outputSchema: {
@@ -1 +1 @@
1
- {"version":3,"file":"capture-footprint.d.ts","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAKzB,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;CAkBlC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;CAGpC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,gBAAgB,EACpB,aAAa,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC;;;;;IAmFzC"}
1
+ {"version":3,"file":"capture-footprint.d.ts","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAKzB,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;CAyClC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;CAIpC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,gBAAgB,EACpB,aAAa,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC;;;;;IAyHzC"}
@@ -6,15 +6,28 @@ import { encrypt } from "../lib/crypto/index.js";
6
6
  import { getCurrentCommit, } from "../lib/storage/index.js";
7
7
  export const captureFootprintSchema = {
8
8
  inputSchema: {
9
- conversationId: z.string().describe("Conversation ID"),
9
+ conversationId: z
10
+ .string()
11
+ .max(500, "Conversation ID too long (max 500 chars)")
12
+ .describe("Unique conversation identifier. Recommended format: {topic}-{descriptor}-{YYYY-MM-DD} (e.g., api-auth-decision-2026-01-28)"),
10
13
  llmProvider: z
11
14
  .string()
12
- .describe("LLM provider name (e.g., Claude Sonnet 4.5)"),
15
+ .default("unknown")
16
+ .describe("LLM provider name (e.g., Claude Sonnet 4.5). Defaults to 'unknown' if not specified."),
13
17
  content: z
14
18
  .string()
15
- .describe("Conversation content (messages, prompts, responses)"),
16
- messageCount: z.number().int().positive().describe("Number of messages"),
17
- tags: z.string().optional().describe("Optional tags (comma-separated)"),
19
+ .max(10 * 1024 * 1024, "Content exceeds 10MB limit")
20
+ .describe("Full conversation text including both human and assistant messages. Include complete message history for accurate evidence preservation."),
21
+ messageCount: z
22
+ .number()
23
+ .int()
24
+ .positive()
25
+ .optional()
26
+ .describe("Number of messages in the conversation. If omitted, auto-calculated by counting conversation turn markers (Human:/Assistant:/User:/AI:/System:)."),
27
+ tags: z
28
+ .string()
29
+ .optional()
30
+ .describe("Comma-separated tags for categorization (e.g., 'ip,patent,decision'). Use 3-6 tags. Common types: decision, milestone, research, legal, compliance."),
18
31
  },
19
32
  outputSchema: {
20
33
  id: z.string(),
@@ -25,7 +38,7 @@ export const captureFootprintSchema = {
25
38
  };
26
39
  export const captureFootprintMetadata = {
27
40
  title: "Capture Footprint",
28
- description: "Capture and encrypt LLM conversation as footprint",
41
+ description: "Capture and encrypt an LLM conversation as a tamper-evident footprint. Use when: user explicitly asks to save, or high-value content detected (IP, legal, business, research, compliance). Creates encrypted record with SHA-256 hash and Git timestamp anchor.",
29
42
  };
30
43
  export function createCaptureFootprintHandler(db, getDerivedKey) {
31
44
  return wrapToolHandler("capture-footprint", "Check content is not empty, messageCount is positive, and tags format is valid.", async (params) => {
@@ -33,7 +46,14 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
33
46
  if (!params.content || params.content.trim().length === 0) {
34
47
  throw new Error("Content cannot be empty");
35
48
  }
36
- if (params.messageCount <= 0) {
49
+ const MAX_CONTENT_LENGTH = 10 * 1024 * 1024; // 10MB
50
+ if (params.content.length > MAX_CONTENT_LENGTH) {
51
+ throw new Error(`Content too large (${(params.content.length / (1024 * 1024)).toFixed(1)}MB). Maximum 10MB allowed.`);
52
+ }
53
+ if (params.conversationId.length > 500) {
54
+ throw new Error("Conversation ID too long (max 500 chars)");
55
+ }
56
+ if (params.messageCount !== undefined && params.messageCount <= 0) {
37
57
  throw new Error("Message count must be positive");
38
58
  }
39
59
  // eslint-disable-next-line no-control-regex
@@ -42,6 +62,8 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
42
62
  }
43
63
  // Validate and sanitize tags if provided
44
64
  if (params.tags) {
65
+ const MAX_TAG_LENGTH = 100;
66
+ const MAX_TAGS_COUNT = 20;
45
67
  const tags = params.tags
46
68
  .split(",")
47
69
  .map((t) => t.trim())
@@ -49,14 +71,33 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
49
71
  if (tags.length === 0) {
50
72
  throw new Error("All provided tags are empty or whitespace");
51
73
  }
74
+ if (tags.length > MAX_TAGS_COUNT) {
75
+ throw new Error(`Too many tags (${tags.length}). Maximum ${MAX_TAGS_COUNT} tags allowed.`);
76
+ }
52
77
  for (const tag of tags) {
78
+ if (tag.length > MAX_TAG_LENGTH) {
79
+ throw new Error(`Tag too long (${tag.length} chars). Maximum ${MAX_TAG_LENGTH} characters per tag.`);
80
+ }
53
81
  // eslint-disable-next-line no-control-regex
54
82
  if (/[\x00\n\r,]/.test(tag)) {
55
83
  throw new Error(`Invalid tag format: "${tag}". Tags cannot contain null bytes, newlines, or commas.`);
56
84
  }
57
85
  }
58
- params.tags = tags.join(",");
86
+ // Use sanitized tags without mutating original params
87
+ params = { ...params, tags: tags.join(",") };
88
+ }
89
+ // Auto-calculate messageCount if not provided
90
+ let messageCount = params.messageCount;
91
+ if (!messageCount) {
92
+ const turnPattern = /^(Human|Assistant|User|System|AI):/im;
93
+ const lines = params.content.split("\n");
94
+ messageCount = lines.filter((line) => turnPattern.test(line.trim())).length;
95
+ if (messageCount === 0)
96
+ messageCount = 1; // Default to 1 if no turns detected
59
97
  }
98
+ // Apply runtime defaults for parameters with Zod schema defaults
99
+ // (Zod defaults only apply through MCP SDK transport layer)
100
+ const llmProvider = params.llmProvider || "unknown";
60
101
  // Encrypt and capture
61
102
  const key = await getDerivedKey();
62
103
  const encrypted = await encrypt(params.content, key);
@@ -69,11 +110,11 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
69
110
  const id = db.create({
70
111
  timestamp,
71
112
  conversationId: params.conversationId,
72
- llmProvider: params.llmProvider,
113
+ llmProvider,
73
114
  encryptedContent: encrypted.ciphertext,
74
115
  nonce: encrypted.nonce,
75
116
  contentHash,
76
- messageCount: params.messageCount,
117
+ messageCount,
77
118
  gitCommitHash: gitInfo?.commitHash || null,
78
119
  gitTimestamp: gitInfo?.timestamp || null,
79
120
  tags: params.tags || null,
@@ -82,7 +123,7 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
82
123
  ID: id,
83
124
  Timestamp: timestamp,
84
125
  "Git Commit": gitInfo?.commitHash || "N/A",
85
- "Message Count": params.messageCount,
126
+ "Message Count": messageCount,
86
127
  }, {
87
128
  id,
88
129
  timestamp,
@@ -1 +1 @@
1
- {"version":3,"file":"capture-footprint.js","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capture-footprint.js","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,17 @@ import * as z from "zod";
2
2
  import type { EvidenceDatabase } from "../lib/storage/index.js";
3
3
  export declare const deleteFootprintsSchema: {
4
4
  inputSchema: {
5
- evidenceIds: z.ZodArray<z.ZodString, "many">;
5
+ evidenceIds: z.ZodArray<z.ZodString>;
6
+ confirmDelete: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
6
7
  };
7
8
  outputSchema: {
8
9
  deletedCount: z.ZodNumber;
10
+ previewed: z.ZodOptional<z.ZodArray<z.ZodObject<{
11
+ id: z.ZodString;
12
+ conversationId: z.ZodString;
13
+ timestamp: z.ZodString;
14
+ }, z.core.$strip>>>;
15
+ notFoundIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
9
16
  success: z.ZodBoolean;
10
17
  };
11
18
  };
@@ -15,8 +22,18 @@ export declare const deleteFootprintsMetadata: {
15
22
  };
16
23
  export declare function createDeleteFootprintsHandler(db: EvidenceDatabase): (params: {
17
24
  evidenceIds: string[];
25
+ confirmDelete?: boolean;
18
26
  }) => Promise<import("../lib/tool-response.js").ToolResponse<{
19
27
  deletedCount: number;
28
+ previewed: {
29
+ id: string;
30
+ conversationId: string | null;
31
+ timestamp: string;
32
+ }[];
33
+ success: boolean;
34
+ }> | import("../lib/tool-response.js").ToolResponse<{
35
+ deletedCount: number;
36
+ notFoundIds: string[];
20
37
  success: boolean;
21
38
  }>>;
22
39
  //# sourceMappingURL=delete-footprints.d.ts.map