@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,2 @@
1
+ import type { Check, Inventory, Project } from "./types.js";
2
+ export declare function phpstanCheck(source: Inventory, project: Project): Promise<Check>;
@@ -0,0 +1,51 @@
1
+ import { localTool } from "./local-tool.js";
2
+ export async function phpstanCheck(source, project) {
3
+ const files = project.files.filter((file) => file.endsWith(".php"));
4
+ const tool = await localTool(source.root, project.path, "phpstan/phpstan/phpstan", "vendor");
5
+ const config = [
6
+ "phpstan.neon",
7
+ "phpstan.neon.dist",
8
+ "phpstan.dist.neon",
9
+ ].find((file) => project.files.includes(file));
10
+ const check = {
11
+ id: "php.phpstan",
12
+ adapter: project.adapter,
13
+ project: project.path,
14
+ scope: files,
15
+ kind: "analysis",
16
+ parser: "phpstan-json",
17
+ commands: tool && config
18
+ ? [
19
+ {
20
+ executable: "php",
21
+ args: [
22
+ tool,
23
+ "analyse",
24
+ "--configuration",
25
+ `./${config}`,
26
+ "--error-format=json",
27
+ "--no-progress",
28
+ "--no-ansi",
29
+ "--debug",
30
+ "--",
31
+ ...files.map((file) => `./${file}`),
32
+ ],
33
+ cwd: project.path,
34
+ },
35
+ ]
36
+ : [],
37
+ reason: "Run local PHPStan with native per-file debug accounting, no result-cache reuse and JSON diagnostic totals.",
38
+ };
39
+ if (!files.length)
40
+ check.unavailableReason = "No PHP files were inventoried.";
41
+ else if (!tool)
42
+ check.unavailableReason =
43
+ "PHPStan is not installed in vendor within the configured root.";
44
+ else if (!config)
45
+ check.unavailableReason =
46
+ "A project-local PHPStan NEON configuration is required.";
47
+ else if (files.some((file) => /[\r\n]/.test(file)))
48
+ check.unavailableReason =
49
+ "PHPStan debug evidence cannot account for filenames containing newlines.";
50
+ return check;
51
+ }
@@ -0,0 +1,2 @@
1
+ import type { Check, CheckResult, ProcessResult } from "./types.js";
2
+ export declare function phpunitEvidence(check: Check, processes: ProcessResult[], root: string | undefined): Pick<CheckResult, "status" | "reason" | "tests">;
@@ -0,0 +1,53 @@
1
+ import path from "node:path";
2
+ import { importJUnit } from "./junit.js";
3
+ export function phpunitEvidence(check, processes, root) {
4
+ const pest = check.id === "php.pest";
5
+ const name = pest ? "Pest" : "PHPUnit";
6
+ const incomplete = {
7
+ status: "inconclusive",
8
+ reason: `${name} evidence is incomplete, omits a planned test file, or has no passing assertions.`,
9
+ };
10
+ if (!root || !check.scope.length || processes.length !== 1)
11
+ return incomplete;
12
+ const process = processes[0];
13
+ const result = importJUnit(pest ? process.stderr : process.stdout);
14
+ if (!result.tests || !result.cases)
15
+ return process.exitCode === 0
16
+ ? incomplete
17
+ : {
18
+ status: "error",
19
+ reason: `${name} could not produce valid JUnit evidence; inspect runtime and configuration.`,
20
+ };
21
+ const tests = result.tests;
22
+ if (tests.failed)
23
+ return {
24
+ status: "failed",
25
+ reason: `${name} reported test or fixture failures.`,
26
+ tests,
27
+ };
28
+ if (!tests.passed)
29
+ return { ...incomplete, tests };
30
+ if (process.exitCode !== 0)
31
+ return {
32
+ status: "failed",
33
+ reason: `${name} reported a runtime, warning or risky-test failure.`,
34
+ tests,
35
+ };
36
+ const expected = new Set(check.scope.map((file) => path.resolve(root, check.project, file)));
37
+ const files = new Set();
38
+ for (const item of result.cases) {
39
+ if (!item.file || (item.status === "passed" && !item.assertions))
40
+ return { ...incomplete, tests };
41
+ const file = path.resolve(root, check.project, pest ? item.file.split("::")[0] : item.file);
42
+ if (!expected.has(file))
43
+ return { ...incomplete, tests };
44
+ files.add(file);
45
+ }
46
+ if (files.size !== expected.size)
47
+ return { ...incomplete, tests };
48
+ return {
49
+ status: "passed",
50
+ reason: `${name} produced fresh JUnit evidence for every planned file with passing assertions.`,
51
+ tests,
52
+ };
53
+ }
@@ -0,0 +1,2 @@
1
+ import type { Check, Inventory, Project } from "./types.js";
2
+ export declare function phpunitCheck(source: Inventory, project: Project, pest?: boolean): Promise<Check>;
@@ -0,0 +1,58 @@
1
+ import { localTool } from "./local-tool.js";
2
+ export async function phpunitCheck(source, project, pest = false) {
3
+ const files = project.files.filter((file) => file.endsWith("Test.php"));
4
+ const tool = await localTool(source.root, project.path, pest ? "pestphp/pest/bin/pest" : "phpunit/phpunit/phpunit", "vendor");
5
+ const configuration = ["phpunit.xml", "phpunit.xml.dist"].find((file) => project.files.includes(file));
6
+ const name = pest ? "Pest" : "PHPUnit";
7
+ const check = {
8
+ id: pest ? "php.pest" : "php.phpunit",
9
+ adapter: project.adapter,
10
+ project: project.path,
11
+ scope: files,
12
+ kind: "test",
13
+ parser: "phpunit-junit",
14
+ commands: tool
15
+ ? [
16
+ {
17
+ executable: "php",
18
+ args: [
19
+ tool,
20
+ ...(pest
21
+ ? [
22
+ "--ci",
23
+ "--no-tia",
24
+ "--colors=never",
25
+ "--configuration",
26
+ `./${configuration ?? "phpunit.xml"}`,
27
+ ]
28
+ : []),
29
+ "--no-output",
30
+ "--do-not-record-test-run-history",
31
+ "--no-logging",
32
+ "--log-junit",
33
+ pest ? "php://stderr" : "php://stdout",
34
+ "--all",
35
+ "--fail-on-empty-test-suite",
36
+ "--fail-on-risky",
37
+ "--fail-on-warning",
38
+ ...(pest ? [] : ["--"]),
39
+ ...files.map((file) => `./${file}`),
40
+ ],
41
+ cwd: project.path,
42
+ },
43
+ ]
44
+ : [],
45
+ reason: `Run ${name} with fresh JUnit output, exact test-file accounting and positive native assertion evidence.`,
46
+ };
47
+ if (!files.length)
48
+ check.unavailableReason = "No *Test.php files were inventoried.";
49
+ else if (!tool)
50
+ check.unavailableReason = `${name} is not installed in vendor within the configured root.`;
51
+ else if (pest && !configuration)
52
+ check.unavailableReason =
53
+ "Pest requires a local phpunit.xml or phpunit.xml.dist to avoid generating configuration.";
54
+ else if (pest && files.some((file) => file.includes("::")))
55
+ check.unavailableReason =
56
+ "Pest JUnit cannot disambiguate a test path containing ::.";
57
+ return check;
58
+ }
@@ -0,0 +1,2 @@
1
+ import type { Check, CheckResult, ProcessResult } from "./types.js";
2
+ export declare function pintEvidence(check: Check, processes: ProcessResult[], root: string | undefined): Pick<CheckResult, "status" | "reason">;
@@ -0,0 +1,79 @@
1
+ import path from "node:path";
2
+ import { z } from "zod";
3
+ const envelope = z
4
+ .object({
5
+ version: z.literal("1.32.1"),
6
+ files: z.array(z.string()),
7
+ fixers: z.array(z.string().min(1)),
8
+ blocked: z.string().nullable(),
9
+ report: z.string().optional(),
10
+ exitCode: z.number().int().optional(),
11
+ })
12
+ .strict();
13
+ const nativeReport = z
14
+ .object({
15
+ tool: z.literal("pint"),
16
+ result: z.enum(["passed", "fail", "fixed"]),
17
+ files: z
18
+ .array(z
19
+ .object({
20
+ path: z.string(),
21
+ fixers: z.array(z.string().min(1)).nonempty(),
22
+ })
23
+ .strict())
24
+ .optional(),
25
+ errors: z
26
+ .array(z.object({ path: z.string(), message: z.string() }).strict())
27
+ .optional(),
28
+ })
29
+ .strict();
30
+ export function pintEvidence(check, processes, root) {
31
+ const incomplete = {
32
+ status: "inconclusive",
33
+ reason: "Pint evidence is incomplete, unsupported, missing planned files or has no active rules.",
34
+ };
35
+ if (!root || !check.scope.length || processes.length !== 1)
36
+ return incomplete;
37
+ const process = processes[0];
38
+ try {
39
+ const result = envelope.parse(JSON.parse(process.stdout));
40
+ if (result.blocked !== null)
41
+ return incomplete;
42
+ if (!result.report || result.exitCode !== process.exitCode)
43
+ return incomplete;
44
+ const report = nativeReport.parse(JSON.parse(result.report));
45
+ if (report.result === "fixed")
46
+ return incomplete;
47
+ if ((report.files?.length ?? 0) + (report.errors?.length ?? 0) > 0)
48
+ return {
49
+ status: "failed",
50
+ reason: "Pint reported style or syntax errors.",
51
+ };
52
+ if (report.result !== "passed" || process.exitCode !== 0)
53
+ return {
54
+ status: "error",
55
+ reason: "Pint could not complete native validation.",
56
+ };
57
+ if (process.stderr.trim())
58
+ return incomplete;
59
+ const expected = new Set(check.scope.map((file) => path.resolve(root, check.project, file)));
60
+ const actual = new Set(result.files.map((file) => path.resolve(root, check.project, file)));
61
+ if (!result.fixers.length ||
62
+ actual.size !== result.files.length ||
63
+ actual.size !== expected.size ||
64
+ [...actual].some((file) => !expected.has(file)))
65
+ return incomplete;
66
+ return {
67
+ status: "passed",
68
+ reason: "Pint checked every planned file with active rules and no style or syntax errors.",
69
+ };
70
+ }
71
+ catch {
72
+ return process.exitCode === 0
73
+ ? incomplete
74
+ : {
75
+ status: "error",
76
+ reason: "Pint returned invalid evidence; inspect configuration and runtime prerequisites.",
77
+ };
78
+ }
79
+ }
@@ -0,0 +1 @@
1
+ export declare const pintRunner: string;
@@ -0,0 +1,53 @@
1
+ export const pintRunner = String.raw `
2
+ $tool = realpath($argv[1]);
3
+ Phar::loadPhar($tool, 'checktrail-pint.phar');
4
+ $base = 'phar://checktrail-pint.phar';
5
+ $loader = require $base.'/vendor/autoload.php';
6
+ $loader->addClassMap([
7
+ 'PhpCsFixer\FixerFactory' => $base.'/overrides/FixerFactory.php',
8
+ 'PhpCsFixer\Runner\Parallel\ProcessFactory' => $base.'/overrides/Runner/Parallel/ProcessFactory.php',
9
+ ]);
10
+ $app = require $base.'/bootstrap/app.php';
11
+ $temporary = getenv('CHECKTRAIL_TEMP');
12
+ if ($temporary === false || !is_dir($temporary)) throw new RuntimeException('Missing execution temporary directory');
13
+ $input = new Symfony\Component\Console\Input\ArgvInput([
14
+ 'pint', '--test', '--format=agent', '--cache-file='.$temporary.'/pint-cache.json', '--no-ansi', '--no-interaction', '--', ...array_slice($argv, 2),
15
+ ]);
16
+ $output = new class extends Symfony\Component\Console\Output\BufferedOutput implements Symfony\Component\Console\Output\ConsoleOutputInterface {
17
+ private Symfony\Component\Console\Output\OutputInterface $errors;
18
+ public function __construct() {
19
+ parent::__construct();
20
+ $this->errors = new Symfony\Component\Console\Output\StreamOutput(STDERR);
21
+ }
22
+ public function getErrorOutput(): Symfony\Component\Console\Output\OutputInterface { return $this->errors; }
23
+ public function setErrorOutput(Symfony\Component\Console\Output\OutputInterface $error): void { $this->errors = $error; }
24
+ public function section(): Symfony\Component\Console\Output\ConsoleSectionOutput { throw new RuntimeException('Interactive sections are unsupported'); }
25
+ };
26
+ $app->instance(Symfony\Component\Console\Input\InputInterface::class, $input);
27
+ $app->instance(Symfony\Component\Console\Output\OutputInterface::class, $output);
28
+ $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
29
+ $kernel->bootstrap();
30
+ $evidence = ['version' => config('app.version'), 'files' => [], 'fixers' => [], 'blocked' => null];
31
+ if ($evidence['version'] !== '1.32.1') {
32
+ $evidence['blocked'] = 'unsupported-version';
33
+ echo json_encode($evidence, JSON_THROW_ON_ERROR);
34
+ exit(2);
35
+ }
36
+ $app['events']->listen(Illuminate\Console\Events\CommandStarting::class, function ($event) use (&$evidence) {
37
+ [$resolver] = App\Factories\ConfigurationResolverFactory::fromIO($event->input, $event->output);
38
+ $evidence['files'] = array_map(fn ($file) => $file->getRealPath(), iterator_to_array($resolver->getFinder(), false));
39
+ $fixers = $resolver->getFixers();
40
+ $evidence['fixers'] = array_map(fn ($fixer) => $fixer->getName(), $fixers);
41
+ if ($fixers === []) $evidence['blocked'] = 'no-active-rules';
42
+ foreach ($fixers as $fixer) {
43
+ if ($fixer instanceof App\Contracts\HasPrettierDependencies) $evidence['blocked'] = 'unverified-prettier-integration';
44
+ }
45
+ if ($evidence['blocked'] !== null) throw new RuntimeException($evidence['blocked']);
46
+ });
47
+ $status = $kernel->handle($input, $output);
48
+ $evidence['report'] = $output->fetch();
49
+ $evidence['exitCode'] = $status;
50
+ $kernel->terminate($input, $status);
51
+ echo json_encode($evidence, JSON_THROW_ON_ERROR);
52
+ exit($status);
53
+ `;
@@ -0,0 +1,2 @@
1
+ import type { Check, Inventory, Project } from "./types.js";
2
+ export declare function pintCheck(source: Inventory, project: Project): Promise<Check>;
@@ -0,0 +1,37 @@
1
+ import { localTool } from "./local-tool.js";
2
+ import { pintRunner } from "./pint-runner.js";
3
+ export async function pintCheck(source, project) {
4
+ const files = project.files.filter((file) => file.endsWith(".php") && !file.endsWith(".blade.php"));
5
+ const tool = await localTool(source.root, project.path, "laravel/pint/builds/pint", "vendor");
6
+ const check = {
7
+ id: "php.pint",
8
+ adapter: project.adapter,
9
+ project: project.path,
10
+ scope: files,
11
+ kind: "format",
12
+ parser: "pint-json",
13
+ commands: tool
14
+ ? [
15
+ {
16
+ executable: "php",
17
+ args: [
18
+ "-r",
19
+ pintRunner,
20
+ "--",
21
+ tool,
22
+ ...files.map((file) => `./${file}`),
23
+ ],
24
+ cwd: project.path,
25
+ temporaryDirectory: true,
26
+ },
27
+ ]
28
+ : [],
29
+ reason: "Run Pint on non-Blade PHP files in test mode with native file and active-rule evidence and no reusable cache.",
30
+ };
31
+ if (!files.length)
32
+ check.unavailableReason = "No non-Blade PHP files were inventoried.";
33
+ else if (!tool)
34
+ check.unavailableReason =
35
+ "Pint is not installed in vendor within the configured root.";
36
+ return check;
37
+ }
@@ -0,0 +1,2 @@
1
+ import type { Check, CheckResult, ProcessResult } from "./types.js";
2
+ export declare function playwrightEvidence(check: Check, processes: ProcessResult[], root: string | undefined): Pick<CheckResult, "status" | "reason" | "tests">;
@@ -0,0 +1,127 @@
1
+ import path from "node:path";
2
+ import { z } from "zod";
3
+ const status = z.enum([
4
+ "passed",
5
+ "failed",
6
+ "timedOut",
7
+ "skipped",
8
+ "interrupted",
9
+ ]);
10
+ const schema = z.object({
11
+ version: z.literal(1),
12
+ status,
13
+ errors: z.array(z.string()),
14
+ projects: z.array(z.string()),
15
+ tests: z.array(z.object({
16
+ id: z.string().min(1),
17
+ file: z.string(),
18
+ project: z.string(),
19
+ expectedStatus: status,
20
+ outcome: z.enum(["expected", "unexpected", "flaky", "skipped"]),
21
+ results: z.array(z.object({
22
+ status,
23
+ retry: z.number().int().nonnegative(),
24
+ errors: z.array(z.string()),
25
+ })),
26
+ })),
27
+ });
28
+ export function playwrightEvidence(check, processes, root) {
29
+ const incomplete = {
30
+ status: "inconclusive",
31
+ reason: "Playwright evidence is incomplete, inconsistent, skipped or omits planned test files.",
32
+ };
33
+ if (!root || processes.length !== 1 || !check.scope.length)
34
+ return incomplete;
35
+ const process = processes[0];
36
+ if (process.exitCode !== 0 && process.exitCode !== 1)
37
+ return {
38
+ status: "error",
39
+ reason: "Playwright configuration or its supported native integration could not run.",
40
+ };
41
+ let report;
42
+ try {
43
+ report = schema.parse(JSON.parse(process.stdout));
44
+ }
45
+ catch {
46
+ return incomplete;
47
+ }
48
+ const expected = new Set(check.scope.map((file) => path.resolve(root, check.project, file)));
49
+ const files = new Set();
50
+ const ids = new Set();
51
+ const projects = new Set(report.projects);
52
+ const seenProjects = new Set();
53
+ if (projects.size !== report.projects.length)
54
+ return incomplete;
55
+ const tests = { total: 0, passed: 0, failed: 0, skipped: 0 };
56
+ let missingBrowserTests = 0;
57
+ for (const test of report.tests) {
58
+ if (!expected.has(test.file) ||
59
+ ids.has(test.id) ||
60
+ !projects.has(test.project))
61
+ return incomplete;
62
+ ids.add(test.id);
63
+ files.add(test.file);
64
+ seenProjects.add(test.project);
65
+ tests.total++;
66
+ if (!test.results.length)
67
+ return incomplete;
68
+ let missingBrowser = false;
69
+ for (const [index, attempt] of test.results.entries()) {
70
+ if (attempt.retry !== index || attempt.status === "interrupted")
71
+ return incomplete;
72
+ if (attempt.status === "passed" && attempt.errors.length)
73
+ return incomplete;
74
+ missingBrowser ||= attempt.errors.some((error) => /browserType\.launch: Executable doesn't exist at/.test(error));
75
+ }
76
+ if (missingBrowser)
77
+ missingBrowserTests++;
78
+ const last = test.results.at(-1);
79
+ if (test.outcome === "skipped") {
80
+ if (last.status !== "skipped")
81
+ return incomplete;
82
+ tests.skipped++;
83
+ }
84
+ else if (test.outcome === "expected") {
85
+ if (last.status !== test.expectedStatus)
86
+ return incomplete;
87
+ if (test.expectedStatus === "passed") {
88
+ if (test.results.some((attempt) => attempt.status !== "passed"))
89
+ return incomplete;
90
+ tests.passed++;
91
+ }
92
+ else
93
+ tests.skipped++;
94
+ }
95
+ else
96
+ tests.failed++;
97
+ }
98
+ if (missingBrowserTests &&
99
+ missingBrowserTests === tests.failed &&
100
+ !report.errors.length)
101
+ return {
102
+ status: "unavailable",
103
+ reason: "Playwright reported a missing browser executable; browsers must be prepared separately.",
104
+ tests,
105
+ };
106
+ if (report.status === "interrupted" || report.status === "skipped")
107
+ return incomplete;
108
+ if (tests.failed ||
109
+ report.errors.length ||
110
+ report.status !== "passed" ||
111
+ process.exitCode !== 0)
112
+ return {
113
+ status: "failed",
114
+ reason: "Playwright reported failed/flaky tests or a native runner error.",
115
+ tests,
116
+ };
117
+ if (files.size !== expected.size ||
118
+ seenProjects.size !== projects.size ||
119
+ !tests.passed ||
120
+ tests.skipped)
121
+ return { ...incomplete, tests };
122
+ return {
123
+ status: "passed",
124
+ reason: "Playwright completed passing non-skipped tests for every planned test file.",
125
+ tests,
126
+ };
127
+ }
@@ -0,0 +1,10 @@
1
+ import type { FullConfig, FullResult, Reporter, Suite, TestError } from "@playwright/test/reporter";
2
+ export default class EvidenceReporter implements Reporter {
3
+ private suite?;
4
+ private errors;
5
+ private projects;
6
+ onBegin(config: FullConfig, suite: Suite): void;
7
+ onError(error: TestError): void;
8
+ onEnd(result: FullResult): void;
9
+ printsToStdio(): boolean;
10
+ }
@@ -0,0 +1,37 @@
1
+ import { stripVTControlCharacters } from "node:util";
2
+ const message = (error) => stripVTControlCharacters(error.message ?? error.value ?? "Unknown Playwright error");
3
+ export default class EvidenceReporter {
4
+ suite;
5
+ errors = [];
6
+ projects = [];
7
+ onBegin(config, suite) {
8
+ this.suite = suite;
9
+ this.projects = config.projects.map((project) => project.name);
10
+ }
11
+ onError(error) {
12
+ this.errors.push(message(error));
13
+ }
14
+ onEnd(result) {
15
+ process.stdout.write(`${JSON.stringify({
16
+ version: 1,
17
+ status: result.status,
18
+ errors: this.errors,
19
+ projects: this.projects,
20
+ tests: this.suite?.allTests().map((test) => ({
21
+ id: test.id,
22
+ file: test.location.file,
23
+ project: test.parent.project()?.name,
24
+ expectedStatus: test.expectedStatus,
25
+ outcome: test.outcome(),
26
+ results: test.results.map((attempt) => ({
27
+ status: attempt.status,
28
+ retry: attempt.retry,
29
+ errors: attempt.errors.map(message),
30
+ })),
31
+ })) ?? [],
32
+ })}\n`);
33
+ }
34
+ printsToStdio() {
35
+ return true;
36
+ }
37
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,61 @@
1
+ import path from "node:path";
2
+ import { mkdtemp, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { createRequire } from "node:module";
5
+ import { fileURLToPath } from "node:url";
6
+ import { withinRoot } from "./inventory.js";
7
+ async function main() {
8
+ const [entry, root] = process.argv.slice(2);
9
+ if (!entry || !root)
10
+ throw new Error("Invalid Playwright runner arguments");
11
+ const tool = await withinRoot(root, path.relative(root, entry));
12
+ const require = createRequire(tool);
13
+ const metadata = require(tool);
14
+ if (metadata.name !== "playwright" || metadata.version !== "1.63.0")
15
+ throw new Error("Playwright native configuration integration requires verified version 1.63.0");
16
+ const { configLoader } = require("playwright/lib/common");
17
+ const { testRunner } = require("playwright/lib/runner");
18
+ const output = await mkdtemp(path.join(tmpdir(), "checktrail-playwright-"));
19
+ try {
20
+ const config = await configLoader.loadConfigFromFile(process.cwd(), {
21
+ forbidOnly: true,
22
+ failOnFlakyTests: true,
23
+ maxFailures: 0,
24
+ updateSnapshots: "none",
25
+ updateSourceMethod: "patch",
26
+ ignoreSnapshots: false,
27
+ shard: null,
28
+ outputDir: output,
29
+ workers: 1,
30
+ quiet: true,
31
+ reporter: [
32
+ [fileURLToPath(new URL("./playwright-reporter.js", import.meta.url))],
33
+ ],
34
+ });
35
+ if (config.webServers.length || config.plugins.length)
36
+ throw new Error("Playwright webServer and private runner plugins require separately supported execution profiles");
37
+ if (new Set(config.projects.map(({ project }) => project.name)).size !==
38
+ config.projects.length)
39
+ throw new Error("Playwright project names must be unique for evidence accounting");
40
+ config.captureGitInfo = { commit: false, diff: false };
41
+ config.config.grep = /.*/;
42
+ config.config.grepInvert = null;
43
+ for (const { project } of config.projects) {
44
+ project.grep = /.*/;
45
+ project.grepInvert = null;
46
+ }
47
+ const status = await testRunner.runAllTestsWithConfig(config, {
48
+ listMode: false,
49
+ passWithNoTests: false,
50
+ lastFailed: false,
51
+ });
52
+ process.exitCode = status === "passed" ? 0 : 1;
53
+ }
54
+ finally {
55
+ await rm(output, { recursive: true, force: true });
56
+ }
57
+ }
58
+ main().catch((error) => {
59
+ process.stderr.write(`${error instanceof Error ? error.message : "Playwright execution failed"}\n`);
60
+ process.exitCode = 2;
61
+ });
@@ -0,0 +1,2 @@
1
+ import type { Check, Inventory, Project } from "./types.js";
2
+ export declare function playwrightCheck(source: Inventory, project: Project): Promise<Check>;
@@ -0,0 +1,35 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { localTool } from "./local-tool.js";
3
+ export async function playwrightCheck(source, project) {
4
+ const files = project.files.filter((file) => /\.(?:test|spec)\.(?:[cm]?[jt]s|[jt]sx)$/.test(file));
5
+ const tool = await localTool(source.root, project.path, "playwright/package.json");
6
+ const check = {
7
+ id: "javascript.playwright",
8
+ adapter: project.adapter,
9
+ project: project.path,
10
+ kind: "test",
11
+ parser: "playwright-json",
12
+ scope: files,
13
+ reason: "Run installed Playwright with complete native test evidence, focused-test rejection and snapshot updates disabled.",
14
+ commands: tool
15
+ ? [
16
+ {
17
+ executable: process.execPath,
18
+ cwd: project.path,
19
+ args: [
20
+ fileURLToPath(new URL("./playwright-runner.js", import.meta.url)),
21
+ tool,
22
+ source.root,
23
+ ],
24
+ env: { CI: "1", PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" },
25
+ },
26
+ ]
27
+ : [],
28
+ };
29
+ if (!files.length)
30
+ check.unavailableReason = "No .test or .spec JS/TS files were inventoried.";
31
+ else if (!tool)
32
+ check.unavailableReason =
33
+ "Playwright is not installed within the configured root.";
34
+ return check;
35
+ }
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ export declare const packReferenceSchema: z.ZodObject<{
3
+ path: z.ZodString;
4
+ sha256: z.ZodString;
5
+ }, z.core.$strict>;
6
+ export declare const policyPackSchema: z.ZodObject<{
7
+ schemaVersion: z.ZodLiteral<1>;
8
+ id: z.ZodString;
9
+ version: z.ZodString;
10
+ description: z.ZodString;
11
+ requiredChecks: z.ZodArray<z.ZodString>;
12
+ requiredEnvironment: z.ZodOptional<z.ZodArray<z.ZodString>>;
13
+ }, z.core.$strict>;
14
+ export type PolicyPack = z.infer<typeof policyPackSchema>;
15
+ export type PackReference = z.infer<typeof packReferenceSchema>;
16
+ export interface LoadedPack {
17
+ pack: PolicyPack;
18
+ sha256: string;
19
+ }
20
+ export declare function parsePolicyPack(contents: string): PolicyPack;
21
+ export declare function loadPolicyPack(root: string, input: PackReference): Promise<LoadedPack>;