@stsepelin/checktrail 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/CONTRIBUTING.md +42 -0
  2. package/LICENSE +21 -0
  3. package/README.md +355 -0
  4. package/SECURITY.md +46 -0
  5. package/dist/src/actionlint-evidence.d.ts +2 -0
  6. package/dist/src/actionlint-evidence.js +166 -0
  7. package/dist/src/actionlint-inputs.d.ts +5 -0
  8. package/dist/src/actionlint-inputs.js +123 -0
  9. package/dist/src/actionlint-runner.d.ts +1 -0
  10. package/dist/src/actionlint-runner.js +122 -0
  11. package/dist/src/actionlint.d.ts +19 -0
  12. package/dist/src/actionlint.js +80 -0
  13. package/dist/src/adapters.d.ts +49 -0
  14. package/dist/src/adapters.js +430 -0
  15. package/dist/src/architecture.d.ts +107 -0
  16. package/dist/src/architecture.js +230 -0
  17. package/dist/src/clang-evidence.d.ts +2 -0
  18. package/dist/src/clang-evidence.js +194 -0
  19. package/dist/src/clang-protocol.d.ts +3 -0
  20. package/dist/src/clang-protocol.js +25 -0
  21. package/dist/src/clang-runner.d.ts +1 -0
  22. package/dist/src/clang-runner.js +159 -0
  23. package/dist/src/clang.d.ts +44 -0
  24. package/dist/src/clang.js +197 -0
  25. package/dist/src/cli.d.ts +2 -0
  26. package/dist/src/cli.js +338 -0
  27. package/dist/src/config.d.ts +33 -0
  28. package/dist/src/config.js +140 -0
  29. package/dist/src/contract-schema.d.ts +85 -0
  30. package/dist/src/contract-schema.js +56 -0
  31. package/dist/src/contract-worker.d.ts +1 -0
  32. package/dist/src/contract-worker.js +123 -0
  33. package/dist/src/contracts.d.ts +22 -0
  34. package/dist/src/contracts.js +123 -0
  35. package/dist/src/django-evidence.d.ts +2 -0
  36. package/dist/src/django-evidence.js +100 -0
  37. package/dist/src/django-runner.d.ts +1 -0
  38. package/dist/src/django-runner.js +80 -0
  39. package/dist/src/django.d.ts +9 -0
  40. package/dist/src/django.js +50 -0
  41. package/dist/src/dotnet-compiler.d.ts +1 -0
  42. package/dist/src/dotnet-compiler.js +87 -0
  43. package/dist/src/dotnet-evidence.d.ts +2 -0
  44. package/dist/src/dotnet-evidence.js +127 -0
  45. package/dist/src/dotnet-runner.d.ts +1 -0
  46. package/dist/src/dotnet-runner.js +167 -0
  47. package/dist/src/dotnet.d.ts +65 -0
  48. package/dist/src/dotnet.js +120 -0
  49. package/dist/src/engine.d.ts +19 -0
  50. package/dist/src/engine.js +239 -0
  51. package/dist/src/environment.d.ts +6 -0
  52. package/dist/src/environment.js +36 -0
  53. package/dist/src/eslint-evidence.d.ts +2 -0
  54. package/dist/src/eslint-evidence.js +98 -0
  55. package/dist/src/eslint-runner.d.ts +1 -0
  56. package/dist/src/eslint-runner.js +61 -0
  57. package/dist/src/eslint.d.ts +2 -0
  58. package/dist/src/eslint.js +40 -0
  59. package/dist/src/evidence.d.ts +2 -0
  60. package/dist/src/evidence.js +313 -0
  61. package/dist/src/external-adapter.d.ts +164 -0
  62. package/dist/src/external-adapter.js +265 -0
  63. package/dist/src/external-evidence.d.ts +2 -0
  64. package/dist/src/external-evidence.js +127 -0
  65. package/dist/src/external-runner.d.ts +1 -0
  66. package/dist/src/external-runner.js +122 -0
  67. package/dist/src/fastapi-evidence.d.ts +2 -0
  68. package/dist/src/fastapi-evidence.js +126 -0
  69. package/dist/src/fastapi-runner.d.ts +1 -0
  70. package/dist/src/fastapi-runner.js +84 -0
  71. package/dist/src/fastapi.d.ts +10 -0
  72. package/dist/src/fastapi.js +52 -0
  73. package/dist/src/fetch-pack.d.ts +16 -0
  74. package/dist/src/fetch-pack.js +154 -0
  75. package/dist/src/finding-policy-schema.d.ts +146 -0
  76. package/dist/src/finding-policy-schema.js +70 -0
  77. package/dist/src/finding-policy.d.ts +62 -0
  78. package/dist/src/finding-policy.js +206 -0
  79. package/dist/src/git-selection.d.ts +3 -0
  80. package/dist/src/git-selection.js +229 -0
  81. package/dist/src/go-directives.d.ts +1 -0
  82. package/dist/src/go-directives.js +32 -0
  83. package/dist/src/go-scope.d.ts +11 -0
  84. package/dist/src/go-scope.js +122 -0
  85. package/dist/src/golangci-evidence.d.ts +2 -0
  86. package/dist/src/golangci-evidence.js +92 -0
  87. package/dist/src/golangci-runner.d.ts +1 -0
  88. package/dist/src/golangci-runner.js +124 -0
  89. package/dist/src/golangci.d.ts +2 -0
  90. package/dist/src/golangci.js +35 -0
  91. package/dist/src/guidance.d.ts +98 -0
  92. package/dist/src/guidance.js +247 -0
  93. package/dist/src/index.d.ts +31 -0
  94. package/dist/src/index.js +16 -0
  95. package/dist/src/inventory.d.ts +4 -0
  96. package/dist/src/inventory.js +94 -0
  97. package/dist/src/java-compiler.d.ts +1 -0
  98. package/dist/src/java-compiler.js +110 -0
  99. package/dist/src/java-evidence.d.ts +2 -0
  100. package/dist/src/java-evidence.js +114 -0
  101. package/dist/src/java-runner.d.ts +1 -0
  102. package/dist/src/java-runner.js +79 -0
  103. package/dist/src/java.d.ts +25 -0
  104. package/dist/src/java.js +102 -0
  105. package/dist/src/jest-evidence.d.ts +2 -0
  106. package/dist/src/jest-evidence.js +117 -0
  107. package/dist/src/jest-runner.d.ts +1 -0
  108. package/dist/src/jest-runner.js +46 -0
  109. package/dist/src/jest.d.ts +2 -0
  110. package/dist/src/jest.js +36 -0
  111. package/dist/src/junit.d.ts +18 -0
  112. package/dist/src/junit.js +157 -0
  113. package/dist/src/laravel-evidence.d.ts +2 -0
  114. package/dist/src/laravel-evidence.js +175 -0
  115. package/dist/src/laravel-runner.d.ts +1 -0
  116. package/dist/src/laravel-runner.js +168 -0
  117. package/dist/src/laravel.d.ts +8 -0
  118. package/dist/src/laravel.js +50 -0
  119. package/dist/src/local-tool.d.ts +1 -0
  120. package/dist/src/local-tool.js +19 -0
  121. package/dist/src/mcp.d.ts +14 -0
  122. package/dist/src/mcp.js +362 -0
  123. package/dist/src/mutation.d.ts +118 -0
  124. package/dist/src/mutation.js +370 -0
  125. package/dist/src/mypy-evidence.d.ts +2 -0
  126. package/dist/src/mypy-evidence.js +63 -0
  127. package/dist/src/mypy.d.ts +2 -0
  128. package/dist/src/mypy.js +59 -0
  129. package/dist/src/node-reporter.d.ts +1 -0
  130. package/dist/src/node-reporter.js +28 -0
  131. package/dist/src/nuxt-evidence.d.ts +2 -0
  132. package/dist/src/nuxt-evidence.js +160 -0
  133. package/dist/src/nuxt-protocol.d.ts +52 -0
  134. package/dist/src/nuxt-protocol.js +29 -0
  135. package/dist/src/nuxt-runner.d.ts +1 -0
  136. package/dist/src/nuxt-runner.js +165 -0
  137. package/dist/src/nuxt.d.ts +24 -0
  138. package/dist/src/nuxt.js +105 -0
  139. package/dist/src/output.d.ts +3 -0
  140. package/dist/src/output.js +48 -0
  141. package/dist/src/phpstan-evidence.d.ts +2 -0
  142. package/dist/src/phpstan-evidence.js +81 -0
  143. package/dist/src/phpstan.d.ts +2 -0
  144. package/dist/src/phpstan.js +51 -0
  145. package/dist/src/phpunit-evidence.d.ts +2 -0
  146. package/dist/src/phpunit-evidence.js +53 -0
  147. package/dist/src/phpunit.d.ts +2 -0
  148. package/dist/src/phpunit.js +58 -0
  149. package/dist/src/pint-evidence.d.ts +2 -0
  150. package/dist/src/pint-evidence.js +79 -0
  151. package/dist/src/pint-runner.d.ts +1 -0
  152. package/dist/src/pint-runner.js +53 -0
  153. package/dist/src/pint.d.ts +2 -0
  154. package/dist/src/pint.js +37 -0
  155. package/dist/src/playwright-evidence.d.ts +2 -0
  156. package/dist/src/playwright-evidence.js +127 -0
  157. package/dist/src/playwright-reporter.d.ts +10 -0
  158. package/dist/src/playwright-reporter.js +37 -0
  159. package/dist/src/playwright-runner.d.ts +1 -0
  160. package/dist/src/playwright-runner.js +61 -0
  161. package/dist/src/playwright.d.ts +2 -0
  162. package/dist/src/playwright.js +35 -0
  163. package/dist/src/policy-pack.d.ts +21 -0
  164. package/dist/src/policy-pack.js +41 -0
  165. package/dist/src/pytest-evidence.d.ts +2 -0
  166. package/dist/src/pytest-evidence.js +116 -0
  167. package/dist/src/pytest-runner.d.ts +1 -0
  168. package/dist/src/pytest-runner.js +48 -0
  169. package/dist/src/pytest.d.ts +2 -0
  170. package/dist/src/pytest.js +25 -0
  171. package/dist/src/report-validation.d.ts +129 -0
  172. package/dist/src/report-validation.js +27 -0
  173. package/dist/src/review.d.ts +270 -0
  174. package/dist/src/review.js +349 -0
  175. package/dist/src/ruby.d.ts +2 -0
  176. package/dist/src/ruby.js +25 -0
  177. package/dist/src/ruff-evidence.d.ts +2 -0
  178. package/dist/src/ruff-evidence.js +99 -0
  179. package/dist/src/ruff.d.ts +2 -0
  180. package/dist/src/ruff.js +40 -0
  181. package/dist/src/runner.d.ts +8 -0
  182. package/dist/src/runner.js +117 -0
  183. package/dist/src/runtime-inventory.d.ts +112 -0
  184. package/dist/src/runtime-inventory.js +200 -0
  185. package/dist/src/rust-dep-info.d.ts +1 -0
  186. package/dist/src/rust-dep-info.js +46 -0
  187. package/dist/src/rust-evidence.d.ts +2 -0
  188. package/dist/src/rust-evidence.js +157 -0
  189. package/dist/src/rust-runner.d.ts +1 -0
  190. package/dist/src/rust-runner.js +161 -0
  191. package/dist/src/rust.d.ts +7 -0
  192. package/dist/src/rust.js +39 -0
  193. package/dist/src/sarif.d.ts +86 -0
  194. package/dist/src/sarif.js +113 -0
  195. package/dist/src/schemas.d.ts +393 -0
  196. package/dist/src/schemas.js +222 -0
  197. package/dist/src/staticcheck-evidence.d.ts +2 -0
  198. package/dist/src/staticcheck-evidence.js +75 -0
  199. package/dist/src/swift.d.ts +2 -0
  200. package/dist/src/swift.js +20 -0
  201. package/dist/src/task-store.d.ts +37 -0
  202. package/dist/src/task-store.js +349 -0
  203. package/dist/src/tool-versions.d.ts +3 -0
  204. package/dist/src/tool-versions.js +260 -0
  205. package/dist/src/types.d.ts +157 -0
  206. package/dist/src/types.js +37 -0
  207. package/dist/src/typescript-build-evidence.d.ts +2 -0
  208. package/dist/src/typescript-build-evidence.js +86 -0
  209. package/dist/src/typescript-build-runner.d.ts +1 -0
  210. package/dist/src/typescript-build-runner.js +132 -0
  211. package/dist/src/typescript-build.d.ts +2 -0
  212. package/dist/src/typescript-build.js +41 -0
  213. package/dist/src/typescript.d.ts +2 -0
  214. package/dist/src/typescript.js +54 -0
  215. package/dist/src/validation-task-worker.d.ts +1 -0
  216. package/dist/src/validation-task-worker.js +205 -0
  217. package/dist/src/validation-tasks-protocol.d.ts +69 -0
  218. package/dist/src/validation-tasks-protocol.js +57 -0
  219. package/dist/src/validation-tasks.d.ts +11 -0
  220. package/dist/src/validation-tasks.js +144 -0
  221. package/dist/src/vitest-evidence.d.ts +2 -0
  222. package/dist/src/vitest-evidence.js +112 -0
  223. package/dist/src/vitest-runner.d.ts +1 -0
  224. package/dist/src/vitest-runner.js +48 -0
  225. package/dist/src/vitest.d.ts +2 -0
  226. package/dist/src/vitest.js +36 -0
  227. package/dist/src/vue-router-capture.d.ts +42 -0
  228. package/dist/src/vue-router-capture.js +87 -0
  229. package/dist/src/vue-router-evidence.d.ts +2 -0
  230. package/dist/src/vue-router-evidence.js +126 -0
  231. package/dist/src/vue-router-protocol.d.ts +63 -0
  232. package/dist/src/vue-router-protocol.js +44 -0
  233. package/dist/src/vue-router-runner.d.ts +1 -0
  234. package/dist/src/vue-router-runner.js +88 -0
  235. package/dist/src/vue-router.d.ts +23 -0
  236. package/dist/src/vue-router.js +108 -0
  237. package/dist/src/vue-tsc-runner.d.ts +1 -0
  238. package/dist/src/vue-tsc-runner.js +24 -0
  239. package/dist/src/workspace.d.ts +7 -0
  240. package/dist/src/workspace.js +53 -0
  241. package/docs/ACCEPTANCE.md +56 -0
  242. package/docs/ACTIONLINT.md +112 -0
  243. package/docs/ARCHITECTURE-POLICY.md +82 -0
  244. package/docs/ARCHITECTURE.md +122 -0
  245. package/docs/CLANG.md +113 -0
  246. package/docs/CLIENTS.md +109 -0
  247. package/docs/CONTRACTS.md +73 -0
  248. package/docs/DEPENDENCIES.md +42 -0
  249. package/docs/DJANGO.md +70 -0
  250. package/docs/DOTNET.md +114 -0
  251. package/docs/ENVIRONMENTS.md +52 -0
  252. package/docs/ESLINT.md +68 -0
  253. package/docs/EVALUATION.md +124 -0
  254. package/docs/EXECUTION.md +250 -0
  255. package/docs/EXTERNAL-ADAPTERS.md +170 -0
  256. package/docs/EXTERNAL-EVALUATION.md +155 -0
  257. package/docs/EXTERNAL-RUFF-EVALUATION.md +85 -0
  258. package/docs/FASTAPI.md +73 -0
  259. package/docs/FINDING-POLICY.md +67 -0
  260. package/docs/GO-RACE.md +19 -0
  261. package/docs/GO-SCOPE.md +63 -0
  262. package/docs/GOLANGCI-LINT.md +64 -0
  263. package/docs/GUIDANCE.md +46 -0
  264. package/docs/IMPACT-MEASUREMENT.md +97 -0
  265. package/docs/INSTALLATION.md +102 -0
  266. package/docs/JAVA.md +79 -0
  267. package/docs/JEST.md +36 -0
  268. package/docs/JUNIT.md +31 -0
  269. package/docs/LANGUAGES.md +113 -0
  270. package/docs/LARAVEL.md +111 -0
  271. package/docs/MCP-COMPATIBILITY.md +68 -0
  272. package/docs/MUTATIONS.md +93 -0
  273. package/docs/MYPY.md +37 -0
  274. package/docs/NATIVE-CI.md +96 -0
  275. package/docs/NUXT.md +123 -0
  276. package/docs/PACK-DISTRIBUTION.md +98 -0
  277. package/docs/PERFORMANCE.md +71 -0
  278. package/docs/PEST.md +36 -0
  279. package/docs/PHPSTAN.md +48 -0
  280. package/docs/PHPUNIT.md +32 -0
  281. package/docs/PINT.md +41 -0
  282. package/docs/PLAN.md +265 -0
  283. package/docs/PLAYWRIGHT.md +73 -0
  284. package/docs/POLICY-PACKS.md +106 -0
  285. package/docs/PRIOR-WORKFLOW-EVALUATION.md +116 -0
  286. package/docs/PUBLICATION.md +28 -0
  287. package/docs/PYTEST.md +51 -0
  288. package/docs/RELEASE.md +115 -0
  289. package/docs/RENAMING.md +55 -0
  290. package/docs/REVIEW-EXCHANGE.md +136 -0
  291. package/docs/RUBY.md +50 -0
  292. package/docs/RUFF.md +39 -0
  293. package/docs/RUNTIME-INVENTORY.md +56 -0
  294. package/docs/RUST.md +74 -0
  295. package/docs/SARIF.md +64 -0
  296. package/docs/STATUS.md +530 -0
  297. package/docs/SWIFT.md +48 -0
  298. package/docs/TASK-STORAGE.md +141 -0
  299. package/docs/TOOL-IDENTITY.md +30 -0
  300. package/docs/TYPESCRIPT-BUILD.md +55 -0
  301. package/docs/VALIDATION-TASKS.md +119 -0
  302. package/docs/VITEST.md +36 -0
  303. package/docs/VUE-ROUTER.md +130 -0
  304. package/docs/VUE-TSC.md +26 -0
  305. package/docs/WORKSPACES.md +81 -0
  306. package/docs/licenses/nodable-entities-3.0.0.txt +21 -0
  307. package/docs/measurements/client-claude-before-schema-fix-darwin-arm64-node26.json +60 -0
  308. package/docs/measurements/client-claude-darwin-arm64-node26.json +55 -0
  309. package/docs/measurements/client-codex-darwin-arm64-node26.json +175 -0
  310. package/docs/measurements/evaluation-corpus-repo-verifier.json +332 -0
  311. package/docs/measurements/evaluation-darwin-arm64-node26.json +1236 -0
  312. package/docs/measurements/evaluation-linux-arm64-node22.json +1236 -0
  313. package/docs/measurements/external-eslint-darwin-arm64-node26.json +11866 -0
  314. package/docs/measurements/external-eslint-linux-arm64-node22.json +11866 -0
  315. package/docs/measurements/external-eslint-preservation.json +1527 -0
  316. package/docs/measurements/external-ruff-darwin-arm64-node26.json +1031 -0
  317. package/docs/measurements/external-ruff-linux-arm64-node22.json +1031 -0
  318. package/docs/measurements/hosted-ci-52ba415.json +1005 -0
  319. package/docs/measurements/impact-darwin-arm64-node26.json +6685 -0
  320. package/docs/measurements/impact-linux-arm64-node22.json +6690 -0
  321. package/docs/measurements/performance-darwin-arm64-node26.json +845 -0
  322. package/docs/measurements/performance-linux-arm64-node22.json +845 -0
  323. package/docs/measurements/required-native-profiles.json +500 -0
  324. package/package.json +72 -0
  325. package/packs/actionlint.json +8 -0
  326. package/packs/cpp.json +8 -0
  327. package/packs/dotnet.json +8 -0
  328. package/packs/go.json +7 -0
  329. package/packs/java.json +8 -0
  330. package/packs/javascript-node.json +7 -0
  331. package/packs/nuxt.json +7 -0
  332. package/packs/php-pest.json +7 -0
  333. package/packs/php-phpunit.json +7 -0
  334. package/packs/python-pytest.json +7 -0
  335. package/packs/ruby.json +7 -0
  336. package/packs/rust.json +7 -0
  337. package/packs/swift.json +7 -0
  338. package/packs/vue-router.json +7 -0
  339. package/packs/vue.json +11 -0
  340. package/schemas/actionlint-config.schema.json +19 -0
  341. package/schemas/architecture-policy.schema.json +51 -0
  342. package/schemas/architecture-report.schema.json +123 -0
  343. package/schemas/architecture-summary.schema.json +82 -0
  344. package/schemas/clang-database.schema.json +23 -0
  345. package/schemas/config.schema.json +69 -0
  346. package/schemas/contract-bundle.schema.json +78 -0
  347. package/schemas/contract-report.schema.json +114 -0
  348. package/schemas/contract-summary.schema.json +72 -0
  349. package/schemas/dependency-graph.schema.json +65 -0
  350. package/schemas/django-config.schema.json +16 -0
  351. package/schemas/dotnet-config.schema.json +60 -0
  352. package/schemas/external-manifest.schema.json +97 -0
  353. package/schemas/external-reference.schema.json +10 -0
  354. package/schemas/external-request.schema.json +56 -0
  355. package/schemas/external-result.schema.json +111 -0
  356. package/schemas/fastapi-config.schema.json +27 -0
  357. package/schemas/finding-baseline.schema.json +92 -0
  358. package/schemas/finding-comparison-summary.schema.json +95 -0
  359. package/schemas/finding-comparison.schema.json +121 -0
  360. package/schemas/guidance-context.schema.json +34 -0
  361. package/schemas/guidance-report.schema.json +176 -0
  362. package/schemas/guidance-summary.schema.json +68 -0
  363. package/schemas/java-config.schema.json +24 -0
  364. package/schemas/junit.schema.json +69 -0
  365. package/schemas/laravel-config.schema.json +11 -0
  366. package/schemas/mutation-recipe.schema.json +31 -0
  367. package/schemas/mutation-report.schema.json +238 -0
  368. package/schemas/mutation-summary.schema.json +98 -0
  369. package/schemas/nuxt-config.schema.json +51 -0
  370. package/schemas/plan-summary.schema.json +63 -0
  371. package/schemas/plan.schema.json +244 -0
  372. package/schemas/policy-pack.schema.json +41 -0
  373. package/schemas/report-summary.schema.json +100 -0
  374. package/schemas/report.schema.json +463 -0
  375. package/schemas/review-assessment.schema.json +133 -0
  376. package/schemas/review-context-summary.schema.json +31 -0
  377. package/schemas/review-context.schema.json +254 -0
  378. package/schemas/review-receipt-summary.schema.json +104 -0
  379. package/schemas/review-receipt.schema.json +271 -0
  380. package/schemas/review-selection.schema.json +30 -0
  381. package/schemas/runtime-comparison-summary.schema.json +68 -0
  382. package/schemas/runtime-comparison.schema.json +127 -0
  383. package/schemas/runtime-inventory.schema.json +99 -0
  384. package/schemas/vue-router-config.schema.json +67 -0
  385. package/server.json +47 -0
@@ -0,0 +1,50 @@
1
+ import path from "node:path";
2
+ import { z } from "zod";
3
+ import { readProjectFile } from "./inventory.js";
4
+ import { localTool } from "./local-tool.js";
5
+ import { laravelRunner } from "./laravel-runner.js";
6
+ export const laravelConfigSchema = z.strictObject({
7
+ schemaVersion: z.literal(1),
8
+ assembly: z.string().min(1).max(256),
9
+ environment: z.literal("testing"),
10
+ });
11
+ export async function laravelCheck(source, project) {
12
+ const check = {
13
+ id: "php.laravel-runtime",
14
+ adapter: project.adapter,
15
+ project: project.path,
16
+ scope: [],
17
+ commands: [],
18
+ kind: "analysis",
19
+ parser: "laravel-json",
20
+ reason: "Bootstrap the explicit Laravel testing profile and capture native assembly registrations without dispatching requests or scheduled work.",
21
+ };
22
+ if (!project.files.includes("checktrail.laravel.json")) {
23
+ check.unavailableReason =
24
+ "Laravel runtime capture requires an explicit checktrail.laravel.json profile.";
25
+ return check;
26
+ }
27
+ const config = laravelConfigSchema.parse(JSON.parse(await readProjectFile(source.root, path.posix.join(project.path, "checktrail.laravel.json"))));
28
+ const autoload = await localTool(source.root, project.path, "autoload.php", "vendor");
29
+ if (!autoload || !project.files.includes("bootstrap/app.php")) {
30
+ check.unavailableReason =
31
+ "Laravel requires local vendor/autoload.php within the operator root and inventoried bootstrap/app.php.";
32
+ return check;
33
+ }
34
+ check.scope = ["bootstrap/app.php"];
35
+ check.commands = [
36
+ {
37
+ executable: "php",
38
+ args: [
39
+ "-r",
40
+ laravelRunner,
41
+ autoload,
42
+ JSON.stringify(config),
43
+ source.fingerprint,
44
+ ],
45
+ cwd: project.path,
46
+ env: { APP_ENV: "testing", APP_DEBUG: "false" },
47
+ },
48
+ ];
49
+ return check;
50
+ }
@@ -0,0 +1 @@
1
+ export declare function localTool(root: string, project: string, entry: string, installationDirectory?: string): Promise<string | undefined>;
@@ -0,0 +1,19 @@
1
+ import { stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { withinRoot } from "./inventory.js";
4
+ export async function localTool(root, project, entry, installationDirectory = "node_modules") {
5
+ let directory = project;
6
+ for (;;) {
7
+ try {
8
+ const tool = await withinRoot(root, path.posix.join(directory, installationDirectory, entry));
9
+ if ((await stat(tool)).isFile())
10
+ return tool;
11
+ }
12
+ catch {
13
+ // Only installed tools contained in the configured root are eligible.
14
+ }
15
+ if (directory === ".")
16
+ return undefined;
17
+ directory = path.posix.dirname(directory);
18
+ }
19
+ }
@@ -0,0 +1,14 @@
1
+ import { type ExternalReference } from "./external-adapter.js";
2
+ import { McpServer } from "@modelcontextprotocol/server";
3
+ export interface ServerOptions {
4
+ externalAdapters?: ExternalReference[];
5
+ root: string;
6
+ allowExecution: boolean;
7
+ allowReviewSource?: boolean;
8
+ detailed: boolean;
9
+ environment?: Record<string, string>;
10
+ base?: string;
11
+ policyOverlay?: string;
12
+ }
13
+ export declare function createServer(options: ServerOptions): McpServer;
14
+ export declare function serve(options: ServerOptions): void;
@@ -0,0 +1,362 @@
1
+ import { createReviewContext, projectReviewContext, receiveReview, projectReviewReceipt, reviewSelectionSchema, reviewContextSchema, reviewContextSummarySchema, reviewReceiptSchema, reviewReceiptSummarySchema, } from "./review.js";
2
+ import { externalReferencesSchema, } from "./external-adapter.js";
3
+ import { runMutations, projectMutations, mutationReportSchema, mutationSummarySchema, } from "./mutation.js";
4
+ import { retrieveGuidance, projectGuidance, guidanceTopicSchema, guidanceReportSchema, guidanceSummarySchema, } from "./guidance.js";
5
+ import { checkArchitecture, projectArchitectureReport, architectureReportSchema, architectureSummarySchema, } from "./architecture.js";
6
+ import { operatorEnvironment } from "./environment.js";
7
+ import { validateContracts, projectContractReport } from "./contracts.js";
8
+ import { contractReportSchema, contractSummarySchema, } from "./contract-schema.js";
9
+ import { compareRuntimeInventories, projectRuntimeComparison, runtimeComparisonSchema, runtimeComparisonSummarySchema, } from "./runtime-inventory.js";
10
+ import { readProjectFile } from "./inventory.js";
11
+ import { compareFindings, projectFindingComparison } from "./finding-policy.js";
12
+ import { findingComparisonSchema, findingComparisonSummarySchema, } from "./finding-policy-schema.js";
13
+ import { McpServer } from "@modelcontextprotocol/server";
14
+ import { serveStdio, StdioServerTransport, } from "@modelcontextprotocol/server/stdio";
15
+ import { z } from "zod";
16
+ import { createPlan, validate } from "./engine.js";
17
+ import { projectPlan, projectReport } from "./output.js";
18
+ import { planSchema, planSummarySchema, reportSchema, reportSummarySchema, } from "./schemas.js";
19
+ import { VERSION } from "./types.js";
20
+ export function createServer(options) {
21
+ if (options.allowReviewSource && !options.detailed)
22
+ throw new Error("Review source disclosure requires detailed output");
23
+ const environment = operatorEnvironment(options.environment);
24
+ const externalAdapters = externalReferencesSchema.parse(options.externalAdapters ?? []);
25
+ const server = new McpServer({ name: "checktrail", version: VERSION });
26
+ const reports = new Map();
27
+ let running;
28
+ let contractRunning;
29
+ // SDK 2.0.0's cancellation handler drops the valid numeric request ID 0.
30
+ server.server.setNotificationHandler("notifications/cancelled", (notification) => {
31
+ if (running && notification.params.requestId === running.id)
32
+ running.controller.abort();
33
+ if (contractRunning &&
34
+ notification.params.requestId === contractRunning.id)
35
+ contractRunning.controller.abort();
36
+ });
37
+ const planOutput = options.detailed ? planSchema : planSummarySchema;
38
+ const reportOutput = options.detailed ? reportSchema : reportSummarySchema;
39
+ const readOnly = {
40
+ readOnlyHint: true,
41
+ destructiveHint: false,
42
+ openWorldHint: false,
43
+ };
44
+ const reply = (value) => ({
45
+ content: [{ type: "text", text: JSON.stringify(value) }],
46
+ structuredContent: value,
47
+ });
48
+ const error = (message) => ({
49
+ isError: true,
50
+ content: [{ type: "text", text: message }],
51
+ });
52
+ for (const name of ["project_context", "validation_plan"]) {
53
+ server.registerTool(name, {
54
+ description: name === "project_context"
55
+ ? "Inspect detected ecosystems within the operator-configured root without executing project code."
56
+ : "Plan registered checks without executing project code. Summary output hides repository paths.",
57
+ inputSchema: z.strictObject({}),
58
+ outputSchema: planOutput,
59
+ annotations: readOnly,
60
+ }, async () => {
61
+ try {
62
+ return reply(projectPlan((await createPlan(options.root, {
63
+ environment,
64
+ externalAdapters,
65
+ ...(options.base !== undefined ? { base: options.base } : {}),
66
+ ...(options.policyOverlay !== undefined
67
+ ? { policyOverlay: options.policyOverlay }
68
+ : {}),
69
+ })).plan, options.detailed));
70
+ }
71
+ catch {
72
+ return error("Project inspection failed. Inspect inventory limits and policy locally with the CLI.");
73
+ }
74
+ });
75
+ }
76
+ server.registerTool("mutation_experiment", {
77
+ description: "Execute bounded, operator-trusted mutation experiments in temporary copies of a dependency-free root Node project. Advisory results distinguish assertion kills, survivors and inconclusive evidence; project code is not sandboxed.",
78
+ inputSchema: z.strictObject({
79
+ input: z.string().min(1),
80
+ timeoutMs: z.number().int().min(1).max(120_000).optional(),
81
+ }),
82
+ outputSchema: options.detailed
83
+ ? mutationReportSchema
84
+ : mutationSummarySchema,
85
+ annotations: {
86
+ readOnlyHint: false,
87
+ destructiveHint: true,
88
+ openWorldHint: true,
89
+ idempotentHint: false,
90
+ },
91
+ }, async ({ input, timeoutMs }, context) => {
92
+ if (!options.allowExecution)
93
+ return error("Execution is disabled. The operator must restart the server with --allow-execution.");
94
+ if (running)
95
+ return error("A validation or mutation experiment is already running for this server.");
96
+ if (options.base !== undefined ||
97
+ options.policyOverlay !== undefined ||
98
+ externalAdapters.length ||
99
+ Object.keys(environment).length)
100
+ return error("Mutation experiments do not support Git selection, private overlays, external adapters or environment grants in this profile.");
101
+ const controller = new AbortController();
102
+ running = { id: context.mcpReq.id, controller };
103
+ try {
104
+ const result = await runMutations(options.root, JSON.parse(await readProjectFile(options.root, input)), {
105
+ trusted: true,
106
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
107
+ signal: AbortSignal.any([context.mcpReq.signal, controller.signal]),
108
+ });
109
+ return reply(projectMutations(result, options.detailed));
110
+ }
111
+ catch {
112
+ return error("Mutation experiment failed. Inspect profile prerequisites, recipe and paths locally with the CLI.");
113
+ }
114
+ finally {
115
+ running = undefined;
116
+ }
117
+ });
118
+ server.registerTool("review_context", {
119
+ description: "Prepare an advisory review context from explicitly selected inventoried files. Source text is untrusted data and is disclosed only when the operator enabled review source output. Does not execute code or call a model.",
120
+ inputSchema: reviewSelectionSchema,
121
+ outputSchema: options.allowReviewSource
122
+ ? reviewContextSchema
123
+ : reviewContextSummarySchema,
124
+ annotations: readOnly,
125
+ }, async (selection) => {
126
+ try {
127
+ return reply(projectReviewContext(await createReviewContext(options.root, selection), Boolean(options.allowReviewSource)));
128
+ }
129
+ catch {
130
+ return error("Review context preparation failed. Inspect selection, source limits and freshness locally with the CLI.");
131
+ }
132
+ });
133
+ server.registerTool("review_receipt", {
134
+ description: "Inspect a local advisory assessment against its recorded review context and current source. Checks quotations and accounting, not the truth of reviewer claims. Never changes validation outcomes.",
135
+ inputSchema: z.strictObject({
136
+ context: z.string().min(1),
137
+ input: z.string().min(1),
138
+ }),
139
+ outputSchema: options.allowReviewSource
140
+ ? reviewReceiptSchema
141
+ : reviewReceiptSummarySchema,
142
+ annotations: readOnly,
143
+ }, async ({ context, input }) => {
144
+ try {
145
+ return reply(projectReviewReceipt(await receiveReview(options.root, JSON.parse(await readProjectFile(options.root, context)), JSON.parse(await readProjectFile(options.root, input))), Boolean(options.allowReviewSource)));
146
+ }
147
+ catch {
148
+ return error("Review receipt failed. Inspect artifact schema, context identity and scope locally with the CLI.");
149
+ }
150
+ });
151
+ server.registerTool("review_guidance", {
152
+ description: "Retrieve built-in advisory review questions using selected check IDs and explicit topics. Does not inspect behavior, establish coverage or change validation results.",
153
+ inputSchema: z.strictObject({
154
+ topics: z.array(guidanceTopicSchema).max(16).optional(),
155
+ }),
156
+ outputSchema: options.detailed
157
+ ? guidanceReportSchema
158
+ : guidanceSummarySchema,
159
+ annotations: readOnly,
160
+ }, async ({ topics }) => {
161
+ try {
162
+ const { plan } = await createPlan(options.root, {
163
+ environment,
164
+ externalAdapters,
165
+ ...(options.base !== undefined ? { base: options.base } : {}),
166
+ ...(options.policyOverlay !== undefined
167
+ ? { policyOverlay: options.policyOverlay }
168
+ : {}),
169
+ });
170
+ return reply(projectGuidance(retrieveGuidance({
171
+ schemaVersion: 1,
172
+ checks: [...new Set(plan.checks.map((check) => check.id))],
173
+ topics: topics ?? [],
174
+ }), options.detailed));
175
+ }
176
+ catch {
177
+ return error("Guidance retrieval failed. Inspect context, inventory limits and policy locally with the CLI.");
178
+ }
179
+ });
180
+ server.registerTool("validation_run", {
181
+ description: "Execute planned checks only when the operator enabled execution at server startup. Project tools can modify files and access networks.",
182
+ inputSchema: z.strictObject({
183
+ timeoutMs: z.number().int().min(1).max(120_000).optional(),
184
+ }),
185
+ outputSchema: reportOutput,
186
+ annotations: {
187
+ readOnlyHint: false,
188
+ destructiveHint: true,
189
+ openWorldHint: true,
190
+ idempotentHint: false,
191
+ },
192
+ }, async ({ timeoutMs }, context) => {
193
+ if (!options.allowExecution)
194
+ return error("Execution is disabled. The operator must restart the server with --allow-execution.");
195
+ if (running)
196
+ return error("A validation is already running for this server.");
197
+ const controller = new AbortController();
198
+ running = { id: context.mcpReq.id, controller };
199
+ try {
200
+ const report = await validate(options.root, {
201
+ trusted: true,
202
+ environment,
203
+ externalAdapters,
204
+ ...(options.base !== undefined ? { base: options.base } : {}),
205
+ ...(options.policyOverlay !== undefined
206
+ ? { policyOverlay: options.policyOverlay }
207
+ : {}),
208
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
209
+ signal: AbortSignal.any([context.mcpReq.signal, controller.signal]),
210
+ });
211
+ reports.set(report.runId, report);
212
+ while (reports.size > 10)
213
+ reports.delete(reports.keys().next().value);
214
+ return reply(projectReport(report, options.detailed));
215
+ }
216
+ catch {
217
+ return error("Validation could not start. Inspect configuration locally with the CLI.");
218
+ }
219
+ finally {
220
+ running = undefined;
221
+ }
222
+ });
223
+ server.registerTool("validation_report", {
224
+ description: "Retrieve a retained report by its opaque run ID. Reports are local to this server and disappear on restart.",
225
+ inputSchema: z.strictObject({ runId: z.string().uuid() }),
226
+ outputSchema: reportOutput,
227
+ annotations: readOnly,
228
+ }, async ({ runId }) => {
229
+ const report = reports.get(runId);
230
+ return report
231
+ ? reply(projectReport(report, options.detailed))
232
+ : error("Report is unavailable or has expired.");
233
+ });
234
+ server.registerTool("finding_comparison", {
235
+ description: "Compare a retained validation report with an exact local baseline or exception policy. Comparison success does not change the native validation outcome or establish current-source freshness.",
236
+ inputSchema: z.strictObject({
237
+ runId: z.string().uuid(),
238
+ baseline: z.string().min(1),
239
+ previousBaseline: z.string().min(1).optional(),
240
+ }),
241
+ outputSchema: options.detailed
242
+ ? findingComparisonSchema
243
+ : findingComparisonSummarySchema,
244
+ annotations: readOnly,
245
+ }, async ({ runId, baseline, previousBaseline }) => {
246
+ const report = reports.get(runId);
247
+ if (!report)
248
+ return error("Report is unavailable or has expired.");
249
+ try {
250
+ const policy = JSON.parse(await readProjectFile(options.root, baseline));
251
+ const previous = previousBaseline === undefined
252
+ ? undefined
253
+ : JSON.parse(await readProjectFile(options.root, previousBaseline));
254
+ return reply(projectFindingComparison(compareFindings(report, policy, previous === undefined ? {} : { previousBaseline: previous }), options.detailed));
255
+ }
256
+ catch {
257
+ return error("Finding comparison failed. Inspect baseline paths, limits and evidence locally with the CLI.");
258
+ }
259
+ });
260
+ server.registerTool("architecture_validation", {
261
+ description: "Check a local captured dependency graph against exact project/layer boundaries and cycle policy. Imported graph completeness is declared, not independently attested.",
262
+ inputSchema: z.strictObject({
263
+ input: z.string().min(1),
264
+ policy: z.string().min(1),
265
+ }),
266
+ outputSchema: options.detailed
267
+ ? architectureReportSchema
268
+ : architectureSummarySchema,
269
+ annotations: readOnly,
270
+ }, async ({ input, policy }) => {
271
+ try {
272
+ const result = checkArchitecture(JSON.parse(await readProjectFile(options.root, input)), JSON.parse(await readProjectFile(options.root, policy)));
273
+ return reply(projectArchitectureReport(result, options.detailed));
274
+ }
275
+ catch {
276
+ return error("Architecture validation failed. Inspect graph/policy schema, limits and paths locally with the CLI.");
277
+ }
278
+ });
279
+ server.registerTool("runtime_comparison", {
280
+ description: "Compare two local runtime inventory artifacts without executing project code. Reports exact registration, attribute and order changes; imported artifacts do not attest runtime freshness.",
281
+ inputSchema: z.strictObject({
282
+ before: z.string().min(1),
283
+ after: z.string().min(1),
284
+ }),
285
+ outputSchema: options.detailed
286
+ ? runtimeComparisonSchema
287
+ : runtimeComparisonSummarySchema,
288
+ annotations: readOnly,
289
+ }, async ({ before, after }) => {
290
+ try {
291
+ const result = compareRuntimeInventories(JSON.parse(await readProjectFile(options.root, before)), JSON.parse(await readProjectFile(options.root, after)));
292
+ return reply(projectRuntimeComparison(result, options.detailed));
293
+ }
294
+ catch {
295
+ return error("Runtime comparison failed. Inspect artifact schema, limits and paths locally with the CLI.");
296
+ }
297
+ });
298
+ server.registerTool("contract_validation", {
299
+ description: "Validate local captured producer payloads against strict consumer JSON Schemas. Does not execute project code or attest live integration or freshness.",
300
+ inputSchema: z.strictObject({
301
+ input: z.string().min(1),
302
+ timeoutMs: z.number().int().min(1).max(30_000).optional(),
303
+ }),
304
+ outputSchema: options.detailed
305
+ ? contractReportSchema
306
+ : contractSummarySchema,
307
+ annotations: readOnly,
308
+ }, async ({ input, timeoutMs }, context) => {
309
+ if (contractRunning)
310
+ return error("A contract validation is already running for this server.");
311
+ const controller = new AbortController();
312
+ contractRunning = { id: context.mcpReq.id, controller };
313
+ try {
314
+ const result = await validateContracts(JSON.parse(await readProjectFile(options.root, input)), {
315
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
316
+ signal: AbortSignal.any([context.mcpReq.signal, controller.signal]),
317
+ });
318
+ return reply(projectContractReport(result, options.detailed));
319
+ }
320
+ catch {
321
+ return error("Contract validation failed. Inspect artifact schema, limits and paths locally with the CLI.");
322
+ }
323
+ finally {
324
+ contractRunning = undefined;
325
+ }
326
+ });
327
+ return server;
328
+ }
329
+ export function serve(options) {
330
+ const handle = serveStdio(() => createServer(options), {
331
+ transport: new StdioServerTransport(process.stdin, process.stdout, {
332
+ maxBufferSize: 1024 * 1024,
333
+ }),
334
+ onerror: () => {
335
+ process.stderr.write("MCP transport error\n");
336
+ },
337
+ });
338
+ let closing = false;
339
+ const shutdown = () => {
340
+ if (closing)
341
+ return;
342
+ closing = true;
343
+ process.stdin.removeListener("end", shutdown);
344
+ process.removeListener("SIGINT", interrupt);
345
+ process.removeListener("SIGTERM", terminate);
346
+ void handle.close().catch(() => {
347
+ process.stderr.write("MCP shutdown failed\n");
348
+ process.exitCode = 2;
349
+ });
350
+ };
351
+ const interrupt = () => {
352
+ process.exitCode = 130;
353
+ shutdown();
354
+ };
355
+ const terminate = () => {
356
+ process.exitCode = 143;
357
+ shutdown();
358
+ };
359
+ process.stdin.once("end", shutdown);
360
+ process.once("SIGINT", interrupt);
361
+ process.once("SIGTERM", terminate);
362
+ }
@@ -0,0 +1,118 @@
1
+ import { z } from "zod";
2
+ export declare const mutationRecipeSchema: z.ZodObject<{
3
+ schemaVersion: z.ZodLiteral<1>;
4
+ profile: z.ZodLiteral<"node-flat-tests">;
5
+ mutations: z.ZodArray<z.ZodObject<{
6
+ id: z.ZodString;
7
+ file: z.ZodString;
8
+ expected: z.ZodString;
9
+ replacement: z.ZodString;
10
+ }, z.core.$strict>>;
11
+ }, z.core.$strict>;
12
+ export declare const mutationReportSchema: z.ZodObject<{
13
+ excluded: z.ZodArray<z.ZodString>;
14
+ baseline: z.ZodOptional<z.ZodObject<{
15
+ runId: z.ZodString;
16
+ outcome: z.ZodEnum<{
17
+ passed: "passed";
18
+ failed: "failed";
19
+ incomplete: "incomplete";
20
+ }>;
21
+ durationMs: z.ZodNumber;
22
+ sourceFingerprint: z.ZodString;
23
+ sourceChanged: z.ZodBoolean;
24
+ sourceError: z.ZodBoolean;
25
+ tests: z.ZodOptional<z.ZodObject<{
26
+ total: z.ZodNumber;
27
+ passed: z.ZodNumber;
28
+ failed: z.ZodNumber;
29
+ skipped: z.ZodNumber;
30
+ }, z.core.$strict>>;
31
+ }, z.core.$strict>>;
32
+ trials: z.ZodArray<z.ZodObject<{
33
+ id: z.ZodString;
34
+ file: z.ZodString;
35
+ status: z.ZodEnum<{
36
+ inconclusive: "inconclusive";
37
+ killed: "killed";
38
+ survived: "survived";
39
+ invalid: "invalid";
40
+ "not-run": "not-run";
41
+ }>;
42
+ reason: z.ZodString;
43
+ observation: z.ZodOptional<z.ZodObject<{
44
+ runId: z.ZodString;
45
+ outcome: z.ZodEnum<{
46
+ passed: "passed";
47
+ failed: "failed";
48
+ incomplete: "incomplete";
49
+ }>;
50
+ durationMs: z.ZodNumber;
51
+ sourceFingerprint: z.ZodString;
52
+ sourceChanged: z.ZodBoolean;
53
+ sourceError: z.ZodBoolean;
54
+ tests: z.ZodOptional<z.ZodObject<{
55
+ total: z.ZodNumber;
56
+ passed: z.ZodNumber;
57
+ failed: z.ZodNumber;
58
+ skipped: z.ZodNumber;
59
+ }, z.core.$strict>>;
60
+ }, z.core.$strict>>;
61
+ }, z.core.$strict>>;
62
+ schemaVersion: z.ZodLiteral<1>;
63
+ engineVersion: z.ZodString;
64
+ profile: z.ZodLiteral<"node-flat-tests">;
65
+ channel: z.ZodLiteral<"advisory">;
66
+ provenance: z.ZodLiteral<"temporary-copy-mutation-experiment">;
67
+ recipeDigest: z.ZodString;
68
+ sourceFingerprint: z.ZodString;
69
+ finalSourceFingerprint: z.ZodNullable<z.ZodString>;
70
+ complete: z.ZodBoolean;
71
+ reason: z.ZodString;
72
+ durationMs: z.ZodNumber;
73
+ runtime: z.ZodObject<{
74
+ name: z.ZodLiteral<"node">;
75
+ version: z.ZodString;
76
+ }, z.core.$strict>;
77
+ counts: z.ZodObject<{
78
+ total: z.ZodNumber;
79
+ killed: z.ZodNumber;
80
+ survived: z.ZodNumber;
81
+ invalid: z.ZodNumber;
82
+ inconclusive: z.ZodNumber;
83
+ notRun: z.ZodNumber;
84
+ }, z.core.$strict>;
85
+ }, z.core.$strict>;
86
+ export declare const mutationSummarySchema: z.ZodObject<{
87
+ schemaVersion: z.ZodLiteral<1>;
88
+ engineVersion: z.ZodString;
89
+ profile: z.ZodLiteral<"node-flat-tests">;
90
+ channel: z.ZodLiteral<"advisory">;
91
+ provenance: z.ZodLiteral<"temporary-copy-mutation-experiment">;
92
+ recipeDigest: z.ZodString;
93
+ sourceFingerprint: z.ZodString;
94
+ finalSourceFingerprint: z.ZodNullable<z.ZodString>;
95
+ complete: z.ZodBoolean;
96
+ reason: z.ZodString;
97
+ durationMs: z.ZodNumber;
98
+ runtime: z.ZodObject<{
99
+ name: z.ZodLiteral<"node">;
100
+ version: z.ZodString;
101
+ }, z.core.$strict>;
102
+ counts: z.ZodObject<{
103
+ total: z.ZodNumber;
104
+ killed: z.ZodNumber;
105
+ survived: z.ZodNumber;
106
+ invalid: z.ZodNumber;
107
+ inconclusive: z.ZodNumber;
108
+ notRun: z.ZodNumber;
109
+ }, z.core.$strict>;
110
+ }, z.core.$strict>;
111
+ export type MutationRecipe = z.infer<typeof mutationRecipeSchema>;
112
+ export type MutationReport = z.infer<typeof mutationReportSchema>;
113
+ export declare function runMutations(root: string, input: unknown, options: {
114
+ trusted: boolean;
115
+ timeoutMs?: number;
116
+ signal?: AbortSignal;
117
+ }): Promise<MutationReport>;
118
+ export declare function projectMutations(report: MutationReport, detailed: boolean): Record<string, unknown>;