@triedotdev/mcp 1.0.168 → 1.0.170

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 (149) hide show
  1. package/README.md +54 -500
  2. package/dist/chunk-2YXOBNKW.js +619 -0
  3. package/dist/chunk-2YXOBNKW.js.map +1 -0
  4. package/dist/chunk-QR64Y5TI.js +363 -0
  5. package/dist/chunk-QR64Y5TI.js.map +1 -0
  6. package/dist/cli/main.d.ts +0 -15
  7. package/dist/cli/main.js +356 -3100
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/index.js +2 -36
  10. package/dist/index.js.map +1 -1
  11. package/dist/server/mcp-server.js +2 -36
  12. package/package.json +8 -31
  13. package/dist/autonomy-config-FSERX3O3.js +0 -30
  14. package/dist/autonomy-config-FSERX3O3.js.map +0 -1
  15. package/dist/chat-store-JNGNTDSN.js +0 -15
  16. package/dist/chat-store-JNGNTDSN.js.map +0 -1
  17. package/dist/chunk-2HF65EHQ.js +0 -311
  18. package/dist/chunk-2HF65EHQ.js.map +0 -1
  19. package/dist/chunk-43X6JBEM.js +0 -36
  20. package/dist/chunk-43X6JBEM.js.map +0 -1
  21. package/dist/chunk-4MXH2ZPT.js +0 -1827
  22. package/dist/chunk-4MXH2ZPT.js.map +0 -1
  23. package/dist/chunk-575YT2SD.js +0 -737
  24. package/dist/chunk-575YT2SD.js.map +0 -1
  25. package/dist/chunk-5BRRRTN6.js +0 -354
  26. package/dist/chunk-5BRRRTN6.js.map +0 -1
  27. package/dist/chunk-6NLHFIYA.js +0 -344
  28. package/dist/chunk-6NLHFIYA.js.map +0 -1
  29. package/dist/chunk-7WITSO22.js +0 -824
  30. package/dist/chunk-7WITSO22.js.map +0 -1
  31. package/dist/chunk-DGUM43GV.js +0 -11
  32. package/dist/chunk-DGUM43GV.js.map +0 -1
  33. package/dist/chunk-EFWVF6TI.js +0 -267
  34. package/dist/chunk-EFWVF6TI.js.map +0 -1
  35. package/dist/chunk-F6WFNUAY.js +0 -216
  36. package/dist/chunk-F6WFNUAY.js.map +0 -1
  37. package/dist/chunk-FQ45QP5A.js +0 -361
  38. package/dist/chunk-FQ45QP5A.js.map +0 -1
  39. package/dist/chunk-G2TGF6TR.js +0 -573
  40. package/dist/chunk-G2TGF6TR.js.map +0 -1
  41. package/dist/chunk-GTKYBOXL.js +0 -700
  42. package/dist/chunk-GTKYBOXL.js.map +0 -1
  43. package/dist/chunk-HVCDY3AK.js +0 -850
  44. package/dist/chunk-HVCDY3AK.js.map +0 -1
  45. package/dist/chunk-JVMBCWKS.js +0 -348
  46. package/dist/chunk-JVMBCWKS.js.map +0 -1
  47. package/dist/chunk-KDHN2ZQE.js +0 -313
  48. package/dist/chunk-KDHN2ZQE.js.map +0 -1
  49. package/dist/chunk-LQIMKE3P.js +0 -12524
  50. package/dist/chunk-LQIMKE3P.js.map +0 -1
  51. package/dist/chunk-ME2OERF5.js +0 -345
  52. package/dist/chunk-ME2OERF5.js.map +0 -1
  53. package/dist/chunk-MRHKX5M5.js +0 -662
  54. package/dist/chunk-MRHKX5M5.js.map +0 -1
  55. package/dist/chunk-OBQ74FOU.js +0 -27
  56. package/dist/chunk-OBQ74FOU.js.map +0 -1
  57. package/dist/chunk-OMR4YCBS.js +0 -987
  58. package/dist/chunk-OMR4YCBS.js.map +0 -1
  59. package/dist/chunk-Q5EKA5YA.js +0 -254
  60. package/dist/chunk-Q5EKA5YA.js.map +0 -1
  61. package/dist/chunk-Q63FFI6D.js +0 -132
  62. package/dist/chunk-Q63FFI6D.js.map +0 -1
  63. package/dist/chunk-SY6KQG44.js +0 -983
  64. package/dist/chunk-SY6KQG44.js.map +0 -1
  65. package/dist/chunk-T63OHG4Q.js +0 -440
  66. package/dist/chunk-T63OHG4Q.js.map +0 -1
  67. package/dist/chunk-TN5WEKWI.js +0 -173
  68. package/dist/chunk-TN5WEKWI.js.map +0 -1
  69. package/dist/chunk-VUL52BQL.js +0 -402
  70. package/dist/chunk-VUL52BQL.js.map +0 -1
  71. package/dist/chunk-VVITXIHN.js +0 -189
  72. package/dist/chunk-VVITXIHN.js.map +0 -1
  73. package/dist/chunk-WCN7S3EI.js +0 -14
  74. package/dist/chunk-WCN7S3EI.js.map +0 -1
  75. package/dist/chunk-XE6KQRKZ.js +0 -816
  76. package/dist/chunk-XE6KQRKZ.js.map +0 -1
  77. package/dist/chunk-XPZZFPBZ.js +0 -491
  78. package/dist/chunk-XPZZFPBZ.js.map +0 -1
  79. package/dist/chunk-XTFWT2XM.js +0 -727
  80. package/dist/chunk-XTFWT2XM.js.map +0 -1
  81. package/dist/chunk-YDHUCDHM.js +0 -4011
  82. package/dist/chunk-YDHUCDHM.js.map +0 -1
  83. package/dist/chunk-YZ6Y2H3P.js +0 -1289
  84. package/dist/chunk-YZ6Y2H3P.js.map +0 -1
  85. package/dist/chunk-ZJF5FTBX.js +0 -1396
  86. package/dist/chunk-ZJF5FTBX.js.map +0 -1
  87. package/dist/chunk-ZV2K6M7T.js +0 -74
  88. package/dist/chunk-ZV2K6M7T.js.map +0 -1
  89. package/dist/cli/create-agent.d.ts +0 -1
  90. package/dist/cli/create-agent.js +0 -1050
  91. package/dist/cli/create-agent.js.map +0 -1
  92. package/dist/cli/yolo-daemon.d.ts +0 -1
  93. package/dist/cli/yolo-daemon.js +0 -423
  94. package/dist/cli/yolo-daemon.js.map +0 -1
  95. package/dist/client-NJPZE5JT.js +0 -28
  96. package/dist/client-NJPZE5JT.js.map +0 -1
  97. package/dist/codebase-index-VAPF32XX.js +0 -12
  98. package/dist/codebase-index-VAPF32XX.js.map +0 -1
  99. package/dist/fast-analyzer-XXYMOXRK.js +0 -216
  100. package/dist/fast-analyzer-XXYMOXRK.js.map +0 -1
  101. package/dist/git-EO5SRFMN.js +0 -28
  102. package/dist/git-EO5SRFMN.js.map +0 -1
  103. package/dist/github-ingester-ZOKK6GRS.js +0 -11
  104. package/dist/github-ingester-ZOKK6GRS.js.map +0 -1
  105. package/dist/goal-manager-YOB7VWK7.js +0 -25
  106. package/dist/goal-manager-YOB7VWK7.js.map +0 -1
  107. package/dist/goal-validator-ULKIBDPX.js +0 -24
  108. package/dist/goal-validator-ULKIBDPX.js.map +0 -1
  109. package/dist/graph-B3NA4S7I.js +0 -10
  110. package/dist/graph-B3NA4S7I.js.map +0 -1
  111. package/dist/hypothesis-7BFFT5JY.js +0 -23
  112. package/dist/hypothesis-7BFFT5JY.js.map +0 -1
  113. package/dist/incident-index-EFNUSGWL.js +0 -11
  114. package/dist/incident-index-EFNUSGWL.js.map +0 -1
  115. package/dist/insight-store-EC4PLSAW.js +0 -22
  116. package/dist/insight-store-EC4PLSAW.js.map +0 -1
  117. package/dist/issue-store-ZIRP23EP.js +0 -36
  118. package/dist/issue-store-ZIRP23EP.js.map +0 -1
  119. package/dist/ledger-TWZTGDFA.js +0 -58
  120. package/dist/ledger-TWZTGDFA.js.map +0 -1
  121. package/dist/linear-ingester-XXPAZZRW.js +0 -11
  122. package/dist/linear-ingester-XXPAZZRW.js.map +0 -1
  123. package/dist/output-manager-RVJ37XKA.js +0 -13
  124. package/dist/output-manager-RVJ37XKA.js.map +0 -1
  125. package/dist/parse-goal-violation-SACGFG3C.js +0 -8
  126. package/dist/parse-goal-violation-SACGFG3C.js.map +0 -1
  127. package/dist/pattern-discovery-F7LU5K6E.js +0 -8
  128. package/dist/pattern-discovery-F7LU5K6E.js.map +0 -1
  129. package/dist/progress-SRQ2V3BP.js +0 -18
  130. package/dist/progress-SRQ2V3BP.js.map +0 -1
  131. package/dist/project-state-AHPA77SM.js +0 -28
  132. package/dist/project-state-AHPA77SM.js.map +0 -1
  133. package/dist/sync-M2FSWPBC.js +0 -12
  134. package/dist/sync-M2FSWPBC.js.map +0 -1
  135. package/dist/terminal-spawn-5YXDMUCF.js +0 -157
  136. package/dist/terminal-spawn-5YXDMUCF.js.map +0 -1
  137. package/dist/tiered-storage-Z3YCR465.js +0 -12
  138. package/dist/tiered-storage-Z3YCR465.js.map +0 -1
  139. package/dist/trie-agent-3YDPEGHJ.js +0 -28
  140. package/dist/trie-agent-3YDPEGHJ.js.map +0 -1
  141. package/dist/ui/chat.html +0 -1014
  142. package/dist/ui/goals.html +0 -967
  143. package/dist/ui/hypotheses.html +0 -1011
  144. package/dist/ui/ledger.html +0 -954
  145. package/dist/ui/nudges.html +0 -995
  146. package/dist/vibe-code-signatures-F6URTBW3.js +0 -16
  147. package/dist/vibe-code-signatures-F6URTBW3.js.map +0 -1
  148. package/dist/vulnerability-signatures-T7SKHORW.js +0 -18
  149. package/dist/vulnerability-signatures-T7SKHORW.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,42 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-YDHUCDHM.js";
5
- import "./chunk-F6WFNUAY.js";
6
- import "./chunk-HVCDY3AK.js";
7
- import "./chunk-Q63FFI6D.js";
8
- import "./chunk-LQIMKE3P.js";
9
- import "./chunk-Q5EKA5YA.js";
10
- import "./chunk-JVMBCWKS.js";
11
- import "./chunk-4MXH2ZPT.js";
12
- import "./chunk-XTFWT2XM.js";
13
- import "./chunk-WCN7S3EI.js";
14
- import "./chunk-G2TGF6TR.js";
15
- import "./chunk-MRHKX5M5.js";
16
- import "./chunk-T63OHG4Q.js";
17
- import "./chunk-YZ6Y2H3P.js";
18
- import "./chunk-5BRRRTN6.js";
19
- import "./chunk-OBQ74FOU.js";
20
- import "./chunk-XPZZFPBZ.js";
21
- import "./chunk-TN5WEKWI.js";
22
- import "./chunk-ZV2K6M7T.js";
23
- import "./chunk-7WITSO22.js";
24
- import "./chunk-SY6KQG44.js";
25
- import "./chunk-OMR4YCBS.js";
26
- import "./chunk-VUL52BQL.js";
27
- import "./chunk-6NLHFIYA.js";
28
- import "./chunk-575YT2SD.js";
29
- import "./chunk-FQ45QP5A.js";
30
- import "./chunk-XE6KQRKZ.js";
31
- import "./chunk-ZJF5FTBX.js";
32
- import "./chunk-GTKYBOXL.js";
33
- import "./chunk-EFWVF6TI.js";
34
- import "./chunk-43X6JBEM.js";
35
- import "./chunk-ME2OERF5.js";
36
- import "./chunk-VVITXIHN.js";
37
- import "./chunk-KDHN2ZQE.js";
38
- import "./chunk-2HF65EHQ.js";
39
- import "./chunk-DGUM43GV.js";
4
+ } from "./chunk-2YXOBNKW.js";
5
+ import "./chunk-QR64Y5TI.js";
40
6
 
41
7
  // src/index.ts
42
8
  startServer().catch((error) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { startServer } from './server/mcp-server.js';\n\n// Start the MCP server\nstartServer().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,YAAY,EAAE,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { startServer } from './server/mcp-server.js';\n\n// Start the MCP server\nstartServer().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});"],"mappings":";;;;;;;AAKA,YAAY,EAAE,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
@@ -1,42 +1,8 @@
1
1
  import {
2
2
  MCPServer,
3
3
  startServer
4
- } from "../chunk-YDHUCDHM.js";
5
- import "../chunk-F6WFNUAY.js";
6
- import "../chunk-HVCDY3AK.js";
7
- import "../chunk-Q63FFI6D.js";
8
- import "../chunk-LQIMKE3P.js";
9
- import "../chunk-Q5EKA5YA.js";
10
- import "../chunk-JVMBCWKS.js";
11
- import "../chunk-4MXH2ZPT.js";
12
- import "../chunk-XTFWT2XM.js";
13
- import "../chunk-WCN7S3EI.js";
14
- import "../chunk-G2TGF6TR.js";
15
- import "../chunk-MRHKX5M5.js";
16
- import "../chunk-T63OHG4Q.js";
17
- import "../chunk-YZ6Y2H3P.js";
18
- import "../chunk-5BRRRTN6.js";
19
- import "../chunk-OBQ74FOU.js";
20
- import "../chunk-XPZZFPBZ.js";
21
- import "../chunk-TN5WEKWI.js";
22
- import "../chunk-ZV2K6M7T.js";
23
- import "../chunk-7WITSO22.js";
24
- import "../chunk-SY6KQG44.js";
25
- import "../chunk-OMR4YCBS.js";
26
- import "../chunk-VUL52BQL.js";
27
- import "../chunk-6NLHFIYA.js";
28
- import "../chunk-575YT2SD.js";
29
- import "../chunk-FQ45QP5A.js";
30
- import "../chunk-XE6KQRKZ.js";
31
- import "../chunk-ZJF5FTBX.js";
32
- import "../chunk-GTKYBOXL.js";
33
- import "../chunk-EFWVF6TI.js";
34
- import "../chunk-43X6JBEM.js";
35
- import "../chunk-ME2OERF5.js";
36
- import "../chunk-VVITXIHN.js";
37
- import "../chunk-KDHN2ZQE.js";
38
- import "../chunk-2HF65EHQ.js";
39
- import "../chunk-DGUM43GV.js";
4
+ } from "../chunk-2YXOBNKW.js";
5
+ import "../chunk-QR64Y5TI.js";
40
6
  export {
41
7
  MCPServer,
42
8
  startServer
package/package.json CHANGED
@@ -1,25 +1,20 @@
1
1
  {
2
2
  "name": "@triedotdev/mcp",
3
- "version": "1.0.168",
4
- "description": "Governance ledger for agent-human teams. Decision memory that travels from Cursor to CLI to CI/CD.",
3
+ "version": "1.0.170",
4
+ "description": "Trie cloud context bridge for Cursor and Claude Code.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "trie": "dist/cli/main.js",
9
9
  "mcp": "dist/index.js",
10
10
  "trie-agent": "dist/cli/main.js",
11
- "trie-mcp": "dist/index.js",
12
- "trie-watch": "dist/cli/yolo-daemon.js",
13
- "trie-create": "dist/cli/create-agent.js"
11
+ "trie-mcp": "dist/index.js"
14
12
  },
15
13
  "scripts": {
16
- "build": "tsup && npm run build:ui",
14
+ "build": "tsup",
17
15
  "build:server": "tsup",
18
- "build:ui": "tsx src/ui/build.ts",
19
16
  "dev": "tsx src/index.ts",
20
17
  "test": "vitest",
21
- "test:mcp-apps": "tsx scripts/test-mcp-apps-integration.js",
22
- "preview:ui": "node scripts/preview-ui-apps.js",
23
18
  "lint": "eslint src/**/*.ts",
24
19
  "typecheck": "tsc --noEmit",
25
20
  "prepublishOnly": "npm run build"
@@ -51,36 +46,18 @@
51
46
  "url": "https://buy.stripe.com/5kQbJ12isaFyfVk0Tu00005"
52
47
  },
53
48
  "dependencies": {
54
- "@anthropic-ai/sdk": "^0.29.0",
55
- "@babel/generator": "^7.23.0",
56
- "@babel/parser": "^7.23.0",
57
- "@babel/traverse": "^7.23.0",
58
- "@babel/types": "^7.23.0",
59
- "@modelcontextprotocol/ext-apps": "^1.0.1",
60
- "@modelcontextprotocol/sdk": "^1.0.0",
61
- "@noble/ed25519": "^3.0.0",
62
- "@triedotdev/mcp": "^1.0.166",
63
- "@vercel/blob": "^2.0.0",
64
- "better-sqlite3": "^12.6.2",
65
- "commander": "^11.1.0",
66
- "glob": "^10.3.0",
67
- "ink": "^5.2.1",
68
- "picocolors": "^1.0.0",
69
- "playwright": "^1.57.0",
70
- "react": "^18.3.1",
49
+ "@modelcontextprotocol/sdk": "^1.27.1",
71
50
  "typescript": "^5.3.0",
72
51
  "zod": "^3.22.0"
73
52
  },
53
+ "optionalDependencies": {
54
+ "keytar": "^7.9.0"
55
+ },
74
56
  "devDependencies": {
75
- "@types/babel__generator": "^7.6.8",
76
- "@types/babel__traverse": "^7.20.6",
77
- "@types/better-sqlite3": "^7.6.13",
78
57
  "@types/node": "^20.10.0",
79
- "@types/react": "^18.3.28",
80
58
  "@typescript-eslint/eslint-plugin": "^6.13.0",
81
59
  "@typescript-eslint/parser": "^6.13.0",
82
60
  "eslint": "^8.55.0",
83
- "ink-testing-library": "^4.0.0",
84
61
  "tsup": "^8.0.0",
85
62
  "tsx": "^4.6.0",
86
63
  "vitest": "^1.0.0"
@@ -1,30 +0,0 @@
1
- import {
2
- clearConfigCache,
3
- createIssueHash,
4
- getAutonomyConfig,
5
- getEscalationLevel,
6
- groupFixesByFile,
7
- loadAutonomyConfig,
8
- recordBypass,
9
- saveAutonomyConfig,
10
- shouldAutoFix,
11
- shouldBlockPush,
12
- trackIssueOccurrence
13
- } from "./chunk-ME2OERF5.js";
14
- import "./chunk-VVITXIHN.js";
15
- import "./chunk-KDHN2ZQE.js";
16
- import "./chunk-DGUM43GV.js";
17
- export {
18
- clearConfigCache,
19
- createIssueHash,
20
- getAutonomyConfig,
21
- getEscalationLevel,
22
- groupFixesByFile,
23
- loadAutonomyConfig,
24
- recordBypass,
25
- saveAutonomyConfig,
26
- shouldAutoFix,
27
- shouldBlockPush,
28
- trackIssueOccurrence
29
- };
30
- //# sourceMappingURL=autonomy-config-FSERX3O3.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,15 +0,0 @@
1
- import {
2
- ChatStore,
3
- clearChatStores,
4
- getChatStore
5
- } from "./chunk-JVMBCWKS.js";
6
- import "./chunk-43X6JBEM.js";
7
- import "./chunk-VVITXIHN.js";
8
- import "./chunk-KDHN2ZQE.js";
9
- import "./chunk-DGUM43GV.js";
10
- export {
11
- ChatStore,
12
- clearChatStores,
13
- getChatStore
14
- };
15
- //# sourceMappingURL=chat-store-JNGNTDSN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,311 +0,0 @@
1
- // src/agent/git.ts
2
- import { existsSync } from "fs";
3
- import path from "path";
4
-
5
- // src/utils/command-runner.ts
6
- import { exec, execFile, execSync } from "child_process";
7
- import { promisify } from "util";
8
-
9
- // src/utils/audit-logger.ts
10
- function createAuditEntry(skillName, skillSource, triggeredBy, targetPath) {
11
- return {
12
- skillName,
13
- skillSource,
14
- triggeredBy,
15
- targetPath,
16
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
17
- commands: []
18
- };
19
- }
20
- function completeAuditEntry(entry, success, error) {
21
- const result = {
22
- ...entry,
23
- completedAt: (/* @__PURE__ */ new Date()).toISOString(),
24
- success
25
- };
26
- if (error !== void 0) {
27
- result.error = error;
28
- }
29
- return result;
30
- }
31
- async function logSkillExecution(_execution) {
32
- }
33
-
34
- // src/utils/command-runner.ts
35
- var execAsync = promisify(exec);
36
- var execFileAsync = promisify(execFile);
37
- function redact(text) {
38
- return text.replace(/\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\s*=\s*([^\s"'`]+)/gi, "$1_<REDACTED>=<REDACTED>").replace(/\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/g, "Bearer <REDACTED>").replace(/\bghp_[A-Za-z0-9]{20,}\b/g, "ghp_<REDACTED>").replace(/\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\b/g, "<REDACTED_SLACK_TOKEN>").replace(/\bAKIA[0-9A-Z]{16}\b/g, "AKIA<REDACTED>");
39
- }
40
- function clampOutput(text, maxChars) {
41
- if (text.length <= maxChars) return text;
42
- return text.slice(0, maxChars) + `
43
- \u2026(truncated ${text.length - maxChars} chars)`;
44
- }
45
- function buildCommandRecord(command) {
46
- return {
47
- command,
48
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
49
- };
50
- }
51
- async function finalizeAndWrite(entry, cmd, outcome, options) {
52
- const duration = Date.now() - outcome.startedAt;
53
- cmd.duration = duration;
54
- if (outcome.exitCode !== void 0) {
55
- cmd.exitCode = outcome.exitCode;
56
- }
57
- const captureOutput = options?.captureOutput ?? false;
58
- const redactOutput = options?.redactOutput ?? true;
59
- const maxOutputChars = options?.maxOutputChars ?? 2e3;
60
- if (captureOutput) {
61
- const out = outcome.stdout ?? "";
62
- const err = outcome.stderr ?? "";
63
- cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);
64
- cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);
65
- }
66
- const completed = completeAuditEntry(entry, outcome.success, outcome.error);
67
- await logSkillExecution(completed);
68
- }
69
- function runShellCommandSync(command, audit, options) {
70
- const startedAt = Date.now();
71
- const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
72
- const cmd = buildCommandRecord(command);
73
- entry.commands?.push(cmd);
74
- try {
75
- const stdout = execSync(command, {
76
- cwd: options?.cwd,
77
- timeout: options?.timeoutMs,
78
- maxBuffer: options?.maxBuffer,
79
- encoding: "utf-8",
80
- stdio: ["pipe", "pipe", "pipe"]
81
- });
82
- void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: "", startedAt }, options);
83
- return { stdout: stdout ?? "", exitCode: 0 };
84
- } catch (e) {
85
- const err = e;
86
- const stdout = typeof err.stdout === "string" ? err.stdout : "";
87
- const stderr = typeof err.stderr === "string" ? err.stderr : "";
88
- const exitCode = typeof err.status === "number" ? err.status : 1;
89
- void finalizeAndWrite(
90
- entry,
91
- cmd,
92
- { success: false, exitCode, stdout, stderr, error: err.message, startedAt },
93
- { ...options, captureOutput: options?.captureOutput ?? true }
94
- );
95
- return { stdout, exitCode };
96
- }
97
- }
98
- async function runExecFile(file, args, audit, options) {
99
- const startedAt = Date.now();
100
- const command = [file, ...args].join(" ");
101
- const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
102
- const cmd = buildCommandRecord(command);
103
- entry.commands?.push(cmd);
104
- try {
105
- const { stdout, stderr } = await execFileAsync(file, args, {
106
- cwd: options?.cwd,
107
- timeout: options?.timeoutMs,
108
- maxBuffer: options?.maxBuffer
109
- });
110
- await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), startedAt }, options);
111
- return { stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), exitCode: 0 };
112
- } catch (e) {
113
- const err = e;
114
- const stdout = typeof err.stdout === "string" ? err.stdout : "";
115
- const stderr = typeof err.stderr === "string" ? err.stderr : "";
116
- const exitCode = typeof err.code === "number" ? err.code : 1;
117
- await finalizeAndWrite(
118
- entry,
119
- cmd,
120
- { success: false, exitCode, stdout, stderr, error: err.message, startedAt },
121
- { ...options, captureOutput: options?.captureOutput ?? true }
122
- );
123
- return { stdout, stderr, exitCode };
124
- }
125
- }
126
-
127
- // src/agent/git.ts
128
- async function execGit(args, cwd) {
129
- try {
130
- const { stdout } = await runExecFile(
131
- "git",
132
- ["-C", cwd, ...args],
133
- { actor: "internal:git", triggeredBy: "manual", targetPath: cwd },
134
- { maxBuffer: 10 * 1024 * 1024, captureOutput: false }
135
- );
136
- return stdout.trim();
137
- } catch (error) {
138
- const stderr = error?.stderr?.toString();
139
- if (stderr?.includes("not a git repository") || stderr?.includes("does not have any commits")) {
140
- return null;
141
- }
142
- throw error;
143
- }
144
- }
145
- async function ensureRepo(projectPath) {
146
- const result = await execGit(["rev-parse", "--is-inside-work-tree"], projectPath);
147
- return result === "true";
148
- }
149
- function parseNameStatus(output) {
150
- return output.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
151
- const parts = line.split(" ");
152
- const status = parts[0] ?? "";
153
- const filePath = parts[1] ?? "";
154
- const oldPath = parts[2];
155
- const change = { status, path: filePath };
156
- if (oldPath) change.oldPath = oldPath;
157
- return change;
158
- }).filter((entry) => entry.path.length > 0);
159
- }
160
- async function getRecentCommits(projectPath, limit) {
161
- const isRepo = await ensureRepo(projectPath);
162
- if (!isRepo) return [];
163
- const output = await execGit(
164
- ["log", `-n`, String(limit), "--pretty=format:%H%x09%an%x09%ad%x09%s", "--date=iso"],
165
- projectPath
166
- );
167
- if (!output) return [];
168
- return output.split("\n").map((line) => {
169
- const [hash, author, date, message] = line.split(" ");
170
- return { hash, author, date, message };
171
- });
172
- }
173
- async function getLastCommit(projectPath) {
174
- const commits = await getRecentCommits(projectPath, 1);
175
- return commits[0] ?? null;
176
- }
177
- async function getStagedChanges(projectPath) {
178
- const isRepo = await ensureRepo(projectPath);
179
- if (!isRepo) return [];
180
- const output = await execGit(["diff", "--cached", "--name-status"], projectPath);
181
- if (!output) return [];
182
- return parseNameStatus(output);
183
- }
184
- async function getUncommittedChanges(projectPath) {
185
- const isRepo = await ensureRepo(projectPath);
186
- if (!isRepo) return [];
187
- const changes = [];
188
- const unstaged = await execGit(["diff", "--name-status"], projectPath);
189
- if (unstaged) {
190
- changes.push(...parseNameStatus(unstaged));
191
- }
192
- const untracked = await execGit(["ls-files", "--others", "--exclude-standard"], projectPath);
193
- if (untracked) {
194
- changes.push(
195
- ...untracked.split("\n").map((p) => p.trim()).filter(Boolean).map((p) => ({ status: "??", path: p }))
196
- );
197
- }
198
- return changes;
199
- }
200
- async function getGitChangedFiles(projectPath) {
201
- const isRepo = await ensureRepo(projectPath);
202
- if (!isRepo) return null;
203
- const [staged, uncommitted] = await Promise.all([
204
- getStagedChanges(projectPath).catch(() => []),
205
- getUncommittedChanges(projectPath).catch(() => [])
206
- ]);
207
- const paths = /* @__PURE__ */ new Set();
208
- for (const change of [...staged, ...uncommitted]) {
209
- if (change.path) paths.add(change.path);
210
- if (change.oldPath) paths.add(change.oldPath);
211
- }
212
- return [...paths];
213
- }
214
- async function getDiff(projectPath, commitHash) {
215
- const isRepo = await ensureRepo(projectPath);
216
- if (!isRepo) return "";
217
- const diff = await execGit(["show", commitHash, "--unified=3", "--no-color"], projectPath);
218
- return diff ?? "";
219
- }
220
- async function getWorkingTreeDiff(projectPath, stagedOnly = false) {
221
- const isRepo = await ensureRepo(projectPath);
222
- if (!isRepo) return "";
223
- const args = stagedOnly ? ["diff", "--cached", "--unified=3", "--no-color"] : ["diff", "--unified=3", "--no-color"];
224
- const diff = await execGit(args, projectPath);
225
- return diff ?? "";
226
- }
227
- async function getUnpushedCommits(projectPath) {
228
- const isRepo = await ensureRepo(projectPath);
229
- if (!isRepo) return [];
230
- const upstream = await execGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], projectPath);
231
- if (!upstream) {
232
- return getRecentCommits(projectPath, 10);
233
- }
234
- const output = await execGit(["log", `${upstream}..HEAD`, "--pretty=format:%H%x09%an%x09%ad%x09%s", "--date=iso"], projectPath);
235
- if (!output) return [];
236
- return output.split("\n").filter(Boolean).map((line) => {
237
- const [hash, author, date, message] = line.split(" ");
238
- return { hash, author, date, message };
239
- });
240
- }
241
- function resolveRepoPath(projectPath) {
242
- const gitDir = path.join(projectPath, ".git");
243
- if (existsSync(gitDir)) return projectPath;
244
- return projectPath;
245
- }
246
- async function isGitRepo(projectPath) {
247
- const result = await execGit(["rev-parse", "--is-inside-work-tree"], projectPath);
248
- return result === "true";
249
- }
250
- async function getChangedFilesSinceTimestamp(projectPath, timestamp) {
251
- const isRepo = await isGitRepo(projectPath);
252
- if (!isRepo) return null;
253
- try {
254
- const sinceDate = new Date(timestamp).toISOString();
255
- const GIT_TIMEOUT_MS = 5e3;
256
- const startTime = Date.now();
257
- const committedChangesPromise = execGit(
258
- ["log", `--since=${sinceDate}`, "--name-only", "--pretty=format:"],
259
- projectPath
260
- );
261
- const committedChangesTimeout = new Promise((resolve) => {
262
- setTimeout(() => resolve(null), GIT_TIMEOUT_MS);
263
- });
264
- const committedChanges = await Promise.race([committedChangesPromise, committedChangesTimeout]);
265
- if (Date.now() - startTime > GIT_TIMEOUT_MS) {
266
- return null;
267
- }
268
- const stagedPromise = execGit(["diff", "--cached", "--name-only"], projectPath);
269
- const unstagedPromise = execGit(["diff", "--name-only"], projectPath);
270
- const untrackedPromise = execGit(
271
- ["ls-files", "--others", "--exclude-standard"],
272
- projectPath
273
- );
274
- const timeoutPromise = new Promise((resolve) => {
275
- setTimeout(() => resolve(null), Math.max(0, GIT_TIMEOUT_MS - (Date.now() - startTime)));
276
- });
277
- const [stagedChanges, unstagedChanges, untrackedFiles] = await Promise.race([
278
- Promise.all([stagedPromise, unstagedPromise, untrackedPromise]),
279
- timeoutPromise.then(() => [null, null, null])
280
- ]);
281
- const changedFiles = /* @__PURE__ */ new Set();
282
- const addFiles = (output) => {
283
- if (output) {
284
- output.split("\n").map((f) => f.trim()).filter(Boolean).forEach((f) => changedFiles.add(path.join(projectPath, f)));
285
- }
286
- };
287
- addFiles(committedChanges);
288
- addFiles(stagedChanges);
289
- addFiles(unstagedChanges);
290
- addFiles(untrackedFiles);
291
- return Array.from(changedFiles);
292
- } catch {
293
- return null;
294
- }
295
- }
296
-
297
- export {
298
- runShellCommandSync,
299
- getRecentCommits,
300
- getLastCommit,
301
- getStagedChanges,
302
- getUncommittedChanges,
303
- getGitChangedFiles,
304
- getDiff,
305
- getWorkingTreeDiff,
306
- getUnpushedCommits,
307
- resolveRepoPath,
308
- isGitRepo,
309
- getChangedFilesSinceTimestamp
310
- };
311
- //# sourceMappingURL=chunk-2HF65EHQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/agent/git.ts","../src/utils/command-runner.ts","../src/utils/audit-logger.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { runExecFile } from '../utils/command-runner.js';\n\nexport interface Commit {\n hash: string;\n author: string;\n date: string;\n message: string;\n}\n\nexport interface Change {\n path: string;\n status: string;\n oldPath?: string;\n}\n\nasync function execGit(args: string[], cwd: string): Promise<string | null> {\n try {\n const { stdout } = await runExecFile(\n 'git',\n ['-C', cwd, ...args],\n { actor: 'internal:git', triggeredBy: 'manual', targetPath: cwd },\n { maxBuffer: 10 * 1024 * 1024, captureOutput: false }\n );\n return stdout.trim();\n } catch (error: any) {\n const stderr: string | undefined = error?.stderr?.toString();\n // Gracefully handle non-git directories and repos with no commits\n if (stderr?.includes('not a git repository') || stderr?.includes('does not have any commits')) {\n return null;\n }\n throw error;\n }\n}\n\nasync function ensureRepo(projectPath: string): Promise<boolean> {\n const result = await execGit(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\nfunction parseNameStatus(output: string): Change[] {\n return output\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const parts = line.split('\\t');\n const status = parts[0] ?? '';\n const filePath = parts[1] ?? '';\n const oldPath = parts[2];\n const change: Change = { status, path: filePath };\n if (oldPath) change.oldPath = oldPath;\n return change;\n })\n .filter((entry) => entry.path.length > 0);\n}\n\nexport async function getRecentCommits(projectPath: string, limit: number): Promise<Commit[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const output = await execGit(\n ['log', `-n`, String(limit), '--pretty=format:%H%x09%an%x09%ad%x09%s', '--date=iso'],\n projectPath\n );\n\n if (!output) return [];\n\n return output.split('\\n').map((line) => {\n const [hash, author, date, message] = line.split('\\t');\n return { hash, author, date, message } as Commit;\n });\n}\n\nexport async function getLastCommit(projectPath: string): Promise<Commit | null> {\n const commits = await getRecentCommits(projectPath, 1);\n return commits[0] ?? null;\n}\n\nexport async function getStagedChanges(projectPath: string): Promise<Change[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const output = await execGit(['diff', '--cached', '--name-status'], projectPath);\n if (!output) return [];\n return parseNameStatus(output);\n}\n\nexport async function getUncommittedChanges(projectPath: string): Promise<Change[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const changes: Change[] = [];\n\n const unstaged = await execGit(['diff', '--name-status'], projectPath);\n if (unstaged) {\n changes.push(...parseNameStatus(unstaged));\n }\n\n const untracked = await execGit(['ls-files', '--others', '--exclude-standard'], projectPath);\n if (untracked) {\n changes.push(\n ...untracked\n .split('\\n')\n .map((p) => p.trim())\n .filter(Boolean)\n .map((p) => ({ status: '??', path: p }))\n );\n }\n\n return changes;\n}\n\n/**\n * Get a flat list of changed file paths in the working tree.\n * Convenience helper used by tooling (e.g. cache invalidation).\n *\n * Returns null if not a git repository.\n */\nexport async function getGitChangedFiles(projectPath: string): Promise<string[] | null> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return null;\n\n const [staged, uncommitted] = await Promise.all([\n getStagedChanges(projectPath).catch(() => []),\n getUncommittedChanges(projectPath).catch(() => []),\n ]);\n\n const paths = new Set<string>();\n for (const change of [...staged, ...uncommitted]) {\n if (change.path) paths.add(change.path);\n if (change.oldPath) paths.add(change.oldPath);\n }\n\n return [...paths];\n}\n\nexport async function getDiff(projectPath: string, commitHash: string): Promise<string> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return '';\n\n const diff = await execGit(['show', commitHash, '--unified=3', '--no-color'], projectPath);\n return diff ?? '';\n}\n\nexport async function getWorkingTreeDiff(projectPath: string, stagedOnly = false): Promise<string> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return '';\n\n const args = stagedOnly ? ['diff', '--cached', '--unified=3', '--no-color'] : ['diff', '--unified=3', '--no-color'];\n const diff = await execGit(args, projectPath);\n return diff ?? '';\n}\n\nexport async function getUnpushedCommits(projectPath: string): Promise<Commit[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n // Handles detached HEAD by falling back to HEAD if upstream missing\n const upstream = await execGit(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], projectPath);\n if (!upstream) {\n return getRecentCommits(projectPath, 10);\n }\n\n const output = await execGit(['log', `${upstream}..HEAD`, '--pretty=format:%H%x09%an%x09%ad%x09%s', '--date=iso'], projectPath);\n if (!output) return [];\n\n return output.split('\\n').filter(Boolean).map((line) => {\n const [hash, author, date, message] = line.split('\\t');\n return { hash, author, date, message } as Commit;\n });\n}\n\nexport function resolveRepoPath(projectPath: string): string {\n const gitDir = path.join(projectPath, '.git');\n if (existsSync(gitDir)) return projectPath;\n return projectPath;\n}\n\n/**\n * Check if the given path is inside a git repository\n */\nexport async function isGitRepo(projectPath: string): Promise<boolean> {\n const result = await execGit(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\n/**\n * Get files changed since a given timestamp\n * Uses git log to find commits after timestamp, then gets affected files\n * Returns null if not a git repo or on error\n */\nexport async function getChangedFilesSinceTimestamp(\n projectPath: string,\n timestamp: number\n): Promise<string[] | null> {\n const isRepo = await isGitRepo(projectPath);\n if (!isRepo) return null;\n\n try {\n // Convert timestamp to ISO date for git\n const sinceDate = new Date(timestamp).toISOString();\n \n // Set timeout for git operations (5 seconds total)\n const GIT_TIMEOUT_MS = 5000;\n const startTime = Date.now();\n \n // Get all files that changed in commits since the timestamp\n // Use Promise.race to timeout if git operations take too long\n const committedChangesPromise = execGit(\n ['log', `--since=${sinceDate}`, '--name-only', '--pretty=format:'],\n projectPath\n );\n const committedChangesTimeout = new Promise<string | null>((resolve) => {\n setTimeout(() => resolve(null), GIT_TIMEOUT_MS);\n });\n const committedChanges = await Promise.race([committedChangesPromise, committedChangesTimeout]);\n\n // Check if we've exceeded timeout\n if (Date.now() - startTime > GIT_TIMEOUT_MS) {\n return null;\n }\n\n // Get currently modified files (staged + unstaged) - run in parallel with timeout\n const stagedPromise = execGit(['diff', '--cached', '--name-only'], projectPath);\n const unstagedPromise = execGit(['diff', '--name-only'], projectPath);\n const untrackedPromise = execGit(\n ['ls-files', '--others', '--exclude-standard'],\n projectPath\n );\n \n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), Math.max(0, GIT_TIMEOUT_MS - (Date.now() - startTime)));\n });\n \n const [stagedChanges, unstagedChanges, untrackedFiles] = await Promise.race([\n Promise.all([stagedPromise, unstagedPromise, untrackedPromise]),\n timeoutPromise.then(() => [null, null, null] as const)\n ]);\n\n // Combine all changed files\n const changedFiles = new Set<string>();\n \n const addFiles = (output: string | null) => {\n if (output) {\n output.split('\\n')\n .map(f => f.trim())\n .filter(Boolean)\n .forEach(f => changedFiles.add(path.join(projectPath, f)));\n }\n };\n\n addFiles(committedChanges);\n addFiles(stagedChanges);\n addFiles(unstagedChanges);\n addFiles(untrackedFiles);\n\n return Array.from(changedFiles);\n } catch {\n return null;\n }\n}\n","/**\n * Command Runner (with audit logging)\n *\n * Goal: Whenever Trie runs a shell command, record:\n * - command string\n * - exit code\n * - duration\n * - optional (redacted) stdout/stderr\n */\nimport { exec, execFile, execSync, type ExecException } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport {\n createAuditEntry,\n completeAuditEntry,\n logSkillExecution,\n type ExecutedCommand,\n type SkillExecution,\n} from './audit-logger.js';\n\nconst execAsync = promisify(exec);\nconst execFileAsync = promisify(execFile);\n\nexport type { ExecutedCommand, SkillExecution };\nexport type AuditTriggeredBy = SkillExecution['triggeredBy'];\n\nexport interface CommandAuditContext {\n /** Shown as `skillName` in audit logs; use something like `tool:pr-review` */\n actor: string;\n /** Where this came from in the product flow */\n triggeredBy: AuditTriggeredBy;\n /** Usually the working directory / repo path */\n targetPath: string;\n /** Optional string for `skillSource` */\n source?: string;\n}\n\nexport interface RunCommandOptions {\n cwd?: string;\n timeoutMs?: number;\n maxBuffer?: number;\n\n /** Capture stdout/stderr in the audit log */\n captureOutput?: boolean;\n /** Redact obvious secrets from captured output */\n redactOutput?: boolean;\n /** Max chars to keep per output stream */\n maxOutputChars?: number;\n}\n\nfunction redact(text: string): string {\n // Keep this conservative to avoid false redaction and avoid expensive processing.\n return text\n // Common key=value secrets\n .replace(/\\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\\s*=\\s*([^\\s\"'`]+)/gi, '$1_<REDACTED>=<REDACTED>')\n // Bearer tokens\n .replace(/\\bBearer\\s+[A-Za-z0-9\\-._~+/]+=*\\b/g, 'Bearer <REDACTED>')\n // GitHub tokens / generic tokens\n .replace(/\\bghp_[A-Za-z0-9]{20,}\\b/g, 'ghp_<REDACTED>')\n .replace(/\\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\\b/g, '<REDACTED_SLACK_TOKEN>')\n // AWS access key id (best-effort)\n .replace(/\\bAKIA[0-9A-Z]{16}\\b/g, 'AKIA<REDACTED>');\n}\n\nfunction clampOutput(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars) + `\\n…(truncated ${text.length - maxChars} chars)`;\n}\n\nfunction buildCommandRecord(command: string): ExecutedCommand {\n return {\n command,\n timestamp: new Date().toISOString(),\n };\n}\n\nasync function finalizeAndWrite(\n entry: SkillExecution,\n cmd: ExecutedCommand,\n outcome: { success: boolean; exitCode?: number; stdout?: string; stderr?: string; error?: string; startedAt: number },\n options?: Pick<RunCommandOptions, 'captureOutput' | 'redactOutput' | 'maxOutputChars'>\n): Promise<void> {\n const duration = Date.now() - outcome.startedAt;\n cmd.duration = duration;\n if (outcome.exitCode !== undefined) {\n cmd.exitCode = outcome.exitCode;\n }\n\n const captureOutput = options?.captureOutput ?? false;\n const redactOutput = options?.redactOutput ?? true;\n const maxOutputChars = options?.maxOutputChars ?? 2000;\n\n if (captureOutput) {\n const out = outcome.stdout ?? '';\n const err = outcome.stderr ?? '';\n cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);\n cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);\n }\n\n const completed = completeAuditEntry(entry, outcome.success, outcome.error);\n await logSkillExecution(completed);\n}\n\nexport async function runShellCommand(\n command: string,\n audit: CommandAuditContext,\n options?: RunCommandOptions\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr, startedAt }, options);\n return { stdout: stdout ?? '', stderr: stderr ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n // Capture output for failures by default (so audits are useful)\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, stderr, exitCode };\n }\n}\n\nexport function runShellCommandSync(\n command: string,\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): { stdout: string; exitCode: number } {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const stdout = execSync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Fire-and-forget write; sync APIs can’t await.\n void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: '', startedAt }, options);\n return { stdout: stdout ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; status?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.status === 'number' ? err.status : 1;\n\n void finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, exitCode };\n }\n}\n\nexport async function runExecFile(\n file: string,\n args: string[],\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const command = [file, ...args].join(' ');\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execFileAsync(file, args, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), startedAt }, options);\n return { stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n return { stdout, stderr, exitCode };\n }\n}\n\n","/**\n * Audit logger stub\n *\n * Audit functionality has been integrated into the decision ledger.\n * This module exists to keep legacy CLI/tooling paths working without the old skills system.\n */\n\nexport interface AuditStatistics {\n totalScans: number;\n totalIssues: number;\n criticalCount: number;\n seriousCount: number;\n moderateCount: number;\n lowCount: number;\n totalExecutions: number;\n successfulExecutions: number;\n failedExecutions: number;\n uniqueSkills: number;\n totalCommands: number;\n blockedCommands: number;\n totalNetworkCalls: number;\n blockedNetworkCalls: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n command: string;\n status: string;\n commands?: ExecutedCommand[];\n}\n\nexport interface ExecutedCommand {\n command: string;\n timestamp: string;\n exitCode?: number;\n duration?: number;\n stdout?: string;\n stderr?: string;\n}\n\nexport interface SkillExecution {\n skillName: string;\n skillSource: string;\n triggeredBy: 'scan' | 'mcp' | 'cli' | 'watch' | 'manual';\n targetPath: string;\n startedAt: string;\n completedAt?: string;\n success?: boolean;\n error?: string;\n commands?: ExecutedCommand[];\n}\n\nexport function formatAuditLog(_entry: AuditEntry): string {\n return 'Audit logging has been integrated into the decision ledger';\n}\n\nexport function getAuditStatistics(): AuditStatistics {\n return {\n totalScans: 0,\n totalIssues: 0,\n criticalCount: 0,\n seriousCount: 0,\n moderateCount: 0,\n lowCount: 0,\n totalExecutions: 0,\n successfulExecutions: 0,\n failedExecutions: 0,\n uniqueSkills: 0,\n totalCommands: 0,\n blockedCommands: 0,\n totalNetworkCalls: 0,\n blockedNetworkCalls: 0,\n };\n}\n\nexport function createAuditEntry(\n skillName: string,\n skillSource: string,\n triggeredBy: SkillExecution['triggeredBy'],\n targetPath: string\n): SkillExecution {\n return {\n skillName,\n skillSource,\n triggeredBy,\n targetPath,\n startedAt: new Date().toISOString(),\n commands: [],\n };\n}\n\nexport function completeAuditEntry(\n entry: SkillExecution,\n success: boolean,\n error?: string\n): SkillExecution {\n const result: SkillExecution = {\n ...entry,\n completedAt: new Date().toISOString(),\n success,\n };\n if (error !== undefined) {\n result.error = error;\n }\n return result;\n}\n\nexport async function logSkillExecution(_execution: SkillExecution): Promise<void> {\n // Stub - no-op\n}\n\nexport async function getRecentAuditLogs(_limit: number = 10): Promise<AuditEntry[]> {\n return [];\n}\n\nexport async function getSkillAuditLogs(_skillName: string): Promise<AuditEntry[]> {\n return [];\n}\n\n"],"mappings":"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","names":[]}
@@ -1,36 +0,0 @@
1
- // src/utils/atomic-write.ts
2
- import { writeFile, rename, unlink, mkdir } from "fs/promises";
3
- import { randomBytes } from "crypto";
4
- import { dirname } from "path";
5
- async function atomicWriteFile(filePath, data, options = {}) {
6
- const { createDir = true, encoding = "utf-8" } = options;
7
- const tempSuffix = randomBytes(6).toString("hex");
8
- const tempPath = `${filePath}.${tempSuffix}.tmp`;
9
- try {
10
- if (createDir) {
11
- await mkdir(dirname(filePath), { recursive: true });
12
- }
13
- if (typeof data === "string") {
14
- await writeFile(tempPath, data, { encoding });
15
- } else {
16
- await writeFile(tempPath, data);
17
- }
18
- await rename(tempPath, filePath);
19
- } catch (error) {
20
- try {
21
- await unlink(tempPath);
22
- } catch {
23
- }
24
- throw error;
25
- }
26
- }
27
- async function atomicWriteJSON(filePath, data, options = {}) {
28
- const { spaces = 2, ...writeOptions } = options;
29
- const json = JSON.stringify(data, null, spaces);
30
- await atomicWriteFile(filePath, json, writeOptions);
31
- }
32
-
33
- export {
34
- atomicWriteJSON
35
- };
36
- //# sourceMappingURL=chunk-43X6JBEM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/atomic-write.ts"],"sourcesContent":["/**\n * Atomic File Write Utility\n * \n * Provides safe file writes using the temp file + rename pattern.\n * Prevents data corruption from interrupted writes or crashes.\n * \n * Pattern:\n * 1. Write to a temporary file with random suffix\n * 2. Rename temp file to target path (atomic on POSIX systems)\n * 3. Clean up temp file on failure\n */\n\nimport { writeFile, rename, unlink, mkdir } from 'fs/promises';\nimport { randomBytes } from 'crypto';\nimport { dirname } from 'path';\n\nexport interface AtomicWriteOptions {\n /**\n * Create parent directories if they don't exist\n * @default true\n */\n createDir?: boolean;\n \n /**\n * File encoding for string data\n * @default 'utf-8'\n */\n encoding?: BufferEncoding;\n}\n\n/**\n * Write data to a file atomically\n * \n * Uses a temp file + rename pattern to ensure the target file\n * is never in a partially written state. On POSIX systems,\n * rename() is atomic, so readers will always see either the\n * old complete file or the new complete file.\n * \n * @param filePath - Target file path\n * @param data - Data to write (string or Buffer)\n * @param options - Write options\n * @throws Error if write or rename fails\n * \n * @example\n * ```typescript\n * await atomicWriteFile('/path/to/data.json', JSON.stringify(data, null, 2));\n * ```\n */\nexport async function atomicWriteFile(\n filePath: string,\n data: string | Buffer,\n options: AtomicWriteOptions = {}\n): Promise<void> {\n const { createDir = true, encoding = 'utf-8' } = options;\n \n // Generate a unique temp file path\n const tempSuffix = randomBytes(6).toString('hex');\n const tempPath = `${filePath}.${tempSuffix}.tmp`;\n \n try {\n // Ensure parent directory exists\n if (createDir) {\n await mkdir(dirname(filePath), { recursive: true });\n }\n \n // Write to temp file\n if (typeof data === 'string') {\n await writeFile(tempPath, data, { encoding });\n } else {\n await writeFile(tempPath, data);\n }\n \n // Atomic rename to target path\n await rename(tempPath, filePath);\n } catch (error) {\n // Clean up temp file on failure\n try {\n await unlink(tempPath);\n } catch {\n // Ignore cleanup errors - temp file might not exist\n }\n throw error;\n }\n}\n\n/**\n * Write JSON data to a file atomically\n * \n * Convenience wrapper that handles JSON serialization\n * with optional pretty printing.\n * \n * @param filePath - Target file path\n * @param data - Data to serialize as JSON\n * @param options - Write options and JSON formatting\n * @throws Error if serialization, write, or rename fails\n * \n * @example\n * ```typescript\n * await atomicWriteJSON('/path/to/config.json', { key: 'value' });\n * ```\n */\nexport async function atomicWriteJSON(\n filePath: string,\n data: unknown,\n options: AtomicWriteOptions & {\n /**\n * Spaces for JSON pretty printing\n * @default 2\n */\n spaces?: number;\n } = {}\n): Promise<void> {\n const { spaces = 2, ...writeOptions } = options;\n const json = JSON.stringify(data, null, spaces);\n await atomicWriteFile(filePath, json, writeOptions);\n}\n"],"mappings":";AAYA,SAAS,WAAW,QAAQ,QAAQ,aAAa;AACjD,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AAkCxB,eAAsB,gBACpB,UACA,MACA,UAA8B,CAAC,GAChB;AACf,QAAM,EAAE,YAAY,MAAM,WAAW,QAAQ,IAAI;AAGjD,QAAM,aAAa,YAAY,CAAC,EAAE,SAAS,KAAK;AAChD,QAAM,WAAW,GAAG,QAAQ,IAAI,UAAU;AAE1C,MAAI;AAEF,QAAI,WAAW;AACb,YAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,IACpD;AAGA,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,UAAU,UAAU,MAAM,EAAE,SAAS,CAAC;AAAA,IAC9C,OAAO;AACL,YAAM,UAAU,UAAU,IAAI;AAAA,IAChC;AAGA,UAAM,OAAO,UAAU,QAAQ;AAAA,EACjC,SAAS,OAAO;AAEd,QAAI;AACF,YAAM,OAAO,QAAQ;AAAA,IACvB,QAAQ;AAAA,IAER;AACA,UAAM;AAAA,EACR;AACF;AAkBA,eAAsB,gBACpB,UACA,MACA,UAMI,CAAC,GACU;AACf,QAAM,EAAE,SAAS,GAAG,GAAG,aAAa,IAAI;AACxC,QAAM,OAAO,KAAK,UAAU,MAAM,MAAM,MAAM;AAC9C,QAAM,gBAAgB,UAAU,MAAM,YAAY;AACpD;","names":[]}