atabey 0.0.13 → 0.0.15

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 (282) hide show
  1. package/ATABEY.md +1 -1
  2. package/PRIVACY.md +8 -14
  3. package/README.md +405 -56
  4. package/bin/cli.js +72 -5
  5. package/dist/framework-mcp/src/index.js +988 -63
  6. package/dist/framework-mcp/src/index.js.map +1 -1
  7. package/dist/framework-mcp/src/tools/compliance/mask_pii.d.ts +17 -0
  8. package/dist/framework-mcp/src/tools/compliance/mask_pii.js +56 -0
  9. package/dist/framework-mcp/src/tools/compliance/mask_pii.js.map +1 -0
  10. package/dist/framework-mcp/src/tools/definitions.js +10 -9
  11. package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
  12. package/dist/framework-mcp/src/tools/framework/run_tests.js +25 -0
  13. package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -1
  14. package/dist/framework-mcp/src/tools/index.js +7 -8
  15. package/dist/framework-mcp/src/tools/index.js.map +1 -1
  16. package/dist/framework-mcp/src/tools/messaging/approve_operation.d.ts +22 -0
  17. package/dist/framework-mcp/src/tools/messaging/approve_operation.js +81 -0
  18. package/dist/framework-mcp/src/tools/messaging/approve_operation.js.map +1 -0
  19. package/dist/framework-mcp/src/tools/messaging/ask_human.d.ts +15 -0
  20. package/dist/framework-mcp/src/tools/messaging/ask_human.js +89 -20
  21. package/dist/framework-mcp/src/tools/messaging/ask_human.js.map +1 -1
  22. package/dist/framework-mcp/src/tools/observability/check_ports.d.ts +1 -0
  23. package/dist/framework-mcp/src/tools/observability/check_ports.js +24 -8
  24. package/dist/framework-mcp/src/tools/observability/check_ports.js.map +1 -1
  25. package/dist/framework-mcp/src/tools/quality/analyze_code_quality.js +13 -64
  26. package/dist/framework-mcp/src/tools/quality/analyze_code_quality.js.map +1 -1
  27. package/dist/framework-mcp/src/tools/schemas.d.ts +48 -53
  28. package/dist/framework-mcp/src/tools/schemas.js +18 -22
  29. package/dist/framework-mcp/src/tools/schemas.js.map +1 -1
  30. package/dist/framework-mcp/src/tools/shell/run_command.js +146 -90
  31. package/dist/framework-mcp/src/tools/shell/run_command.js.map +1 -1
  32. package/dist/framework-mcp/src/tools/types.d.ts +11 -105
  33. package/dist/framework-mcp/src/tools/types.js +1 -0
  34. package/dist/framework-mcp/src/tools/types.js.map +1 -1
  35. package/dist/framework-mcp/src/utils/auth.d.ts +36 -0
  36. package/dist/framework-mcp/src/utils/auth.js +79 -0
  37. package/dist/framework-mcp/src/utils/auth.js.map +1 -0
  38. package/dist/framework-mcp/src/utils/auto-rollback.d.ts +71 -0
  39. package/dist/framework-mcp/src/utils/auto-rollback.js +266 -0
  40. package/dist/framework-mcp/src/utils/auto-rollback.js.map +1 -0
  41. package/dist/framework-mcp/src/utils/compliance.js +12 -4
  42. package/dist/framework-mcp/src/utils/compliance.js.map +1 -1
  43. package/dist/framework-mcp/src/utils/context-optimizer.d.ts +69 -0
  44. package/dist/framework-mcp/src/utils/context-optimizer.js +157 -0
  45. package/dist/framework-mcp/src/utils/context-optimizer.js.map +1 -0
  46. package/dist/framework-mcp/src/utils/discipline.d.ts +68 -0
  47. package/dist/framework-mcp/src/utils/discipline.js +218 -0
  48. package/dist/framework-mcp/src/utils/discipline.js.map +1 -0
  49. package/dist/framework-mcp/src/utils/finops.d.ts +143 -0
  50. package/dist/framework-mcp/src/utils/finops.js +326 -0
  51. package/dist/framework-mcp/src/utils/finops.js.map +1 -0
  52. package/dist/framework-mcp/src/utils/human-in-loop.d.ts +95 -0
  53. package/dist/framework-mcp/src/utils/human-in-loop.js +216 -0
  54. package/dist/framework-mcp/src/utils/human-in-loop.js.map +1 -0
  55. package/dist/framework-mcp/src/utils/license-scanner.d.ts +71 -0
  56. package/dist/framework-mcp/src/utils/license-scanner.js +284 -0
  57. package/dist/framework-mcp/src/utils/license-scanner.js.map +1 -0
  58. package/dist/framework-mcp/src/utils/loop-detector.d.ts +105 -0
  59. package/dist/framework-mcp/src/utils/loop-detector.js +362 -0
  60. package/dist/framework-mcp/src/utils/loop-detector.js.map +1 -0
  61. package/dist/framework-mcp/src/utils/quality.d.ts +19 -0
  62. package/dist/framework-mcp/src/utils/quality.js +125 -0
  63. package/dist/framework-mcp/src/utils/quality.js.map +1 -0
  64. package/dist/framework-mcp/src/utils/rules-engine.d.ts +78 -0
  65. package/dist/framework-mcp/src/utils/rules-engine.js +232 -0
  66. package/dist/framework-mcp/src/utils/rules-engine.js.map +1 -0
  67. package/dist/framework-mcp/src/utils/silent-router.d.ts +49 -0
  68. package/dist/framework-mcp/src/utils/silent-router.js +155 -0
  69. package/dist/framework-mcp/src/utils/silent-router.js.map +1 -0
  70. package/dist/framework-mcp/src/utils/storage.d.ts +1 -0
  71. package/dist/framework-mcp/src/utils/storage.js +2 -2
  72. package/dist/framework-mcp/src/utils/storage.js.map +1 -1
  73. package/dist/framework-mcp/src/utils/telemetry-streamer.d.ts +133 -0
  74. package/dist/framework-mcp/src/utils/telemetry-streamer.js +397 -0
  75. package/dist/framework-mcp/src/utils/telemetry-streamer.js.map +1 -0
  76. package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js +2 -2
  77. package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js.map +1 -1
  78. package/dist/framework-mcp/tests/tools/framework/run_tests.test.d.ts +1 -0
  79. package/dist/framework-mcp/tests/tools/framework/run_tests.test.js +49 -0
  80. package/dist/framework-mcp/tests/tools/framework/run_tests.test.js.map +1 -0
  81. package/dist/framework-mcp/tests/tools/messaging/send_message.test.js +14 -5
  82. package/dist/framework-mcp/tests/tools/messaging/send_message.test.js.map +1 -1
  83. package/dist/framework-mcp/tests/tools/observability/check_ports.test.d.ts +1 -0
  84. package/dist/framework-mcp/tests/tools/observability/check_ports.test.js +44 -0
  85. package/dist/framework-mcp/tests/tools/observability/check_ports.test.js.map +1 -0
  86. package/dist/framework-mcp/tests/tools/shell/run_command.test.js +44 -14
  87. package/dist/framework-mcp/tests/tools/shell/run_command.test.js.map +1 -1
  88. package/dist/framework-mcp/tests/utils/auto-rollback.test.d.ts +7 -0
  89. package/dist/framework-mcp/tests/utils/auto-rollback.test.js +178 -0
  90. package/dist/framework-mcp/tests/utils/auto-rollback.test.js.map +1 -0
  91. package/dist/framework-mcp/tests/utils/context-optimizer.test.d.ts +1 -0
  92. package/dist/framework-mcp/tests/utils/context-optimizer.test.js +62 -0
  93. package/dist/framework-mcp/tests/utils/context-optimizer.test.js.map +1 -0
  94. package/dist/framework-mcp/tests/utils/finops.test.d.ts +7 -0
  95. package/dist/framework-mcp/tests/utils/finops.test.js +157 -0
  96. package/dist/framework-mcp/tests/utils/finops.test.js.map +1 -0
  97. package/dist/framework-mcp/tests/utils/human-in-loop.test.d.ts +1 -0
  98. package/dist/framework-mcp/tests/utils/human-in-loop.test.js +59 -0
  99. package/dist/framework-mcp/tests/utils/human-in-loop.test.js.map +1 -0
  100. package/dist/framework-mcp/tests/utils/license-scanner.test.d.ts +7 -0
  101. package/dist/framework-mcp/tests/utils/license-scanner.test.js +131 -0
  102. package/dist/framework-mcp/tests/utils/license-scanner.test.js.map +1 -0
  103. package/dist/framework-mcp/tests/utils/loop-detector.test.d.ts +7 -0
  104. package/dist/framework-mcp/tests/utils/loop-detector.test.js +204 -0
  105. package/dist/framework-mcp/tests/utils/loop-detector.test.js.map +1 -0
  106. package/dist/framework-mcp/tests/utils/rules-engine.test.d.ts +1 -0
  107. package/dist/framework-mcp/tests/utils/rules-engine.test.js +106 -0
  108. package/dist/framework-mcp/tests/utils/rules-engine.test.js.map +1 -0
  109. package/dist/framework-mcp/tests/utils/telemetry-streamer.test.d.ts +7 -0
  110. package/dist/framework-mcp/tests/utils/telemetry-streamer.test.js +201 -0
  111. package/dist/framework-mcp/tests/utils/telemetry-streamer.test.js.map +1 -0
  112. package/dist/src/cli/commands/check.js +16 -1
  113. package/dist/src/cli/commands/check.js.map +1 -1
  114. package/dist/src/cli/commands/dashboard.js +188 -164
  115. package/dist/src/cli/commands/dashboard.js.map +1 -1
  116. package/dist/src/cli/commands/gateway.js +2 -2
  117. package/dist/src/cli/commands/gateway.js.map +1 -1
  118. package/dist/src/cli/commands/init/scaffold-core.d.ts +2 -0
  119. package/dist/src/cli/commands/init/scaffold-core.js +16 -1
  120. package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
  121. package/dist/src/cli/commands/init/scaffold-ops.js +2 -2
  122. package/dist/src/cli/commands/init/scaffold-ops.js.map +1 -1
  123. package/dist/src/cli/commands/init/scaffold-standards.js +13 -1
  124. package/dist/src/cli/commands/init/scaffold-standards.js.map +1 -1
  125. package/dist/src/cli/commands/init.d.ts +4 -0
  126. package/dist/src/cli/commands/init.js +94 -31
  127. package/dist/src/cli/commands/init.js.map +1 -1
  128. package/dist/src/cli/commands/mcp.js +3 -1
  129. package/dist/src/cli/commands/mcp.js.map +1 -1
  130. package/dist/src/cli/commands/quickstart.d.ts +1 -1
  131. package/dist/src/cli/commands/quickstart.js +12 -24
  132. package/dist/src/cli/commands/quickstart.js.map +1 -1
  133. package/dist/src/cli/commands/script.js +8 -1
  134. package/dist/src/cli/commands/script.js.map +1 -1
  135. package/dist/src/cli/index.js +24 -23
  136. package/dist/src/cli/index.js.map +1 -1
  137. package/dist/src/cli/shims.js +7 -7
  138. package/dist/src/cli/utils/pkg.js +2 -3
  139. package/dist/src/cli/utils/pkg.js.map +1 -1
  140. package/dist/src/cli/utils/quality.d.ts +10 -0
  141. package/dist/src/cli/utils/quality.js +10 -0
  142. package/dist/src/cli/utils/quality.js.map +1 -0
  143. package/dist/src/modules/agents/definitions.js +45 -40
  144. package/dist/src/modules/agents/definitions.js.map +1 -1
  145. package/dist/src/modules/agents/registry/manager.js +6 -1
  146. package/dist/src/modules/agents/registry/manager.js.map +1 -1
  147. package/dist/src/modules/engines/agent-executor.d.ts +6 -10
  148. package/dist/src/modules/engines/agent-executor.js +63 -21
  149. package/dist/src/modules/engines/agent-executor.js.map +1 -1
  150. package/dist/src/modules/engines/agent-loop.d.ts +34 -0
  151. package/dist/src/modules/engines/agent-loop.js +102 -0
  152. package/dist/src/modules/engines/agent-loop.js.map +1 -0
  153. package/dist/src/modules/engines/evaluation-engine.d.ts +12 -2
  154. package/dist/src/modules/engines/evaluation-engine.js +78 -11
  155. package/dist/src/modules/engines/evaluation-engine.js.map +1 -1
  156. package/dist/src/modules/engines/quality-gate.d.ts +13 -5
  157. package/dist/src/modules/engines/quality-gate.js +39 -31
  158. package/dist/src/modules/engines/quality-gate.js.map +1 -1
  159. package/dist/src/modules/engines/routing-engine.d.ts +5 -3
  160. package/dist/src/modules/engines/routing-engine.js +16 -9
  161. package/dist/src/modules/engines/routing-engine.js.map +1 -1
  162. package/dist/src/modules/gateway/cost-tracker.d.ts +5 -0
  163. package/dist/src/modules/gateway/cost-tracker.js +71 -0
  164. package/dist/src/modules/gateway/cost-tracker.js.map +1 -1
  165. package/dist/src/modules/gateway/gateway.d.ts +4 -0
  166. package/dist/src/modules/gateway/gateway.js +8 -0
  167. package/dist/src/modules/gateway/gateway.js.map +1 -1
  168. package/dist/src/shared/audit.js +3 -2
  169. package/dist/src/shared/audit.js.map +1 -1
  170. package/dist/src/shared/pii.d.ts +41 -9
  171. package/dist/src/shared/pii.js +122 -31
  172. package/dist/src/shared/pii.js.map +1 -1
  173. package/dist/src/shared/storage.d.ts +62 -0
  174. package/dist/src/shared/storage.js +47 -7
  175. package/dist/src/shared/storage.js.map +1 -1
  176. package/dist/tests/embedding.test.d.ts +1 -0
  177. package/dist/tests/embedding.test.js +82 -0
  178. package/dist/tests/embedding.test.js.map +1 -0
  179. package/dist/tests/engines/evaluation-engine.test.d.ts +1 -0
  180. package/dist/tests/engines/evaluation-engine.test.js +71 -0
  181. package/dist/tests/engines/evaluation-engine.test.js.map +1 -0
  182. package/dist/tests/engines/planning-engine.test.d.ts +1 -0
  183. package/dist/tests/engines/planning-engine.test.js +100 -0
  184. package/dist/tests/engines/planning-engine.test.js.map +1 -0
  185. package/dist/tests/engines/quality-gate.test.d.ts +1 -0
  186. package/dist/tests/engines/quality-gate.test.js +59 -0
  187. package/dist/tests/engines/quality-gate.test.js.map +1 -0
  188. package/dist/tests/engines/risk-engine.test.d.ts +1 -0
  189. package/dist/tests/engines/risk-engine.test.js +80 -0
  190. package/dist/tests/engines/risk-engine.test.js.map +1 -0
  191. package/dist/tests/engines/routing-engine.test.d.ts +1 -0
  192. package/dist/tests/engines/routing-engine.test.js +78 -0
  193. package/dist/tests/engines/routing-engine.test.js.map +1 -0
  194. package/dist/tests/integration/hermes_locking.test.js +1 -0
  195. package/dist/tests/integration/hermes_locking.test.js.map +1 -1
  196. package/dist/tests/modules/engines/agent-executor.test.js +1 -1
  197. package/dist/tests/modules/engines/agent-executor.test.js.map +1 -1
  198. package/dist/tests/modules/gateway/cost-tracker.test.js +20 -1
  199. package/dist/tests/modules/gateway/cost-tracker.test.js.map +1 -1
  200. package/dist/tests/shared/lock.test.d.ts +1 -0
  201. package/dist/tests/shared/lock.test.js +95 -0
  202. package/dist/tests/shared/lock.test.js.map +1 -0
  203. package/dist/tests/shared/pii.test.d.ts +1 -0
  204. package/dist/tests/shared/pii.test.js +183 -0
  205. package/dist/tests/shared/pii.test.js.map +1 -0
  206. package/framework-mcp/README.md +307 -35
  207. package/framework-mcp/dist/dashboard/assets/index-B_rK57vi.js +1221 -0
  208. package/framework-mcp/dist/dashboard/index.html +1 -1
  209. package/framework-mcp/dist/framework-mcp/src/index.js +988 -63
  210. package/framework-mcp/dist/framework-mcp/src/tools/compliance/mask_pii.js +55 -0
  211. package/framework-mcp/dist/framework-mcp/src/tools/definitions.js +10 -9
  212. package/framework-mcp/dist/framework-mcp/src/tools/framework/run_tests.js +25 -0
  213. package/framework-mcp/dist/framework-mcp/src/tools/index.js +7 -8
  214. package/framework-mcp/dist/framework-mcp/src/tools/messaging/approve_operation.js +80 -0
  215. package/framework-mcp/dist/framework-mcp/src/tools/messaging/ask_human.js +89 -20
  216. package/framework-mcp/dist/framework-mcp/src/tools/observability/check_ports.js +24 -8
  217. package/framework-mcp/dist/framework-mcp/src/tools/quality/analyze_code_quality.js +13 -64
  218. package/framework-mcp/dist/framework-mcp/src/tools/schemas.js +18 -22
  219. package/framework-mcp/dist/framework-mcp/src/tools/shell/run_command.js +146 -90
  220. package/framework-mcp/dist/framework-mcp/src/tools/types.js +1 -0
  221. package/framework-mcp/dist/framework-mcp/src/utils/auth.js +78 -0
  222. package/framework-mcp/dist/framework-mcp/src/utils/auto-rollback.js +265 -0
  223. package/framework-mcp/dist/framework-mcp/src/utils/compliance.js +12 -4
  224. package/framework-mcp/dist/framework-mcp/src/utils/context-optimizer.js +156 -0
  225. package/framework-mcp/dist/framework-mcp/src/utils/discipline.js +217 -0
  226. package/framework-mcp/dist/framework-mcp/src/utils/finops.js +325 -0
  227. package/framework-mcp/dist/framework-mcp/src/utils/human-in-loop.js +215 -0
  228. package/framework-mcp/dist/framework-mcp/src/utils/license-scanner.js +283 -0
  229. package/framework-mcp/dist/framework-mcp/src/utils/loop-detector.js +361 -0
  230. package/framework-mcp/dist/framework-mcp/src/utils/quality.js +124 -0
  231. package/framework-mcp/dist/framework-mcp/src/utils/rules-engine.js +231 -0
  232. package/framework-mcp/dist/framework-mcp/src/utils/silent-router.js +154 -0
  233. package/framework-mcp/dist/framework-mcp/src/utils/storage.js +2 -2
  234. package/framework-mcp/dist/framework-mcp/src/utils/telemetry-streamer.js +396 -0
  235. package/framework-mcp/dist/src/cli/platforms/core.js +72 -0
  236. package/framework-mcp/dist/src/cli/platforms/index.js +5 -0
  237. package/framework-mcp/dist/src/cli/platforms/paths.js +101 -0
  238. package/framework-mcp/dist/src/cli/platforms/scaffold.js +72 -0
  239. package/framework-mcp/dist/src/cli/platforms/utils.js +75 -0
  240. package/framework-mcp/dist/src/cli/utils/claude.js +57 -0
  241. package/framework-mcp/dist/src/cli/utils/compliance.js +12 -0
  242. package/framework-mcp/dist/src/cli/utils/fs.js +138 -0
  243. package/framework-mcp/dist/src/cli/utils/pkg.js +282 -0
  244. package/framework-mcp/dist/src/cli/utils/quality.js +9 -0
  245. package/framework-mcp/dist/src/modules/agents/definitions.js +563 -0
  246. package/framework-mcp/dist/src/modules/agents/registry/analyst.js +39 -0
  247. package/framework-mcp/dist/src/modules/agents/registry/architect.js +42 -0
  248. package/framework-mcp/dist/src/modules/agents/registry/backend.js +50 -0
  249. package/framework-mcp/dist/src/modules/agents/registry/database.js +45 -0
  250. package/framework-mcp/dist/src/modules/agents/registry/devops.js +45 -0
  251. package/framework-mcp/dist/src/modules/agents/registry/explorer.js +37 -0
  252. package/framework-mcp/dist/src/modules/agents/registry/frontend.js +52 -0
  253. package/framework-mcp/dist/src/modules/agents/registry/git.js +36 -0
  254. package/framework-mcp/dist/src/modules/agents/registry/manager.js +64 -0
  255. package/framework-mcp/dist/src/modules/agents/registry/mobile.js +41 -0
  256. package/framework-mcp/dist/src/modules/agents/registry/native.js +41 -0
  257. package/framework-mcp/dist/src/modules/agents/registry/quality.js +43 -0
  258. package/framework-mcp/dist/src/modules/agents/registry/security.js +42 -0
  259. package/framework-mcp/dist/src/modules/agents/types.js +1 -0
  260. package/framework-mcp/dist/src/modules/engines/evaluation-engine.js +169 -0
  261. package/framework-mcp/dist/src/modules/engines/quality-gate.js +92 -0
  262. package/framework-mcp/dist/src/modules/engines/risk-engine.js +105 -0
  263. package/framework-mcp/dist/src/modules/engines/routing-engine.js +408 -0
  264. package/framework-mcp/dist/src/modules/engines/types.js +1 -0
  265. package/framework-mcp/dist/src/modules/providers/definitions.js +140 -0
  266. package/framework-mcp/dist/src/modules/providers/registry.js +18 -0
  267. package/framework-mcp/dist/src/modules/providers/shared.js +104 -0
  268. package/framework-mcp/dist/src/modules/providers/types.js +1 -0
  269. package/framework-mcp/dist/src/modules/skills/adapter-skills.js +449 -0
  270. package/framework-mcp/dist/src/modules/skills/definitions.js +70 -0
  271. package/framework-mcp/dist/src/shared/audit.js +220 -0
  272. package/framework-mcp/dist/src/shared/errors.js +68 -0
  273. package/framework-mcp/dist/src/shared/lock.js +159 -0
  274. package/framework-mcp/dist/src/shared/pii.js +122 -31
  275. package/framework-mcp/dist/src/shared/retention.js +170 -0
  276. package/framework-mcp/dist/src/shared/storage.js +47 -7
  277. package/framework-mcp/dist/src/shared/string.js +29 -0
  278. package/framework-mcp/package.json +8 -2
  279. package/mcp.json +12 -6
  280. package/package.json +11 -5
  281. package/templates/full/ATABEY_FULL.md +1 -1
  282. package/framework-mcp/dist/dashboard/assets/index-BAPGLiWE.js +0 -267
@@ -1,107 +1,162 @@
1
- import { exec } from "child_process";
1
+ import { spawn } from "child_process";
2
2
  import { Metrics } from "../../utils/metrics.js";
3
+ // Each entry defines the executable and its allowed args prefix
3
4
  const COMMAND_ALLOW_LIST = [
4
5
  // Package managers
5
- "npm test",
6
- "npm run",
7
- "npm install",
8
- "npm ci",
9
- "npm audit",
10
- "npx vitest",
11
- "npx tsc",
12
- "npx eslint",
13
- "yarn test",
14
- "yarn run",
15
- "yarn install",
16
- "pnpm test",
17
- "pnpm run",
18
- "pnpm install",
6
+ { cmd: "npm", args: ["test"] },
7
+ { cmd: "npm", args: ["run"] },
8
+ { cmd: "npm", args: ["install"] },
9
+ { cmd: "npm", args: ["ci"] },
10
+ { cmd: "npm", args: ["audit"] },
11
+ { cmd: "npx", args: ["vitest"] },
12
+ { cmd: "npx", args: ["tsc"] },
13
+ { cmd: "npx", args: ["eslint"] },
14
+ { cmd: "yarn", args: ["test"] },
15
+ { cmd: "yarn", args: ["run"] },
16
+ { cmd: "yarn", args: ["install"] },
17
+ { cmd: "pnpm", args: ["test"] },
18
+ { cmd: "pnpm", args: ["run"] },
19
+ { cmd: "pnpm", args: ["install"] },
19
20
  // Git
20
- "git status",
21
- "git diff",
22
- "git log",
23
- "git branch",
24
- "git stash",
25
- "git add",
26
- "git commit",
27
- "git push",
28
- "git pull",
29
- "git fetch",
30
- "git merge",
31
- "git rebase",
32
- "git checkout",
33
- "git reset",
21
+ { cmd: "git", args: ["status"] },
22
+ { cmd: "git", args: ["diff"] },
23
+ { cmd: "git", args: ["log"] },
24
+ { cmd: "git", args: ["branch"] },
25
+ { cmd: "git", args: ["stash"] },
26
+ { cmd: "git", args: ["add"] },
27
+ { cmd: "git", args: ["commit"] },
28
+ { cmd: "git", args: ["push"] },
29
+ { cmd: "git", args: ["pull"] },
30
+ { cmd: "git", args: ["fetch"] },
31
+ { cmd: "git", args: ["merge"] },
32
+ { cmd: "git", args: ["rebase"] },
33
+ { cmd: "git", args: ["checkout"] },
34
+ { cmd: "git", args: ["reset"] },
34
35
  // Build tools
35
- "npm run build",
36
- "npx tsc",
37
- "npx vite build",
38
- "npx webpack",
39
- "npx rollup",
40
- "npx esbuild",
41
- "make",
42
- "cmake",
43
- "dotnet test",
44
- "dotnet format",
45
- "dotnet build",
46
- "dotnet run",
47
- "dotnet restore",
48
- "go test",
49
- "go fmt",
50
- "go build",
51
- "go run",
52
- "go vet",
53
- "go mod",
54
- "pytest",
55
- "ruff check",
56
- "ruff format",
57
- "mvn",
58
- "./gradlew",
59
- "cargo test",
60
- "cargo build",
61
- "cargo check",
62
- "cargo fmt",
63
- // File operations (safe) — NOTE: "rm -rf" and "rm -r" intentionally excluded.
64
- // Only "rmdir" is allowed to prevent dangerous commands like "rm -rf /".
65
- "mkdir",
66
- "cp",
67
- "mv",
68
- "rmdir",
69
- "cat",
70
- "ls",
71
- "touch",
72
- "head",
73
- "tail",
74
- "wc",
75
- "grep",
76
- "find",
77
- "sort",
78
- "uniq",
79
- "echo",
80
- "pwd",
81
- "which",
82
- "file",
83
- "du",
84
- "df",
36
+ { cmd: "make" },
37
+ { cmd: "cmake" },
38
+ { cmd: "dotnet", args: ["test"] },
39
+ { cmd: "dotnet", args: ["format"] },
40
+ { cmd: "dotnet", args: ["build"] },
41
+ { cmd: "dotnet", args: ["run"] },
42
+ { cmd: "dotnet", args: ["restore"] },
43
+ { cmd: "go", args: ["test"] },
44
+ { cmd: "go", args: ["fmt"] },
45
+ { cmd: "go", args: ["build"] },
46
+ { cmd: "go", args: ["run"] },
47
+ { cmd: "go", args: ["vet"] },
48
+ { cmd: "go", args: ["mod"] },
49
+ { cmd: "pytest" },
50
+ { cmd: "ruff", args: ["check"] },
51
+ { cmd: "ruff", args: ["format"] },
52
+ { cmd: "mvn" },
53
+ { cmd: "./gradlew" },
54
+ { cmd: "cargo", args: ["test"] },
55
+ { cmd: "cargo", args: ["build"] },
56
+ { cmd: "cargo", args: ["check"] },
57
+ { cmd: "cargo", args: ["fmt"] },
58
+ // File operations (safe) — spawn prevents shell injection
59
+ { cmd: "mkdir" },
60
+ { cmd: "cp" },
61
+ { cmd: "mv" },
62
+ { cmd: "rmdir" },
63
+ { cmd: "cat" },
64
+ { cmd: "ls" },
65
+ { cmd: "touch" },
66
+ { cmd: "head" },
67
+ { cmd: "tail" },
68
+ { cmd: "wc" },
69
+ { cmd: "grep" },
70
+ { cmd: "find" },
71
+ { cmd: "sort" },
72
+ { cmd: "uniq" },
73
+ { cmd: "echo" },
74
+ { cmd: "pwd" },
75
+ { cmd: "which" },
76
+ { cmd: "file" },
77
+ { cmd: "du" },
78
+ { cmd: "df" },
85
79
  ];
86
80
  const TIMEOUT = 30000; // 30 seconds
81
+ /**
82
+ * Parse a command string into executable + args array.
83
+ * Uses spawn for safety (no shell injection).
84
+ */
85
+ function parseCommand(cmdString) {
86
+ const parts = cmdString.trim().split(/\s+/);
87
+ if (parts.length === 0)
88
+ return null;
89
+ return { cmd: parts[0], args: parts.slice(1) };
90
+ }
91
+ /**
92
+ * Check if a parsed command matches the allow list.
93
+ */
94
+ function isAllowed(parsed) {
95
+ return COMMAND_ALLOW_LIST.some(entry => {
96
+ if (entry.cmd !== parsed.cmd)
97
+ return false;
98
+ if (!entry.args)
99
+ return true; // Any args allowed for this cmd
100
+ if (!parsed.args || parsed.args.length < entry.args.length)
101
+ return false;
102
+ // Check that args start with the allowed prefix
103
+ return entry.args.every((arg, i) => parsed.args[i] === arg);
104
+ });
105
+ }
87
106
  export function handleRunCommand(projectRoot, args) {
88
107
  const command = args.command;
89
- const isAllowed = COMMAND_ALLOW_LIST.some(allowedCmd => command.startsWith(allowedCmd));
90
- if (!isAllowed) {
91
- const errorMsg = `Command not allowed: "${command}". Only commands starting with the following are allowed: ${COMMAND_ALLOW_LIST.join(", ")}`;
108
+ // Parse command into executable + args
109
+ const parsed = parseCommand(command);
110
+ if (!parsed) {
111
+ return Promise.resolve({
112
+ content: [{ type: "text", text: "ERROR: Empty command." }],
113
+ isError: true,
114
+ });
115
+ }
116
+ if (!isAllowed(parsed)) {
117
+ const allowedList = COMMAND_ALLOW_LIST.map(e => e.args ? `${e.cmd} ${e.args.join(" ")}` : e.cmd);
118
+ const errorMsg = `Command not allowed: "${command}". Only the following are allowed: ${allowedList.join(", ")}`;
92
119
  Metrics.logError(projectRoot, "@mcp", `run_shell_command: ${command} (denied)`, errorMsg);
93
120
  return Promise.resolve({
94
121
  content: [{ type: "text", text: `ERROR: ${errorMsg}` }],
95
122
  isError: true,
96
123
  });
97
124
  }
125
+ // Reject any args containing shell metacharacters
126
+ const hasShellMetacharacters = parsed.args.some(a => /[;&|><$`\n\r]/.test(a));
127
+ if (hasShellMetacharacters) {
128
+ const errorMsg = "Command rejected: Shell metacharacters are forbidden to prevent command injection.";
129
+ Metrics.logError(projectRoot, "@mcp", `run_shell_command: ${command} (denied: metacharacters)`, errorMsg);
130
+ return Promise.resolve({
131
+ content: [{ type: "text", text: `ERROR: ${errorMsg}` }],
132
+ isError: true,
133
+ });
134
+ }
98
135
  return new Promise((resolve) => {
99
- exec(command, { cwd: projectRoot, timeout: TIMEOUT }, (error, stdout, stderr) => {
136
+ const child = spawn(parsed.cmd, parsed.args, {
137
+ cwd: projectRoot,
138
+ timeout: TIMEOUT,
139
+ shell: false,
140
+ stdio: ["ignore", "pipe", "pipe"],
141
+ });
142
+ let stdout = "";
143
+ let stderr = "";
144
+ child.stdout.on("data", (data) => { stdout += data.toString(); });
145
+ child.stderr.on("data", (data) => { stderr += data.toString(); });
146
+ child.on("error", (err) => {
147
+ const errorMsg = `Failed to start command: ${err.message}`;
148
+ Metrics.logError(projectRoot, "@mcp", `run_shell_command: ${command}`, errorMsg);
149
+ resolve({
150
+ content: [{ type: "text", text: `ERROR: ${errorMsg}` }],
151
+ isError: true,
152
+ });
153
+ });
154
+ child.on("close", (code) => {
100
155
  const output = stdout + stderr;
101
156
  const tokens = Metrics.estimateTokens(output);
102
157
  Metrics.logUsage(projectRoot, "@mcp", `run_shell_command: ${command}`, tokens);
103
- if (error) {
104
- const errorMsg = `Command failed with exit code ${error.code}: ${error.message}.`;
158
+ if (code !== 0) {
159
+ const errorMsg = `Command failed with exit code ${code}.`;
105
160
  Metrics.logError(projectRoot, "@mcp", `run_shell_command: ${command}`, errorMsg);
106
161
  resolve({
107
162
  content: [{ type: "text", text: `ERROR: ${errorMsg}. Output: ${output}` }],
@@ -111,11 +166,12 @@ export function handleRunCommand(projectRoot, args) {
111
166
  }
112
167
  // Truncate long outputs
113
168
  const MAX_OUTPUT_LENGTH = 5000;
114
- let truncatedOutput = output;
115
- if (output.length > MAX_OUTPUT_LENGTH) {
116
- truncatedOutput = output.substring(0, MAX_OUTPUT_LENGTH) + "... [TRUNCATED] ..."; // Simplified
117
- }
118
- resolve({ content: [{ type: "text", text: truncatedOutput }] });
169
+ const truncatedOutput = output.length > MAX_OUTPUT_LENGTH
170
+ ? output.substring(0, MAX_OUTPUT_LENGTH) + "... [TRUNCATED] ..."
171
+ : output;
172
+ resolve({
173
+ content: [{ type: "text", text: truncatedOutput }],
174
+ });
119
175
  });
120
176
  });
121
177
  }
@@ -1 +1,2 @@
1
+ // Import types locally for ToolArgs union usage
1
2
  export {};
@@ -0,0 +1,78 @@
1
+ /**
2
+ * ─── MCP AUTHENTICATION ──────────────────────────────────────────
3
+ *
4
+ * Simple API key authentication for MCP server.
5
+ * When MCP_AUTH_TOKEN is set, all MCP and API requests require
6
+ * Authorization: Bearer <token> header.
7
+ *
8
+ * Environment Variables:
9
+ * MCP_AUTH_TOKEN - API key for authentication (optional)
10
+ * MCP_AUTH_USERS - Comma-separated list of user:token pairs (optional)
11
+ * Example: "alice:key1,bob:key2"
12
+ *
13
+ * If neither is set, authentication is disabled (open access).
14
+ */
15
+ let authUsers = [];
16
+ let masterToken = null;
17
+ /**
18
+ * Initialize authentication from environment variables.
19
+ */
20
+ export function initAuth() {
21
+ masterToken = process.env.MCP_AUTH_TOKEN || null;
22
+ const usersStr = process.env.MCP_AUTH_USERS || "";
23
+ if (usersStr) {
24
+ authUsers = usersStr.split(",").map(pair => {
25
+ const [name, token] = pair.split(":");
26
+ return { name: name?.trim() || "unknown", token: token?.trim() || "" };
27
+ }).filter(u => u.token);
28
+ }
29
+ if (masterToken) {
30
+ process.stderr.write(`[AUTH] Master token configured (${masterToken.length} chars)\n`);
31
+ }
32
+ if (authUsers.length > 0) {
33
+ process.stderr.write(`[AUTH] ${authUsers.length} user(s) configured: ${authUsers.map(u => u.name).join(", ")}\n`);
34
+ }
35
+ if (!masterToken && authUsers.length === 0) {
36
+ process.stderr.write("[AUTH] No authentication configured - OPEN ACCESS\n");
37
+ process.stderr.write("[AUTH] Set MCP_AUTH_TOKEN=<key> or MCP_AUTH_USERS=user1:key1,user2:key2 to enable\n");
38
+ }
39
+ }
40
+ /**
41
+ * Authenticate a request using the Authorization header.
42
+ * Returns the authenticated user name or null if unauthorized.
43
+ */
44
+ export function authenticate(req) {
45
+ if (!masterToken && authUsers.length === 0) {
46
+ // Auth disabled - allow all
47
+ return { authenticated: true, user: "anonymous" };
48
+ }
49
+ const authHeader = req.headers["authorization"];
50
+ if (!authHeader) {
51
+ return { authenticated: false, user: "" };
52
+ }
53
+ // Support both "Bearer <key>" and "<key>" formats
54
+ const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : authHeader;
55
+ // Check master token first
56
+ if (masterToken && token === masterToken) {
57
+ return { authenticated: true, user: "admin" };
58
+ }
59
+ // Check user tokens
60
+ for (const user of authUsers) {
61
+ if (token === user.token) {
62
+ return { authenticated: true, user: user.name };
63
+ }
64
+ }
65
+ return { authenticated: false, user: "" };
66
+ }
67
+ /**
68
+ * Generate authentication headers for MCP client configuration.
69
+ */
70
+ export function getAuthHeader(user, token) {
71
+ return `Bearer ${token}`;
72
+ }
73
+ /**
74
+ * Check if authentication is enabled.
75
+ */
76
+ export function isAuthEnabled() {
77
+ return !!masterToken || authUsers.length > 0;
78
+ }
@@ -0,0 +1,265 @@
1
+ /**
2
+ * ─── AUTO-ROLLBACK + REGENERATE ───────────────────────────────────
3
+ *
4
+ * When the AI generates code that violates governance rules (e.g., `any` type,
5
+ * console.log, copyleft license), this module:
6
+ * 1. Captures the file content before the write
7
+ * 2. Validates the new content against governance rules
8
+ * 3. If violation found: blocks the write, restores original, and sends
9
+ * a regenerate instruction back to the AI via MCP notification
10
+ *
11
+ * Flow:
12
+ * [Pre-Write Snapshot] → [Validate Content] → [Violation?] ─yes→ [Rollback] → [Notify AI]
13
+ * └─no─→ [Allow Write]
14
+ *
15
+ * Key Innovation: Unlike simple blocking, this tells the AI WHY it was
16
+ * blocked and gives it specific instructions to self-correct.
17
+ */
18
+ import fs from "fs";
19
+ import path from "path";
20
+ class SnapshotManager {
21
+ snapshots = new Map();
22
+ /**
23
+ * Capture a pre-write snapshot of a file.
24
+ */
25
+ capture(filePath, traceId) {
26
+ const resolvedPath = path.resolve(filePath);
27
+ let originalContent = null;
28
+ try {
29
+ if (fs.existsSync(resolvedPath)) {
30
+ originalContent = fs.readFileSync(resolvedPath, "utf8");
31
+ }
32
+ }
33
+ catch { /* file doesn't exist yet (new file) */ }
34
+ this.snapshots.set(resolvedPath, {
35
+ filePath: resolvedPath,
36
+ originalContent,
37
+ timestamp: Date.now(),
38
+ traceId,
39
+ restored: false,
40
+ });
41
+ }
42
+ /**
43
+ * Get a snapshot for a file.
44
+ */
45
+ get(filePath) {
46
+ return this.snapshots.get(path.resolve(filePath));
47
+ }
48
+ /**
49
+ * Restore a file to its pre-write state.
50
+ * Returns true if restored, false if no snapshot exists.
51
+ */
52
+ restore(filePath) {
53
+ const resolvedPath = path.resolve(filePath);
54
+ const snapshot = this.snapshots.get(resolvedPath);
55
+ if (!snapshot || snapshot.restored)
56
+ return false;
57
+ try {
58
+ if (snapshot.originalContent !== null) {
59
+ // File existed before – restore original
60
+ fs.writeFileSync(resolvedPath, snapshot.originalContent, "utf8");
61
+ process.stderr.write(`[ROLLBACK] Restored: ${path.relative(process.cwd(), resolvedPath)}\n`);
62
+ }
63
+ else {
64
+ // File was new – delete it
65
+ if (fs.existsSync(resolvedPath)) {
66
+ fs.unlinkSync(resolvedPath);
67
+ process.stderr.write(`[ROLLBACK] Deleted (new file): ${path.relative(process.cwd(), resolvedPath)}\n`);
68
+ }
69
+ }
70
+ snapshot.restored = true;
71
+ return true;
72
+ }
73
+ catch (error) {
74
+ process.stderr.write(`[ROLLBACK] Failed to restore ${resolvedPath}: ${error}\n`);
75
+ return false;
76
+ }
77
+ }
78
+ /**
79
+ * Clean up old snapshots.
80
+ */
81
+ cleanup(maxAgeMs = 300000) {
82
+ const cutoff = Date.now() - maxAgeMs;
83
+ for (const [filePath, snapshot] of this.snapshots) {
84
+ if (snapshot.timestamp < cutoff) {
85
+ this.snapshots.delete(filePath);
86
+ }
87
+ }
88
+ }
89
+ /**
90
+ * Get all active snapshots.
91
+ */
92
+ getAll() {
93
+ return Array.from(this.snapshots.values());
94
+ }
95
+ }
96
+ // ─── Auto-Rollback Engine ─────────────────────────────────────────
97
+ export class AutoRollback {
98
+ static snapshots = new SnapshotManager();
99
+ /**
100
+ * Initialize the auto-rollback system.
101
+ * Sets up file watcher cleanup.
102
+ */
103
+ static initialize() {
104
+ // Periodic cleanup of old snapshots (every 5 minutes)
105
+ setInterval(() => {
106
+ AutoRollback.snapshots.cleanup();
107
+ }, 300000);
108
+ }
109
+ /**
110
+ * Prepare for a file write by capturing the current state.
111
+ * Call this BEFORE the tool handler writes to the file.
112
+ */
113
+ static prepareWrite(filePath, traceId) {
114
+ AutoRollback.snapshots.capture(filePath, traceId);
115
+ }
116
+ /**
117
+ * Validate content and rollback if violations are found.
118
+ * This is called after the tool handler writes the file, but
119
+ * BEFORE the response is returned to the AI.
120
+ *
121
+ * Returns:
122
+ * - null if content is clean
123
+ * - ViolationRecord[] if violations were found and rolled back
124
+ */
125
+ static validateAndRollback(filePath, content, violations) {
126
+ if (violations.length === 0)
127
+ return null;
128
+ // Restore the original file
129
+ const restored = AutoRollback.snapshots.restore(filePath);
130
+ if (restored) {
131
+ process.stderr.write(`[ROLLBACK] Rolled back ${path.relative(process.cwd(), filePath)} due to ${violations.length} violation(s)\n`);
132
+ }
133
+ return violations;
134
+ }
135
+ /**
136
+ * Build a regenerate instruction for the AI.
137
+ * This is what gets sent back to the AI to tell it to fix its output.
138
+ */
139
+ static buildRegenerateInstruction(violations, toolName) {
140
+ const criticalViolations = violations.filter(v => v.severity === "CRITICAL");
141
+ const lines = [
142
+ "## ⛔ AI Output Blocked – Governance Violation",
143
+ "",
144
+ `The code you generated for tool "${toolName}" has been BLOCKED and ROLLED BACK.`,
145
+ "The file has been restored to its previous state.",
146
+ "",
147
+ ];
148
+ if (criticalViolations.length > 0) {
149
+ lines.push(`### 🔴 Critical Violations (${criticalViolations.length})`);
150
+ lines.push("");
151
+ for (const v of criticalViolations) {
152
+ lines.push(`- **${v.rule}** (${v.filePath}:${v.line})`);
153
+ lines.push(` - Detail: ${v.detail}`);
154
+ lines.push(` - Fix: ${v.regenerateInstruction}`);
155
+ lines.push("");
156
+ }
157
+ }
158
+ const otherViolations = violations.filter(v => v.severity !== "CRITICAL");
159
+ if (otherViolations.length > 0) {
160
+ lines.push(`### 🟠 Other Violations (${otherViolations.length})`);
161
+ lines.push("");
162
+ for (const v of otherViolations) {
163
+ lines.push(`- **${v.rule}** (${v.filePath}:${v.line})`);
164
+ lines.push(` - Detail: ${v.detail}`);
165
+ lines.push(` - Fix: ${v.regenerateInstruction}`);
166
+ lines.push("");
167
+ }
168
+ }
169
+ lines.push("---");
170
+ lines.push("> **Instruction:** Please regenerate the code for this operation.");
171
+ lines.push("> Address ALL violations listed above.");
172
+ lines.push("> Do NOT reintroduce the same violations.");
173
+ return lines.join("\n");
174
+ }
175
+ /**
176
+ * Validate tool response content against governance rules.
177
+ * Used by the MCP middleware to check file write content before returning.
178
+ */
179
+ static checkWriteContent(filePath, content, traceId) {
180
+ const ext = path.extname(filePath).toLowerCase();
181
+ const violations = [];
182
+ // Only check source files
183
+ if (![".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".java", ".rs", ".swift", ".kt"].includes(ext)) {
184
+ return { allowed: true, violations: [], instruction: null };
185
+ }
186
+ const lines = content.split("\n");
187
+ // 1. Check for `any` type (CRITICAL)
188
+ if ([".ts", ".tsx"].includes(ext)) {
189
+ for (let i = 0; i < lines.length; i++) {
190
+ const anyMatch = lines[i].match(/:\s*any\b/);
191
+ if (anyMatch) {
192
+ violations.push({
193
+ rule: "No `any` Type",
194
+ severity: "CRITICAL",
195
+ filePath,
196
+ line: i + 1,
197
+ detail: `Line ${i + 1}: ${anyMatch[0].substring(0, 60)}`,
198
+ regenerateInstruction: "Replace `any` with `unknown` and add proper type guards. Or use a specific interface/type.",
199
+ });
200
+ }
201
+ }
202
+ }
203
+ // 2. Check for console.log (CRITICAL)
204
+ for (let i = 0; i < lines.length; i++) {
205
+ const consoleMatch = lines[i].match(/console\.(log|error|warn|debug)\s*\(/);
206
+ if (consoleMatch) {
207
+ // Check if file is exempt
208
+ if (!filePath.includes("logger.ts") && !filePath.includes("cli.ts") && !filePath.includes("compliance.ts")) {
209
+ violations.push({
210
+ rule: "No Console Log",
211
+ severity: "CRITICAL",
212
+ filePath,
213
+ line: i + 1,
214
+ detail: `Line ${i + 1}: ${consoleMatch[0].substring(0, 60)}`,
215
+ regenerateInstruction: "Replace with the project's logger (import from the appropriate logger module).",
216
+ });
217
+ }
218
+ }
219
+ }
220
+ // 3. Check for hardcoded secrets (HIGH)
221
+ const secretPatterns = [
222
+ { pattern: /(['"])sk-[a-zA-Z0-9]{20,}['"]/, name: "OpenAI API Key" },
223
+ { pattern: /(['"])ghp_[a-zA-Z0-9]{36,}['"]/, name: "GitHub Token" },
224
+ { pattern: /(['"])AIza[0-9A-Za-z_-]{35}['"]/, name: "Google API Key" },
225
+ ];
226
+ for (let i = 0; i < lines.length; i++) {
227
+ for (const { pattern, name } of secretPatterns) {
228
+ if (pattern.test(lines[i])) {
229
+ violations.push({
230
+ rule: `Hardcoded Secret: ${name}`,
231
+ severity: "HIGH",
232
+ filePath,
233
+ line: i + 1,
234
+ detail: `Potential ${name} hardcoded at line ${i + 1}`,
235
+ regenerateInstruction: `Use environment variables (process.env.*) instead of hardcoding ${name}.`,
236
+ });
237
+ }
238
+ }
239
+ }
240
+ // If violations found, prepare snapshot and rollback
241
+ if (violations.length > 0) {
242
+ AutoRollback.prepareWrite(filePath, traceId);
243
+ const rolledBack = AutoRollback.validateAndRollback(filePath, content, violations);
244
+ const instruction = AutoRollback.buildRegenerateInstruction(violations, "write_file");
245
+ return {
246
+ allowed: false,
247
+ violations: rolledBack || violations,
248
+ instruction,
249
+ };
250
+ }
251
+ return { allowed: true, violations: [], instruction: null };
252
+ }
253
+ /**
254
+ * Get snapshot stats.
255
+ */
256
+ static getSnapshotStats() {
257
+ const all = AutoRollback.snapshots.getAll();
258
+ return {
259
+ total: all.length,
260
+ restored: all.filter(s => s.restored).length,
261
+ pending: all.filter(s => !s.restored).length,
262
+ };
263
+ }
264
+ }
265
+ export { AutoRollback as AutoRollbackEngine };
@@ -53,7 +53,14 @@ export function verifyCorporateCompliance(content, filePath) {
53
53
  }
54
54
  // 5. Secure CLI Policy (No direct child_process)
55
55
  if (moduleSpecifier.text === "child_process") {
56
- errors.push(`[ERROR] Corporate Compliance Breach: Direct 'child_process' usage is forbidden at line ${sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1}. Use secure framework APIs.`);
56
+ const isExempt = filePath.includes("src/cli/commands/") ||
57
+ filePath.includes("shared/fs.ts") ||
58
+ filePath.includes("shared/lock.ts") ||
59
+ filePath.includes("quality-gate.ts") ||
60
+ filePath.includes("providers/shared.ts");
61
+ if (!isExempt) {
62
+ errors.push(`[ERROR] Corporate Compliance Breach: Direct 'child_process' usage is forbidden at line ${sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1}. Use secure framework APIs.`);
63
+ }
57
64
  }
58
65
  }
59
66
  }
@@ -75,10 +82,11 @@ export function verifyCorporateCompliance(content, filePath) {
75
82
  const prop = node.expression;
76
83
  if (ts.isIdentifier(prop.expression) && prop.expression.text === "fs") {
77
84
  if (["writeFileSync", "appendFileSync"].includes(prop.name.text)) {
78
- // Lock files are exempt
85
+ // Lock files, core atomic fs wrapper, and mcp configs are exempt
79
86
  const args = node.arguments;
80
87
  const firstArgText = args.length > 0 ? args[0].getText(sourceFile).toLowerCase() : "";
81
- if (!firstArgText.includes("lock")) {
88
+ const isExemptFile = filePath.includes("shared/fs.ts") || filePath.includes("src/cli/commands/mcp.ts");
89
+ if (!firstArgText.includes("lock") && !isExemptFile) {
82
90
  errors.push(`[ERROR] Corporate Compliance Breach: Raw 'fs.${prop.name.text}' mutation detected at line ${sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1}. Use atomic utilities instead.`);
83
91
  }
84
92
  }
@@ -118,7 +126,7 @@ export function scanProjectCompliance(targetDir = "src") {
118
126
  const files = getAllFiles(targetDir);
119
127
  for (const file of files) {
120
128
  // Skip exempt files
121
- if (file.includes("compliance") || file.includes("definitions") || file.includes("logger") || file.includes("cli/index.ts"))
129
+ if (file.includes("compliance") || file.includes("definitions") || file.includes("logger") || file.includes("cli/index.ts") || file.includes("shared/fs.ts") || file.includes("shared/lock.ts"))
122
130
  continue;
123
131
  const content = fs.readFileSync(file, "utf8");
124
132
  try {