@cyanautomation/kaseki-agent 1.4.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 (459) hide show
  1. package/.dockerignore +54 -0
  2. package/.eslintignore +11 -0
  3. package/.eslintrc.json +95 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +53 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +53 -0
  6. package/.github/ISSUE_TEMPLATE/security.md +51 -0
  7. package/.github/PULL_REQUEST_TEMPLATE/default.md +71 -0
  8. package/.github/dependabot.yml +38 -0
  9. package/.github/skills/dependency-cache-optimization/SKILL.md +526 -0
  10. package/.github/skills/docker-image-management/SKILL.md +532 -0
  11. package/.github/skills/frontend-design/SKILL.md +782 -0
  12. package/.github/skills/prompt-engineering/SKILL.md +360 -0
  13. package/.github/skills/quality-gate-config/SKILL.md +591 -0
  14. package/.github/skills/result-report-analysis/SKILL.md +576 -0
  15. package/.github/skills/test-automation/SKILL.md +593 -0
  16. package/.github/skills/workflow-diagnosis/SKILL.md +468 -0
  17. package/.github/workflows/build-docker-image.yml +453 -0
  18. package/.github/workflows/release.yml +68 -0
  19. package/.releaserc.json +135 -0
  20. package/CHANGELOG.md +117 -0
  21. package/CLAUDE.md +336 -0
  22. package/CONTRIBUTING.md +339 -0
  23. package/Dockerfile +217 -0
  24. package/README.md +1527 -0
  25. package/STYLE.md +521 -0
  26. package/add-js-extensions.d.ts +9 -0
  27. package/add-js-extensions.d.ts.map +1 -0
  28. package/add-js-extensions.js.map +1 -0
  29. package/dist/add-js-extensions.d.ts +9 -0
  30. package/dist/add-js-extensions.d.ts.map +1 -0
  31. package/dist/add-js-extensions.js +52 -0
  32. package/dist/add-js-extensions.js.map +1 -0
  33. package/dist/ansi-colors.d.ts +26 -0
  34. package/dist/ansi-colors.d.ts.map +1 -0
  35. package/dist/ansi-colors.js +51 -0
  36. package/dist/ansi-colors.js.map +1 -0
  37. package/dist/cli/BaseCommand.d.ts +18 -0
  38. package/dist/cli/BaseCommand.d.ts.map +1 -0
  39. package/dist/cli/BaseCommand.js +31 -0
  40. package/dist/cli/BaseCommand.js.map +1 -0
  41. package/dist/cli/KasekiCLI.d.ts +30 -0
  42. package/dist/cli/KasekiCLI.d.ts.map +1 -0
  43. package/dist/cli/KasekiCLI.js +134 -0
  44. package/dist/cli/KasekiCLI.js.map +1 -0
  45. package/dist/cli/commands/ConfigCommand.d.ts +13 -0
  46. package/dist/cli/commands/ConfigCommand.d.ts.map +1 -0
  47. package/dist/cli/commands/ConfigCommand.js +131 -0
  48. package/dist/cli/commands/ConfigCommand.js.map +1 -0
  49. package/dist/cli/commands/DoctorCommand.d.ts +45 -0
  50. package/dist/cli/commands/DoctorCommand.d.ts.map +1 -0
  51. package/dist/cli/commands/DoctorCommand.js +309 -0
  52. package/dist/cli/commands/DoctorCommand.js.map +1 -0
  53. package/dist/cli/commands/ListCommand.d.ts +9 -0
  54. package/dist/cli/commands/ListCommand.d.ts.map +1 -0
  55. package/dist/cli/commands/ListCommand.js +81 -0
  56. package/dist/cli/commands/ListCommand.js.map +1 -0
  57. package/dist/cli/commands/ReportCommand.d.ts +9 -0
  58. package/dist/cli/commands/ReportCommand.d.ts.map +1 -0
  59. package/dist/cli/commands/ReportCommand.js +98 -0
  60. package/dist/cli/commands/ReportCommand.js.map +1 -0
  61. package/dist/cli/commands/RunCommand.d.ts +13 -0
  62. package/dist/cli/commands/RunCommand.d.ts.map +1 -0
  63. package/dist/cli/commands/RunCommand.js +191 -0
  64. package/dist/cli/commands/RunCommand.js.map +1 -0
  65. package/dist/cli/commands/SecretsCommand.d.ts +9 -0
  66. package/dist/cli/commands/SecretsCommand.d.ts.map +1 -0
  67. package/dist/cli/commands/SecretsCommand.js +109 -0
  68. package/dist/cli/commands/SecretsCommand.js.map +1 -0
  69. package/dist/cli/commands/ServeCommand.d.ts +9 -0
  70. package/dist/cli/commands/ServeCommand.d.ts.map +1 -0
  71. package/dist/cli/commands/ServeCommand.js +50 -0
  72. package/dist/cli/commands/ServeCommand.js.map +1 -0
  73. package/dist/cli/commands/SetupCommand.d.ts +42 -0
  74. package/dist/cli/commands/SetupCommand.d.ts.map +1 -0
  75. package/dist/cli/commands/SetupCommand.js +249 -0
  76. package/dist/cli/commands/SetupCommand.js.map +1 -0
  77. package/dist/cli.d.ts +9 -0
  78. package/dist/cli.d.ts.map +1 -0
  79. package/dist/cli.js +130 -0
  80. package/dist/cli.js.map +1 -0
  81. package/dist/config/ConfigManager.d.ts +395 -0
  82. package/dist/config/ConfigManager.d.ts.map +1 -0
  83. package/dist/config/ConfigManager.js +446 -0
  84. package/dist/config/ConfigManager.js.map +1 -0
  85. package/dist/docker/DockerManager.d.ts +69 -0
  86. package/dist/docker/DockerManager.d.ts.map +1 -0
  87. package/dist/docker/DockerManager.js +266 -0
  88. package/dist/docker/DockerManager.js.map +1 -0
  89. package/dist/event-aggregator.d.ts +71 -0
  90. package/dist/event-aggregator.d.ts.map +1 -0
  91. package/dist/event-aggregator.js +95 -0
  92. package/dist/event-aggregator.js.map +1 -0
  93. package/dist/github-app-token.d.ts +16 -0
  94. package/dist/github-app-token.d.ts.map +1 -0
  95. package/dist/github-app-token.js +148 -0
  96. package/dist/github-app-token.js.map +1 -0
  97. package/dist/idempotency-store.d.ts +61 -0
  98. package/dist/idempotency-store.d.ts.map +1 -0
  99. package/dist/idempotency-store.js +321 -0
  100. package/dist/idempotency-store.js.map +1 -0
  101. package/dist/index.d.ts +25 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +31 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/instance/InstanceManager.d.ts +81 -0
  106. package/dist/instance/InstanceManager.d.ts.map +1 -0
  107. package/dist/instance/InstanceManager.js +220 -0
  108. package/dist/instance/InstanceManager.js.map +1 -0
  109. package/dist/instance-metadata-reader.d.ts +48 -0
  110. package/dist/instance-metadata-reader.d.ts.map +1 -0
  111. package/dist/instance-metadata-reader.js +94 -0
  112. package/dist/instance-metadata-reader.js.map +1 -0
  113. package/dist/instance-state-derivation.d.ts +42 -0
  114. package/dist/instance-state-derivation.d.ts.map +1 -0
  115. package/dist/instance-state-derivation.js +133 -0
  116. package/dist/instance-state-derivation.js.map +1 -0
  117. package/dist/job-scheduler.d.ts +124 -0
  118. package/dist/job-scheduler.d.ts.map +1 -0
  119. package/dist/job-scheduler.js +992 -0
  120. package/dist/job-scheduler.js.map +1 -0
  121. package/dist/kaseki-api-client.d.ts +89 -0
  122. package/dist/kaseki-api-client.d.ts.map +1 -0
  123. package/dist/kaseki-api-client.js +405 -0
  124. package/dist/kaseki-api-client.js.map +1 -0
  125. package/dist/kaseki-api-config.d.ts +34 -0
  126. package/dist/kaseki-api-config.d.ts.map +1 -0
  127. package/dist/kaseki-api-config.js +113 -0
  128. package/dist/kaseki-api-config.js.map +1 -0
  129. package/dist/kaseki-api-routes.d.ts +13 -0
  130. package/dist/kaseki-api-routes.d.ts.map +1 -0
  131. package/dist/kaseki-api-routes.js +559 -0
  132. package/dist/kaseki-api-routes.js.map +1 -0
  133. package/dist/kaseki-api-service-wrapper.d.ts +43 -0
  134. package/dist/kaseki-api-service-wrapper.d.ts.map +1 -0
  135. package/dist/kaseki-api-service-wrapper.js +150 -0
  136. package/dist/kaseki-api-service-wrapper.js.map +1 -0
  137. package/dist/kaseki-api-service.d.ts +16 -0
  138. package/dist/kaseki-api-service.d.ts.map +1 -0
  139. package/dist/kaseki-api-service.js +143 -0
  140. package/dist/kaseki-api-service.js.map +1 -0
  141. package/dist/kaseki-api-types.d.ts +440 -0
  142. package/dist/kaseki-api-types.d.ts.map +1 -0
  143. package/dist/kaseki-api-types.js +64 -0
  144. package/dist/kaseki-api-types.js.map +1 -0
  145. package/dist/kaseki-cli-lib.d.ts +219 -0
  146. package/dist/kaseki-cli-lib.d.ts.map +1 -0
  147. package/dist/kaseki-cli-lib.js +523 -0
  148. package/dist/kaseki-cli-lib.js.map +1 -0
  149. package/dist/kaseki-cli.d.ts +38 -0
  150. package/dist/kaseki-cli.d.ts.map +1 -0
  151. package/dist/kaseki-cli.js +559 -0
  152. package/dist/kaseki-cli.js.map +1 -0
  153. package/dist/kaseki-report.d.ts +3 -0
  154. package/dist/kaseki-report.d.ts.map +1 -0
  155. package/dist/kaseki-report.js +140 -0
  156. package/dist/kaseki-report.js.map +1 -0
  157. package/dist/lib/subprocess-helpers.d.ts +98 -0
  158. package/dist/lib/subprocess-helpers.d.ts.map +1 -0
  159. package/dist/lib/subprocess-helpers.js +136 -0
  160. package/dist/lib/subprocess-helpers.js.map +1 -0
  161. package/dist/logger.d.ts +39 -0
  162. package/dist/logger.d.ts.map +1 -0
  163. package/dist/logger.js +79 -0
  164. package/dist/logger.js.map +1 -0
  165. package/dist/metrics.d.ts +19 -0
  166. package/dist/metrics.d.ts.map +1 -0
  167. package/dist/metrics.js +59 -0
  168. package/dist/metrics.js.map +1 -0
  169. package/dist/middleware/job-lookup.d.ts +27 -0
  170. package/dist/middleware/job-lookup.d.ts.map +1 -0
  171. package/dist/middleware/job-lookup.js +28 -0
  172. package/dist/middleware/job-lookup.js.map +1 -0
  173. package/dist/pi-event-filter.d.ts +3 -0
  174. package/dist/pi-event-filter.d.ts.map +1 -0
  175. package/dist/pi-event-filter.js +126 -0
  176. package/dist/pi-event-filter.js.map +1 -0
  177. package/dist/pi-progress-stream.d.ts +3 -0
  178. package/dist/pi-progress-stream.d.ts.map +1 -0
  179. package/dist/pi-progress-stream.js +205 -0
  180. package/dist/pi-progress-stream.js.map +1 -0
  181. package/dist/pi-progress-summarizer.d.ts +61 -0
  182. package/dist/pi-progress-summarizer.d.ts.map +1 -0
  183. package/dist/pi-progress-summarizer.js +246 -0
  184. package/dist/pi-progress-summarizer.js.map +1 -0
  185. package/dist/pre-flight-validator.d.ts +72 -0
  186. package/dist/pre-flight-validator.d.ts.map +1 -0
  187. package/dist/pre-flight-validator.js +513 -0
  188. package/dist/pre-flight-validator.js.map +1 -0
  189. package/dist/progress-stream-utils.d.ts +3 -0
  190. package/dist/progress-stream-utils.d.ts.map +1 -0
  191. package/dist/progress-stream-utils.js +15 -0
  192. package/dist/progress-stream-utils.js.map +1 -0
  193. package/dist/result-cache.d.ts +52 -0
  194. package/dist/result-cache.d.ts.map +1 -0
  195. package/dist/result-cache.js +134 -0
  196. package/dist/result-cache.js.map +1 -0
  197. package/dist/routes/artifact-routes.d.ts +10 -0
  198. package/dist/routes/artifact-routes.d.ts.map +1 -0
  199. package/dist/routes/artifact-routes.js +126 -0
  200. package/dist/routes/artifact-routes.js.map +1 -0
  201. package/dist/routes/log-routes.d.ts +8 -0
  202. package/dist/routes/log-routes.d.ts.map +1 -0
  203. package/dist/routes/log-routes.js +345 -0
  204. package/dist/routes/log-routes.js.map +1 -0
  205. package/dist/routes/status-routes.d.ts +8 -0
  206. package/dist/routes/status-routes.d.ts.map +1 -0
  207. package/dist/routes/status-routes.js +82 -0
  208. package/dist/routes/status-routes.js.map +1 -0
  209. package/dist/routes/webhook-routes.d.ts +6 -0
  210. package/dist/routes/webhook-routes.d.ts.map +1 -0
  211. package/dist/routes/webhook-routes.js +86 -0
  212. package/dist/routes/webhook-routes.js.map +1 -0
  213. package/dist/run-artifact-metadata-cache.d.ts +42 -0
  214. package/dist/run-artifact-metadata-cache.d.ts.map +1 -0
  215. package/dist/run-artifact-metadata-cache.js +139 -0
  216. package/dist/run-artifact-metadata-cache.js.map +1 -0
  217. package/dist/secret-value-cache.d.ts +13 -0
  218. package/dist/secret-value-cache.d.ts.map +1 -0
  219. package/dist/secret-value-cache.js +44 -0
  220. package/dist/secret-value-cache.js.map +1 -0
  221. package/dist/secrets/SecretsManager.d.ts +80 -0
  222. package/dist/secrets/SecretsManager.d.ts.map +1 -0
  223. package/dist/secrets/SecretsManager.js +306 -0
  224. package/dist/secrets/SecretsManager.js.map +1 -0
  225. package/dist/test-utils.d.ts +55 -0
  226. package/dist/test-utils.d.ts.map +1 -0
  227. package/dist/test-utils.js +48 -0
  228. package/dist/test-utils.js.map +1 -0
  229. package/dist/timestamp-tracker.d.ts +75 -0
  230. package/dist/timestamp-tracker.d.ts.map +1 -0
  231. package/dist/timestamp-tracker.js +121 -0
  232. package/dist/timestamp-tracker.js.map +1 -0
  233. package/dist/utils/failure-artifact-writer.d.ts +29 -0
  234. package/dist/utils/failure-artifact-writer.d.ts.map +1 -0
  235. package/dist/utils/failure-artifact-writer.js +157 -0
  236. package/dist/utils/failure-artifact-writer.js.map +1 -0
  237. package/dist/utils/file-helpers.d.ts +41 -0
  238. package/dist/utils/file-helpers.d.ts.map +1 -0
  239. package/dist/utils/file-helpers.js +143 -0
  240. package/dist/utils/file-helpers.js.map +1 -0
  241. package/dist/utils/http-client-factory.d.ts +46 -0
  242. package/dist/utils/http-client-factory.d.ts.map +1 -0
  243. package/dist/utils/http-client-factory.js +114 -0
  244. package/dist/utils/http-client-factory.js.map +1 -0
  245. package/dist/utils/progress-normalizer.d.ts +13 -0
  246. package/dist/utils/progress-normalizer.d.ts.map +1 -0
  247. package/dist/utils/progress-normalizer.js +57 -0
  248. package/dist/utils/progress-normalizer.js.map +1 -0
  249. package/dist/utils/response-helpers.d.ts +34 -0
  250. package/dist/utils/response-helpers.d.ts.map +1 -0
  251. package/dist/utils/response-helpers.js +78 -0
  252. package/dist/utils/response-helpers.js.map +1 -0
  253. package/dist/utils/route-helpers.d.ts +17 -0
  254. package/dist/utils/route-helpers.d.ts.map +1 -0
  255. package/dist/utils/route-helpers.js +22 -0
  256. package/dist/utils/route-helpers.js.map +1 -0
  257. package/dist/utils/status-response-builder.d.ts +23 -0
  258. package/dist/utils/status-response-builder.d.ts.map +1 -0
  259. package/dist/utils/status-response-builder.js +144 -0
  260. package/dist/utils/status-response-builder.js.map +1 -0
  261. package/dist/utils/type-guards.d.ts +37 -0
  262. package/dist/utils/type-guards.d.ts.map +1 -0
  263. package/dist/utils/type-guards.js +45 -0
  264. package/dist/utils/type-guards.js.map +1 -0
  265. package/dist/utils/utf8-helpers.d.ts +32 -0
  266. package/dist/utils/utf8-helpers.d.ts.map +1 -0
  267. package/dist/utils/utf8-helpers.js +97 -0
  268. package/dist/utils/utf8-helpers.js.map +1 -0
  269. package/dist/utils/webhook-event-builder.d.ts +26 -0
  270. package/dist/utils/webhook-event-builder.d.ts.map +1 -0
  271. package/dist/utils/webhook-event-builder.js +77 -0
  272. package/dist/utils/webhook-event-builder.js.map +1 -0
  273. package/dist/webhook-manager.d.ts +56 -0
  274. package/dist/webhook-manager.d.ts.map +1 -0
  275. package/dist/webhook-manager.js +359 -0
  276. package/dist/webhook-manager.js.map +1 -0
  277. package/docker/workspace-cache/package-lock.json +13 -0
  278. package/docker/workspace-cache/package.json +7 -0
  279. package/docker-compose.yml +53 -0
  280. package/docs/API.md +708 -0
  281. package/docs/BACKLOG.md +19 -0
  282. package/docs/BUILD_STRATEGY.md +404 -0
  283. package/docs/CLI.md +569 -0
  284. package/docs/DEPLOYMENT.md +521 -0
  285. package/docs/DEVELOPMENT.md +459 -0
  286. package/docs/DOCKER_SETUP.md +522 -0
  287. package/docs/ENHANCED_PROGRESS_LOGS.md +264 -0
  288. package/docs/IMPLEMENTATION_SUMMARY.md +549 -0
  289. package/docs/INTEGRATION_EXAMPLE.md +217 -0
  290. package/docs/NPM_SETUP.md +468 -0
  291. package/docs/PHASE1-4_IMPLEMENTATION.md +302 -0
  292. package/docs/PHASE1_COMPLETION.md +192 -0
  293. package/docs/PHASE2_COMPLETION.md +134 -0
  294. package/docs/PHASE6_MIGRATION.md +392 -0
  295. package/docs/PRINTF_SAFETY_FIX.md +282 -0
  296. package/docs/QUALITY_GATES.md +369 -0
  297. package/docs/SETUP_GUIDE.md +482 -0
  298. package/docs/TASK_PROMPT_TEMPLATES.md +533 -0
  299. package/docs/VALIDATION_FIX.md +139 -0
  300. package/docs/VERIFICATION_CHECKLIST.md +335 -0
  301. package/docs/repo-maturity.md +760 -0
  302. package/fix-tests.d.ts +9 -0
  303. package/fix-tests.d.ts.map +1 -0
  304. package/fix-tests.js.map +1 -0
  305. package/fix-tests.ts +53 -0
  306. package/jest.config.ts +31 -0
  307. package/kaseki +183 -0
  308. package/kaseki-agent.sh +1961 -0
  309. package/ops/logrotate/kaseki +10 -0
  310. package/package.json +83 -0
  311. package/perf/README.md +54 -0
  312. package/perf/pi-event-filter.benchmark.test.ts +98 -0
  313. package/run-kaseki-json.test.sh +106 -0
  314. package/run-kaseki.sh +990 -0
  315. package/scripts/allowlist-helper.sh +56 -0
  316. package/scripts/cleanup-kaseki.sh +168 -0
  317. package/scripts/deploy-pi-template.sh +293 -0
  318. package/scripts/docker-entrypoint.sh +71 -0
  319. package/scripts/dry-run-allowlist.sh +161 -0
  320. package/scripts/kaseki-activate.sh +396 -0
  321. package/scripts/kaseki-api.service +62 -0
  322. package/scripts/kaseki-container-entrypoint-wrapper.sh +119 -0
  323. package/scripts/kaseki-container-setup-remote.sh +172 -0
  324. package/scripts/kaseki-container-setup.sh +193 -0
  325. package/scripts/kaseki-healthcheck.sh +95 -0
  326. package/scripts/kaseki-install.sh +50 -0
  327. package/scripts/kaseki-maturity-score.sh +291 -0
  328. package/scripts/kaseki-performance-metrics.sh +122 -0
  329. package/scripts/kaseki-preflight.sh +270 -0
  330. package/scripts/kaseki-setup.sh +265 -0
  331. package/scripts/pi-setup-remote.sh +213 -0
  332. package/scripts/setup-github-labels.sh +42 -0
  333. package/scripts/suggest-allowlist.sh +68 -0
  334. package/scripts/templates/MULTI_HOST_DISTRIBUTED.md +337 -0
  335. package/scripts/templates/REST_API_SERVICE.md +490 -0
  336. package/scripts/templates/SINGLE_HOST_CLI.md +194 -0
  337. package/scripts/test-github-app.sh +248 -0
  338. package/src/add-js-extensions.ts +61 -0
  339. package/src/ansi-colors.test.ts +62 -0
  340. package/src/ansi-colors.ts +67 -0
  341. package/src/cli/BaseCommand.ts +40 -0
  342. package/src/cli/KasekiCLI.ts +154 -0
  343. package/src/cli/commands/ConfigCommand.ts +145 -0
  344. package/src/cli/commands/DoctorCommand.ts +329 -0
  345. package/src/cli/commands/ListCommand.ts +105 -0
  346. package/src/cli/commands/ReportCommand.ts +110 -0
  347. package/src/cli/commands/RunCommand.ts +218 -0
  348. package/src/cli/commands/SecretsCommand.ts +120 -0
  349. package/src/cli/commands/ServeCommand.ts +62 -0
  350. package/src/cli/commands/SetupCommand.ts +301 -0
  351. package/src/cli.ts +138 -0
  352. package/src/config/ConfigManager.ts +476 -0
  353. package/src/docker/DockerManager.ts +319 -0
  354. package/src/docker-entrypoint-packaging.test.ts +33 -0
  355. package/src/event-aggregator.test.ts +117 -0
  356. package/src/event-aggregator.ts +126 -0
  357. package/src/github-app-token.ts +215 -0
  358. package/src/idempotency-store.test.ts +117 -0
  359. package/src/idempotency-store.ts +385 -0
  360. package/src/index.ts +89 -0
  361. package/src/instance/InstanceManager.ts +285 -0
  362. package/src/instance-metadata-reader.test.ts +190 -0
  363. package/src/instance-metadata-reader.ts +129 -0
  364. package/src/instance-state-derivation.test.ts +263 -0
  365. package/src/instance-state-derivation.ts +148 -0
  366. package/src/job-scheduler.test.ts +1236 -0
  367. package/src/job-scheduler.ts +1117 -0
  368. package/src/kaseki-api-client.ts +488 -0
  369. package/src/kaseki-api-config.test.ts +315 -0
  370. package/src/kaseki-api-config.ts +175 -0
  371. package/src/kaseki-api-routes.test.ts +1615 -0
  372. package/src/kaseki-api-routes.ts +643 -0
  373. package/src/kaseki-api-service-wrapper.ts +188 -0
  374. package/src/kaseki-api-service.test.ts +418 -0
  375. package/src/kaseki-api-service.ts +192 -0
  376. package/src/kaseki-api-types.ts +320 -0
  377. package/src/kaseki-cli-lib.test.ts +552 -0
  378. package/src/kaseki-cli-lib.ts +760 -0
  379. package/src/kaseki-cli.ts +682 -0
  380. package/src/kaseki-report.test.ts +118 -0
  381. package/src/kaseki-report.ts +192 -0
  382. package/src/lib/subprocess-helpers.ts +177 -0
  383. package/src/logger.ts +114 -0
  384. package/src/metrics.ts +66 -0
  385. package/src/middleware/job-lookup.test.ts +113 -0
  386. package/src/middleware/job-lookup.ts +45 -0
  387. package/src/pi-event-filter.test.ts +183 -0
  388. package/src/pi-event-filter.ts +183 -0
  389. package/src/pi-progress-stream.ts +287 -0
  390. package/src/pi-progress-summarizer.test.ts +302 -0
  391. package/src/pi-progress-summarizer.ts +287 -0
  392. package/src/pre-flight-validator.test.ts +512 -0
  393. package/src/pre-flight-validator.ts +618 -0
  394. package/src/progress-stream-utils.test.ts +35 -0
  395. package/src/progress-stream-utils.ts +14 -0
  396. package/src/result-cache.test.ts +195 -0
  397. package/src/result-cache.ts +181 -0
  398. package/src/routes/artifact-routes.ts +169 -0
  399. package/src/routes/log-routes.ts +391 -0
  400. package/src/routes/status-routes.ts +92 -0
  401. package/src/routes/webhook-routes.ts +97 -0
  402. package/src/run-artifact-metadata-cache.test.ts +80 -0
  403. package/src/run-artifact-metadata-cache.ts +184 -0
  404. package/src/secret-value-cache.test.ts +66 -0
  405. package/src/secret-value-cache.ts +55 -0
  406. package/src/secrets/SecretsManager.ts +343 -0
  407. package/src/test-utils.ts +81 -0
  408. package/src/timestamp-tracker.test.ts +134 -0
  409. package/src/timestamp-tracker.ts +132 -0
  410. package/src/utils/failure-artifact-writer.ts +187 -0
  411. package/src/utils/file-helpers.test.ts +235 -0
  412. package/src/utils/file-helpers.ts +150 -0
  413. package/src/utils/http-client-factory.test.ts +245 -0
  414. package/src/utils/http-client-factory.ts +157 -0
  415. package/src/utils/progress-normalizer.test.ts +442 -0
  416. package/src/utils/progress-normalizer.ts +68 -0
  417. package/src/utils/response-helpers.test.ts +122 -0
  418. package/src/utils/response-helpers.ts +101 -0
  419. package/src/utils/route-helpers.ts +30 -0
  420. package/src/utils/status-response-builder.ts +159 -0
  421. package/src/utils/type-guards.ts +52 -0
  422. package/src/utils/utf8-helpers.ts +102 -0
  423. package/src/utils/webhook-event-builder.test.ts +143 -0
  424. package/src/utils/webhook-event-builder.ts +87 -0
  425. package/src/webhook-manager.test.ts +152 -0
  426. package/src/webhook-manager.ts +445 -0
  427. package/templates/allowlist-api-route.txt +7 -0
  428. package/templates/allowlist-comprehensive.txt +8 -0
  429. package/templates/allowlist-parser-fix.txt +6 -0
  430. package/templates/allowlist-ui-component.txt +9 -0
  431. package/templates/allowlist-utility.txt +9 -0
  432. package/test/actual-model-metadata.test.sh +102 -0
  433. package/test/dry-run.test.sh +131 -0
  434. package/test/fixtures/kaseki-report-exit-codes/metadata-exit-0.json +1 -0
  435. package/test/fixtures/kaseki-report-exit-codes/metadata-exit-1.json +1 -0
  436. package/test/fixtures/kaseki-report-exit-codes/metadata-exit-invalid.json +1 -0
  437. package/test/fixtures/kaseki-report-exit-codes/metadata-exit-str-0.json +1 -0
  438. package/test/fixtures/kaseki-report-exit-codes/metadata-exit-str-1.json +1 -0
  439. package/test/kaseki-api.integration.test.sh +165 -0
  440. package/test/pi-event-filter-failure.test.sh +83 -0
  441. package/test/printf-safety-focused.test.sh +99 -0
  442. package/test/printf-safety-results/results/restoration.jsonl +10 -0
  443. package/test/printf-safety-results/results/test.jsonl +0 -0
  444. package/test/printf-safety.test.sh +297 -0
  445. package/test/validation-fix.test.sh +79 -0
  446. package/test/validation-integration.test.sh +109 -0
  447. package/tests/allowlist-glob.test.sh +61 -0
  448. package/tests/dependency-cache-key.test.sh +48 -0
  449. package/tests/dependency-restore-mode.test.sh +48 -0
  450. package/tests/doctor-template-parity.test.sh +95 -0
  451. package/tests/github-operations.test.sh +142 -0
  452. package/tests/npm-install-flags.test.sh +58 -0
  453. package/tests/quality-gates.test.sh +178 -0
  454. package/tests/repo-memory.test.sh +103 -0
  455. package/tests/restore-disallowed-changes.test.sh +80 -0
  456. package/tests/validation-missing-npm-scripts.test.sh +93 -0
  457. package/tests/validation-strict-mode.test.sh +118 -0
  458. package/tsconfig.changed.json +7 -0
  459. package/tsconfig.json +39 -0
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/env bash
2
+ # kaseki-maturity-score.sh
3
+ # Calculates the kaseki-agent repository maturity score and outputs JSON
4
+ #
5
+ # This script evaluates the repository against 9 maturity signal categories:
6
+ # 1. Setup & Installation
7
+ # 2. Testing & Quality
8
+ # 3. CI/CD & Automation
9
+ # 4. Documentation
10
+ # 5. Governance
11
+ # 6. Security
12
+ # 7. Operability
13
+ # 8. Performance & Efficiency
14
+ # 9. Maintenance & Sustainability
15
+ #
16
+ # Usage: kaseki-maturity-score.sh [repo_path] [output_json_file]
17
+ # Default: uses /workspace/repo and outputs to /results/maturity-score.json
18
+
19
+ set -euo pipefail
20
+
21
+ REPO_PATH="${1:-.}"
22
+ OUTPUT_FILE="${2:-/results/maturity-score.json}"
23
+
24
+ # Score tracking variables
25
+ SETUP_SCORE=0
26
+ TESTING_SCORE=0
27
+ CICD_SCORE=0
28
+ DOCS_SCORE=0
29
+ GOVERNANCE_SCORE=0
30
+ SECURITY_SCORE=0
31
+ OPERABILITY_SCORE=0
32
+ PERFORMANCE_SCORE=0
33
+ MAINTENANCE_SCORE=0
34
+
35
+ evaluate_setup() {
36
+ local score=0
37
+
38
+ # Check for package.json (1 point)
39
+ [ -f "$REPO_PATH/package.json" ] && score=$((score + 1))
40
+
41
+ # Check for package-lock.json (1 point)
42
+ [ -f "$REPO_PATH/package-lock.json" ] && score=$((score + 1))
43
+
44
+ # Check for TypeScript config (1 point)
45
+ [ -f "$REPO_PATH/tsconfig.json" ] && score=$((score + 1))
46
+
47
+ # Check for Dockerfile (1 point)
48
+ [ -f "$REPO_PATH/Dockerfile" ] && score=$((score + 1))
49
+
50
+ # Check for README (1 point)
51
+ [ -f "$REPO_PATH/README.md" ] && score=$((score + 1))
52
+
53
+ # Check for .gitignore (1 point)
54
+ [ -f "$REPO_PATH/.gitignore" ] && score=$((score + 1))
55
+
56
+ # Check for Node.js version pinned in Dockerfile (1 point)
57
+ grep -q "node:" "$REPO_PATH/Dockerfile" 2>/dev/null && score=$((score + 1))
58
+
59
+ SETUP_SCORE="$score"
60
+ }
61
+
62
+ evaluate_testing() {
63
+ local score=0
64
+
65
+ # Check for jest/test config (1 point)
66
+ [ -f "$REPO_PATH/jest.config.ts" ] || [ -f "$REPO_PATH/jest.config.js" ] && score=$((score + 1))
67
+
68
+ # Check for test directory (1 point)
69
+ [ -d "$REPO_PATH/test" ] && score=$((score + 1))
70
+
71
+ # Check for src test files (1 point)
72
+ find "$REPO_PATH/src" -name "*.test.ts" -o -name "*.test.js" 2>/dev/null | grep -q . && score=$((score + 1))
73
+
74
+ # Check for ESLint config (1 point)
75
+ [ -f "$REPO_PATH/.eslintrc" ] || [ -f "$REPO_PATH/.eslintrc.json" ] || [ -f "$REPO_PATH/.eslintrc.js" ] && score=$((score + 1))
76
+
77
+ # Check for TypeScript strict mode (1 point)
78
+ grep -q '"strict":\s*true' "$REPO_PATH/tsconfig.json" 2>/dev/null && score=$((score + 1))
79
+
80
+ TESTING_SCORE="$score"
81
+ }
82
+
83
+ evaluate_cicd() {
84
+ local score=0
85
+
86
+ # Check for GitHub Actions workflows (2 points)
87
+ [ -d "$REPO_PATH/.github/workflows" ] && score=$((score + 2))
88
+
89
+ # Check for build workflow (1 point)
90
+ find "$REPO_PATH/.github/workflows" \( -name "*.yml" -o -name "*.yaml" \) -print0 2>/dev/null | xargs -0 grep -l "build\|docker" 2>/dev/null | grep -q . && score=$((score + 1))
91
+
92
+ # Check for Dependabot config (1 point)
93
+ [ -f "$REPO_PATH/.github/dependabot.yml" ] && score=$((score + 1))
94
+
95
+ # Check for shell linting in workflows (1 point)
96
+ find "$REPO_PATH/.github/workflows" -name "*.yml" -print0 2>/dev/null | xargs -0 grep -l "shellcheck" 2>/dev/null | grep -q . && score=$((score + 1))
97
+
98
+ CICD_SCORE="$score"
99
+ }
100
+
101
+ evaluate_docs() {
102
+ local score=0
103
+
104
+ # Check for CONTRIBUTING.md (1 point)
105
+ [ -f "$REPO_PATH/CONTRIBUTING.md" ] && score=$((score + 1))
106
+
107
+ # Check for CLAUDE.md (1 point)
108
+ [ -f "$REPO_PATH/CLAUDE.md" ] && score=$((score + 1))
109
+
110
+ # Check for docs directory (1 point)
111
+ [ -d "$REPO_PATH/docs" ] && score=$((score + 1))
112
+
113
+ # Check for repo-maturity.md (1 point)
114
+ [ -f "$REPO_PATH/docs/repo-maturity.md" ] && score=$((score + 1))
115
+
116
+ # Check for well-structured README (1 point)
117
+ grep -q "## \|### " "$REPO_PATH/README.md" 2>/dev/null && score=$((score + 1))
118
+
119
+ DOCS_SCORE="$score"
120
+ }
121
+
122
+ evaluate_governance() {
123
+ local score=0
124
+
125
+ # Check for issue templates (1 point)
126
+ [ -d "$REPO_PATH/.github/ISSUE_TEMPLATE" ] && [ "$(find "$REPO_PATH/.github/ISSUE_TEMPLATE" -type f | wc -l)" -gt 0 ] && score=$((score + 1))
127
+
128
+ # Check for PR template (1 point)
129
+ [ -d "$REPO_PATH/.github/PULL_REQUEST_TEMPLATE" ] && [ "$(find "$REPO_PATH/.github/PULL_REQUEST_TEMPLATE" -type f | wc -l)" -gt 0 ] && score=$((score + 1))
130
+
131
+ # Check for STYLE.md or style guide (0.5 points, counted as 1 if present)
132
+ [ -f "$REPO_PATH/STYLE.md" ] && score=$((score + 1))
133
+
134
+ GOVERNANCE_SCORE="$score"
135
+ }
136
+
137
+ evaluate_security() {
138
+ local score=0
139
+
140
+ # Check for Trivy scanning in CI (1.5 points, rounded to 1 or 2)
141
+ find "$REPO_PATH/.github/workflows" -name "*.yml" -print0 2>/dev/null | xargs -0 grep -l "trivy\|Trivy" 2>/dev/null | grep -q . && score=$((score + 2))
142
+
143
+ # Check for no hardcoded secrets (1 point)
144
+ ! find "$REPO_PATH/src" -type f \( -name "*.ts" -o -name "*.js" \) -print0 2>/dev/null | xargs -0 grep -l "sk-or-\|OPENROUTER_API_KEY=" 2>/dev/null | grep -q . && score=$((score + 1))
145
+
146
+ # Check for Dockerfile security flags (1 point)
147
+ grep -q "cap-drop\|read-only\|security-opt" "$REPO_PATH/Dockerfile" 2>/dev/null && score=$((score + 1))
148
+
149
+ SECURITY_SCORE="$score"
150
+ }
151
+
152
+ evaluate_operability() {
153
+ local score=0
154
+
155
+ # Check for --dry-run support (1 point)
156
+ grep -q "KASEKI_DRY_RUN\|--dry-run" "$REPO_PATH/run-kaseki.sh" 2>/dev/null && score=$((score + 1))
157
+
158
+ # Check for structured logging (1 point)
159
+ grep -q "json_encode\|emit_progress\|emit_json_log" "$REPO_PATH/run-kaseki.sh" 2>/dev/null && score=$((score + 1))
160
+
161
+ # Check for health check script (1 point)
162
+ [ -f "$REPO_PATH/scripts/kaseki-healthcheck.sh" ] && score=$((score + 1))
163
+
164
+ # Check for metrics/timing tracking (1 point)
165
+ grep -q "stage-timings\|validation-timings" "$REPO_PATH/kaseki-agent.sh" 2>/dev/null && score=$((score + 1))
166
+
167
+ OPERABILITY_SCORE="$score"
168
+ }
169
+
170
+ evaluate_performance() {
171
+ local score=0
172
+
173
+ # Check for dependency caching (2 points)
174
+ grep -q "kaseki-cache\|KASEKI_DEPENDENCY_CACHE_DIR" "$REPO_PATH/kaseki-agent.sh" 2>/dev/null && score=$((score + 2))
175
+
176
+ # Check for build cache in Dockerfile (1 point)
177
+ grep -q "cache" "$REPO_PATH/Dockerfile" 2>/dev/null && score=$((score + 1))
178
+
179
+ # Check for multi-stage build (1 point)
180
+ grep -c "FROM" "$REPO_PATH/Dockerfile" 2>/dev/null | grep -q "[2-9]" && score=$((score + 1))
181
+
182
+ PERFORMANCE_SCORE="$score"
183
+ }
184
+
185
+ evaluate_maintenance() {
186
+ local score=0
187
+
188
+ # Check for SECURITY.md (1 point)
189
+ [ -f "$REPO_PATH/SECURITY.md" ] && score=$((score + 1))
190
+
191
+ # Check for LICENSE (1 point)
192
+ [ -f "$REPO_PATH/LICENSE" ] || [ -f "$REPO_PATH/LICENSE.md" ] && score=$((score + 1))
193
+
194
+ # Check for version consistency (1 point)
195
+ grep -q '"version"' "$REPO_PATH/package.json" 2>/dev/null && score=$((score + 1))
196
+
197
+ MAINTENANCE_SCORE="$score"
198
+ }
199
+
200
+ # Run all evaluations
201
+ evaluate_setup
202
+ evaluate_testing
203
+ evaluate_cicd
204
+ evaluate_docs
205
+ evaluate_governance
206
+ evaluate_security
207
+ evaluate_operability
208
+ evaluate_performance
209
+ evaluate_maintenance
210
+
211
+ # Calculate total score
212
+ TOTAL_SCORE=$((
213
+ SETUP_SCORE +
214
+ TESTING_SCORE +
215
+ CICD_SCORE +
216
+ DOCS_SCORE +
217
+ GOVERNANCE_SCORE +
218
+ SECURITY_SCORE +
219
+ OPERABILITY_SCORE +
220
+ PERFORMANCE_SCORE +
221
+ MAINTENANCE_SCORE
222
+ ))
223
+
224
+ # Maximum possible score
225
+ MAX_SCORE=50 # Calculated from all categories above
226
+
227
+ # Percentage
228
+ PERCENTAGE=$((TOTAL_SCORE * 100 / MAX_SCORE))
229
+
230
+ # Output JSON
231
+ mkdir -p "$(dirname "$OUTPUT_FILE")"
232
+ cat > "$OUTPUT_FILE" <<EOF
233
+ {
234
+ "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
235
+ "total_score": $TOTAL_SCORE,
236
+ "max_score": $MAX_SCORE,
237
+ "percentage": $PERCENTAGE,
238
+ "rating": "$(
239
+ if [ $TOTAL_SCORE -ge 45 ]; then
240
+ echo "Exemplary"
241
+ elif [ $TOTAL_SCORE -ge 40 ]; then
242
+ echo "Mature"
243
+ elif [ $TOTAL_SCORE -ge 30 ]; then
244
+ echo "Capable"
245
+ else
246
+ echo "Developing"
247
+ fi
248
+ )",
249
+ "categories": {
250
+ "setup_and_installation": {
251
+ "score": $SETUP_SCORE,
252
+ "max": 7
253
+ },
254
+ "testing_and_quality": {
255
+ "score": $TESTING_SCORE,
256
+ "max": 5
257
+ },
258
+ "cicd_and_automation": {
259
+ "score": $CICD_SCORE,
260
+ "max": 5
261
+ },
262
+ "documentation": {
263
+ "score": $DOCS_SCORE,
264
+ "max": 5
265
+ },
266
+ "governance": {
267
+ "score": $GOVERNANCE_SCORE,
268
+ "max": 3
269
+ },
270
+ "security": {
271
+ "score": $SECURITY_SCORE,
272
+ "max": 4
273
+ },
274
+ "operability": {
275
+ "score": $OPERABILITY_SCORE,
276
+ "max": 4
277
+ },
278
+ "performance_and_efficiency": {
279
+ "score": $PERFORMANCE_SCORE,
280
+ "max": 4
281
+ },
282
+ "maintenance_and_sustainability": {
283
+ "score": $MAINTENANCE_SCORE,
284
+ "max": 3
285
+ }
286
+ }
287
+ }
288
+ EOF
289
+
290
+ # Output to stdout as well
291
+ cat "$OUTPUT_FILE"
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env bash
2
+ # kaseki-performance-metrics.sh
3
+ # Analyzes stage timings and generates performance benchmarks
4
+ #
5
+ # Reads the stage-timings.tsv file and generates a performance report
6
+ # in JSON format with summary statistics and percentiles
7
+ #
8
+ # Usage: kaseki-performance-metrics.sh <stage_timings_tsv> [output_json]
9
+ # Default output: /results/performance-metrics.json
10
+
11
+ set -euo pipefail
12
+
13
+ STAGE_TIMINGS_FILE="${1:-/results/stage-timings.tsv}"
14
+ OUTPUT_FILE="${2:-/results/performance-metrics.json}"
15
+
16
+ if [ ! -f "$STAGE_TIMINGS_FILE" ]; then
17
+ echo '{"error": "stage-timings.tsv not found"}' > "$OUTPUT_FILE"
18
+ exit 1
19
+ fi
20
+
21
+ # Parse stage timings and calculate metrics
22
+ TOTAL_TIME=0
23
+ STAGE_COUNT=0
24
+ declare -a DURATIONS
25
+
26
+ while IFS=$'\t' read -r stage _exit_code duration _detail; do
27
+ [ -z "$stage" ] && continue
28
+ [ -z "$duration" ] && continue
29
+
30
+ DURATIONS+=("$duration")
31
+ TOTAL_TIME=$((TOTAL_TIME + duration))
32
+ STAGE_COUNT=$((STAGE_COUNT + 1))
33
+ done < "$STAGE_TIMINGS_FILE"
34
+
35
+ # Calculate statistics
36
+ if [ "$STAGE_COUNT" -eq 0 ]; then
37
+ cat > "$OUTPUT_FILE" <<EOF
38
+ {
39
+ "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
40
+ "total_stages": 0,
41
+ "total_duration_seconds": 0,
42
+ "average_stage_duration_seconds": 0,
43
+ "status": "no_data"
44
+ }
45
+ EOF
46
+ exit 0
47
+ fi
48
+
49
+ AVG_DURATION=$((TOTAL_TIME / STAGE_COUNT))
50
+
51
+ # Sort durations for percentile calculation
52
+ mapfile -t sorted_durations < <(printf '%s\n' "${DURATIONS[@]}" | sort -n)
53
+
54
+ # Calculate percentiles
55
+ P50_INDEX=$((STAGE_COUNT * 50 / 100))
56
+ P90_INDEX=$((STAGE_COUNT * 90 / 100))
57
+ P95_INDEX=$((STAGE_COUNT * 95 / 100))
58
+ P99_INDEX=$((STAGE_COUNT * 99 / 100))
59
+
60
+ # Handle edge cases
61
+ [ $P50_INDEX -eq 0 ] && P50_INDEX=0
62
+ [ $P90_INDEX -ge $STAGE_COUNT ] && P90_INDEX=$((STAGE_COUNT - 1))
63
+ [ $P95_INDEX -ge $STAGE_COUNT ] && P95_INDEX=$((STAGE_COUNT - 1))
64
+ [ $P99_INDEX -ge $STAGE_COUNT ] && P99_INDEX=$((STAGE_COUNT - 1))
65
+
66
+ P50="${sorted_durations[$P50_INDEX]:-0}"
67
+ P90="${sorted_durations[$P90_INDEX]:-0}"
68
+ P95="${sorted_durations[$P95_INDEX]:-0}"
69
+ P99="${sorted_durations[$P99_INDEX]:-0}"
70
+
71
+ MIN_DURATION="${sorted_durations[0]:-0}"
72
+ MAX_DURATION="${sorted_durations[$((STAGE_COUNT - 1))]:-0}"
73
+
74
+ # Determine performance rating
75
+ if [ "$TOTAL_TIME" -lt 300 ]; then
76
+ RATING="Excellent"
77
+ elif [ "$TOTAL_TIME" -lt 600 ]; then
78
+ RATING="Good"
79
+ elif [ "$TOTAL_TIME" -lt 1200 ]; then
80
+ RATING="Acceptable"
81
+ else
82
+ RATING="Slow"
83
+ fi
84
+
85
+ # Generate output JSON
86
+ mkdir -p "$(dirname "$OUTPUT_FILE")"
87
+ cat > "$OUTPUT_FILE" <<EOF
88
+ {
89
+ "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
90
+ "summary": {
91
+ "total_stages": $STAGE_COUNT,
92
+ "total_duration_seconds": $TOTAL_TIME,
93
+ "average_stage_duration_seconds": $AVG_DURATION,
94
+ "min_stage_duration_seconds": $MIN_DURATION,
95
+ "max_stage_duration_seconds": $MAX_DURATION,
96
+ "rating": "$RATING"
97
+ },
98
+ "percentiles": {
99
+ "p50_seconds": $P50,
100
+ "p90_seconds": $P90,
101
+ "p95_seconds": $P95,
102
+ "p99_seconds": $P99
103
+ },
104
+ "recommendations": [
105
+ $(
106
+ if [ "$MAX_DURATION" -gt 300 ]; then
107
+ echo '"Consider optimizing stages taking >5 minutes",'
108
+ fi
109
+ if [ "$P99" -gt 60 ]; then
110
+ echo '"Some stages exceed 1 minute; review for parallelization",'
111
+ fi
112
+ if [ "$AVG_DURATION" -gt 30 ]; then
113
+ echo '"Average stage duration is high; profile for bottlenecks",'
114
+ fi
115
+ echo '"Good performance baseline"'
116
+ )
117
+ ]
118
+ }
119
+ EOF
120
+
121
+ # Print to stdout as well
122
+ cat "$OUTPUT_FILE"
@@ -0,0 +1,270 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ mode="${1:-run}"
5
+ output_format="text" # text or json
6
+ guide_mode=0 # 0 or 1
7
+
8
+ # Parse flags
9
+ while [[ $# -gt 0 ]]; do
10
+ case "$1" in
11
+ --json)
12
+ output_format="json"
13
+ shift
14
+ ;;
15
+ --guide)
16
+ guide_mode=1
17
+ shift
18
+ ;;
19
+ run|doctor)
20
+ mode="$1"
21
+ shift
22
+ ;;
23
+ *)
24
+ printf 'Error: unknown flag or mode: %s\n' "$1" >&2
25
+ exit 2
26
+ ;;
27
+ esac
28
+ done
29
+
30
+ required_bins=(docker)
31
+ optional_bins=()
32
+ case "$mode" in
33
+ run)
34
+ optional_bins=(curl wget sshpass git node npm)
35
+ ;;
36
+ doctor)
37
+ optional_bins=(curl wget sshpass git node npm)
38
+ ;;
39
+ *)
40
+ printf 'Error: unknown preflight mode: %s\n' "$mode" >&2
41
+ exit 2
42
+ ;;
43
+ esac
44
+
45
+ missing_required=()
46
+ missing_optional=()
47
+
48
+ for bin in "${required_bins[@]}"; do
49
+ if ! command -v "$bin" >/dev/null 2>&1; then
50
+ missing_required+=("$bin")
51
+ fi
52
+ done
53
+
54
+ for bin in "${optional_bins[@]}"; do
55
+ if ! command -v "$bin" >/dev/null 2>&1; then
56
+ missing_optional+=("$bin")
57
+ fi
58
+ done
59
+
60
+ # Detect OS for install suggestions
61
+ detect_os() {
62
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
63
+ if [ -f /etc/os-release ]; then
64
+ # shellcheck disable=SC1091
65
+ . /etc/os-release
66
+ case "$ID" in
67
+ debian|ubuntu|raspbian)
68
+ echo "debian"
69
+ ;;
70
+ fedora|centos|rhel)
71
+ echo "fedora"
72
+ ;;
73
+ arch|manjaro)
74
+ echo "arch"
75
+ ;;
76
+ *)
77
+ echo "linux"
78
+ ;;
79
+ esac
80
+ else
81
+ echo "linux"
82
+ fi
83
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
84
+ echo "macos"
85
+ else
86
+ echo "unknown"
87
+ fi
88
+ }
89
+
90
+ # Get install command for detected OS
91
+ get_install_command() {
92
+ local bin="$1"
93
+ local detected_os
94
+ detected_os="$(detect_os)"
95
+
96
+ case "$detected_os" in
97
+ debian)
98
+ case "$bin" in
99
+ docker) echo "sudo apt update && sudo apt install -y docker.io" ;;
100
+ git) echo "sudo apt install -y git" ;;
101
+ curl) echo "sudo apt install -y curl" ;;
102
+ wget) echo "sudo apt install -y wget" ;;
103
+ node|npm) echo "curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash - && sudo apt install -y nodejs" ;;
104
+ sshpass) echo "sudo apt install -y sshpass" ;;
105
+ *) echo "sudo apt install -y $bin" ;;
106
+ esac
107
+ ;;
108
+ fedora)
109
+ case "$bin" in
110
+ docker) echo "sudo dnf install -y docker" ;;
111
+ git) echo "sudo dnf install -y git" ;;
112
+ curl) echo "sudo dnf install -y curl" ;;
113
+ wget) echo "sudo dnf install -y wget" ;;
114
+ node|npm) echo "curl -fsSL https://rpm.nodesource.com/setup_24.x | sudo bash - && sudo dnf install -y nodejs" ;;
115
+ sshpass) echo "sudo dnf install -y sshpass" ;;
116
+ *) echo "sudo dnf install -y $bin" ;;
117
+ esac
118
+ ;;
119
+ arch)
120
+ case "$bin" in
121
+ docker) echo "sudo pacman -S --needed docker" ;;
122
+ git) echo "sudo pacman -S --needed git" ;;
123
+ curl) echo "sudo pacman -S --needed curl" ;;
124
+ wget) echo "sudo pacman -S --needed wget" ;;
125
+ node|npm) echo "sudo pacman -S --needed nodejs npm" ;;
126
+ sshpass) echo "sudo pacman -S --needed sshpass" ;;
127
+ *) echo "sudo pacman -S --needed $bin" ;;
128
+ esac
129
+ ;;
130
+ macos)
131
+ case "$bin" in
132
+ docker) echo "brew install --cask docker" ;;
133
+ git) echo "brew install git" ;;
134
+ curl) echo "brew install curl" ;;
135
+ wget) echo "brew install wget" ;;
136
+ node|npm) echo "brew install node" ;;
137
+ sshpass) echo "brew install sshpass" ;;
138
+ *) echo "brew install $bin" ;;
139
+ esac
140
+ ;;
141
+ *)
142
+ echo "Please install $bin manually"
143
+ ;;
144
+ esac
145
+ }
146
+
147
+ # Output helpers
148
+ output_text_mode() {
149
+ if [ "${#missing_required[@]}" -gt 0 ]; then
150
+ printf 'Error: missing required host dependencies: %s\n' "$(IFS=', '; echo "${missing_required[*]}")" >&2
151
+ printf 'Install them, then re-run ./run-kaseki.sh.\n' >&2
152
+ return 1
153
+ fi
154
+
155
+ printf 'Preflight required dependencies: ok (%s)\n' "$(IFS=', '; echo "${required_bins[*]}")"
156
+ if [ "${#missing_optional[@]}" -eq 0 ]; then
157
+ printf 'Preflight optional dependencies: ok (%s)\n' "$(IFS=', '; echo "${optional_bins[*]}")"
158
+ else
159
+ printf 'Preflight optional dependencies: missing (%s)\n' "$(IFS=', '; echo "${missing_optional[*]}")"
160
+ fi
161
+
162
+ return 0
163
+ }
164
+
165
+ output_json_mode() {
166
+ local status="ready"
167
+ [ "${#missing_required[@]}" -gt 0 ] && status="failed"
168
+
169
+ # Build JSON output
170
+ cat <<EOF
171
+ {
172
+ "status": "$status",
173
+ "required_ok": $([[ ${#missing_required[@]} -eq 0 ]] && echo "true" || echo "false"),
174
+ "optional_ok": $([[ ${#missing_optional[@]} -eq 0 ]] && echo "true" || echo "false"),
175
+ "required_bins": $(printf '%s\n' "${required_bins[@]}" | jq -sR -c 'split("\n")[:-1]'),
176
+ "optional_bins": $(printf '%s\n' "${optional_bins[@]}" | jq -sR -c 'split("\n")[:-1]'),
177
+ "missing_required": $(printf '%s\n' "${missing_required[@]}" | jq -sR -c 'split("\n")[:-1]'),
178
+ "missing_optional": $(printf '%s\n' "${missing_optional[@]}" | jq -sR -c 'split("\n")[:-1]'),
179
+ "detected_os": "$(detect_os)"
180
+ }
181
+ EOF
182
+
183
+ [ "${#missing_required[@]}" -gt 0 ] && return 1 || return 0
184
+ }
185
+
186
+ output_guide_mode() {
187
+ echo "╔════════════════════════════════════════════════════════════╗"
188
+ echo "║ Kaseki Agent Preflight Guide ║"
189
+ echo "╚════════════════════════════════════════════════════════════╝"
190
+ echo ""
191
+
192
+ local detected_os
193
+ detected_os="$(detect_os)"
194
+ echo "System Information:"
195
+ echo " OS: $detected_os"
196
+ echo " Shell: $SHELL"
197
+ echo ""
198
+
199
+ # Check required dependencies
200
+ echo "Required Dependencies:"
201
+ for bin in "${required_bins[@]}"; do
202
+ if command -v "$bin" >/dev/null 2>&1; then
203
+ echo " ✓ $bin"
204
+ else
205
+ echo " ✗ $bin (MISSING)"
206
+ local install_cmd
207
+ install_cmd=$(get_install_command "$bin")
208
+ echo " Install: $install_cmd"
209
+ fi
210
+ done
211
+ echo ""
212
+
213
+ # Check optional dependencies
214
+ echo "Optional Dependencies:"
215
+ for bin in "${optional_bins[@]}"; do
216
+ if command -v "$bin" >/dev/null 2>&1; then
217
+ echo " ✓ $bin"
218
+ else
219
+ echo " ○ $bin (optional, not found)"
220
+ local install_cmd
221
+ install_cmd=$(get_install_command "$bin")
222
+ echo " Install: $install_cmd"
223
+ fi
224
+ done
225
+ echo ""
226
+
227
+ # Summary and next steps
228
+ if [ "${#missing_required[@]}" -gt 0 ]; then
229
+ echo "⚠ Action Required:"
230
+ echo " Install missing required dependencies:"
231
+ for bin in "${missing_required[@]}"; do
232
+ local install_cmd
233
+ install_cmd=$(get_install_command "$bin")
234
+ echo " $install_cmd"
235
+ done
236
+ echo ""
237
+ echo " After installing, run: ./run-kaseki.sh --doctor"
238
+ return 1
239
+ else
240
+ echo "✓ All required dependencies are installed!"
241
+ if [ "${#missing_optional[@]}" -gt 0 ]; then
242
+ echo ""
243
+ echo "⚠ Note: Some optional dependencies are missing:"
244
+ for bin in "${missing_optional[@]}"; do
245
+ echo " - $bin"
246
+ done
247
+ echo " These are optional but recommended for full functionality."
248
+ fi
249
+ return 0
250
+ fi
251
+ }
252
+
253
+ # Route to appropriate output mode
254
+ case "$output_format" in
255
+ json)
256
+ output_json_mode
257
+ ;;
258
+ text)
259
+ if [ "$guide_mode" -eq 1 ]; then
260
+ output_guide_mode
261
+ else
262
+ output_text_mode
263
+ fi
264
+ ;;
265
+ *)
266
+ printf 'Error: unknown output format: %s\n' "$output_format" >&2
267
+ exit 2
268
+ ;;
269
+ esac
270
+