@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,145 @@
1
+ /**
2
+ * Config Command
3
+ * Manage configuration
4
+ */
5
+
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import os from 'os';
9
+ import { BaseCommand } from '../BaseCommand';
10
+ import { createLogger } from '../../logger';
11
+
12
+ const logger = createLogger('config-cmd');
13
+
14
+ export class ConfigCommand extends BaseCommand {
15
+ async execute(args: string[]): Promise<number> {
16
+ try {
17
+ const { positional, flags } = this.parseArgs(args);
18
+ const subcommand = positional[0];
19
+ const key = positional[1];
20
+ const value = positional.slice(2).join(' ');
21
+
22
+ await this.configManager.load();
23
+
24
+ switch (subcommand) {
25
+ case 'get': {
26
+ if (!key) {
27
+ console.error('Usage: kaseki-agent config get <KEY>');
28
+ return 1;
29
+ }
30
+ const result = this.configManager.get(key);
31
+ if (result === undefined) {
32
+ console.log('(not set)');
33
+ } else {
34
+ console.log(result);
35
+ }
36
+ return 0;
37
+ }
38
+
39
+ case 'set': {
40
+ if (!key || !value) {
41
+ console.error('Usage: kaseki-agent config set <KEY> <VALUE>');
42
+ return 1;
43
+ }
44
+
45
+ const useGlobal = flags.has('global');
46
+ const configPath = useGlobal
47
+ ? path.join(os.homedir(), '.kaseki', 'config.json')
48
+ : 'kaseki-agent.json';
49
+
50
+ // Ensure directory exists
51
+ const configDir = path.dirname(configPath);
52
+ await fs.mkdir(configDir, { recursive: true });
53
+
54
+ // Read existing config
55
+ let config = {};
56
+ try {
57
+ const content = await fs.readFile(configPath, 'utf-8');
58
+ config = JSON.parse(content);
59
+ } catch {
60
+ // File doesn't exist, that's fine
61
+ }
62
+
63
+ // Set value using dot notation
64
+ this.setNestedValue(config, key, value);
65
+
66
+ // Write back
67
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
68
+
69
+ console.log(`✓ Set ${key} = ${value}`);
70
+ console.log(` Config file: ${configPath}`);
71
+ return 0;
72
+ }
73
+
74
+ case 'show': {
75
+ const useGlobal = flags.has('global');
76
+ const configPath = useGlobal
77
+ ? path.join(os.homedir(), '.kaseki', 'config.json')
78
+ : 'kaseki-agent.json';
79
+
80
+ try {
81
+ const content = await fs.readFile(configPath, 'utf-8');
82
+ const config = JSON.parse(content);
83
+ console.log(`Configuration from: ${configPath}\n`);
84
+ console.log(JSON.stringify(config, null, 2));
85
+ } catch (error) {
86
+ console.log(`No configuration found at ${configPath}`);
87
+ logger.debug(`Failed to read config: ${error}`);
88
+ }
89
+ return 0;
90
+ }
91
+
92
+ case 'locations': {
93
+ console.log('Configuration locations (in precedence order):\n');
94
+ console.log('1. CLI flags (--key=value)');
95
+ console.log('2. kaseki-agent.json (project-local)');
96
+ console.log('3. ~/.kaseki/config.json (user-global)');
97
+ console.log('4. Environment variables (KASEKI_*, OPENROUTER_*)');
98
+ console.log('5. Built-in defaults\n');
99
+
100
+ console.log('Examples:');
101
+ console.log(' kaseki-agent config set agent.timeout_seconds 1800 --global');
102
+ console.log(' kaseki-agent config get agent.model');
103
+ console.log(' kaseki-agent config show --global');
104
+ return 0;
105
+ }
106
+
107
+ default:
108
+ console.error('Unknown subcommand: ' + subcommand);
109
+ console.error('\nUsage:');
110
+ console.error(' kaseki-agent config get <KEY>');
111
+ console.error(' kaseki-agent config set <KEY> <VALUE> [--global]');
112
+ console.error(' kaseki-agent config show [--global]');
113
+ console.error(' kaseki-agent config locations');
114
+ return 1;
115
+ }
116
+ } catch (error) {
117
+ logger.error(`Config command failed: ${error}`);
118
+ return 1;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Set nested object value using dot notation
124
+ */
125
+ private setNestedValue(obj: any, path: string, value: string): void {
126
+ const keys = path.split('.');
127
+ let current = obj;
128
+
129
+ for (let i = 0; i < keys.length - 1; i++) {
130
+ const key = keys[i];
131
+ if (!current[key] || typeof current[key] !== 'object') {
132
+ current[key] = {};
133
+ }
134
+ current = current[key];
135
+ }
136
+
137
+ const lastKey = keys[keys.length - 1];
138
+ // Try to parse as JSON if possible
139
+ try {
140
+ current[lastKey] = JSON.parse(value);
141
+ } catch {
142
+ current[lastKey] = value;
143
+ }
144
+ }
145
+ }
@@ -0,0 +1,329 @@
1
+ /**
2
+ * Doctor Command
3
+ * Health checks and dependency validation
4
+ */
5
+
6
+ import { execSync } from 'child_process';
7
+ import { BaseCommand } from '../BaseCommand';
8
+ import { SecretsManager } from '../../secrets/SecretsManager';
9
+ import { createLogger } from '../../logger';
10
+
11
+ const logger = createLogger('doctor-cmd');
12
+
13
+ interface Check {
14
+ name: string;
15
+ status: 'pass' | 'warn' | 'fail';
16
+ message: string;
17
+ fixable?: boolean;
18
+ }
19
+
20
+ export class DoctorCommand extends BaseCommand {
21
+ async execute(args: string[]): Promise<number> {
22
+ try {
23
+ const { flags } = this.parseArgs(args);
24
+ const isJson = flags.has('json');
25
+ const _isFix = flags.has('fix');
26
+ // Note: --verbose is parsed but not yet used in non-verbose output
27
+
28
+ console.log('🏥 Kaseki Agent Health Check\n');
29
+
30
+ // Load configuration
31
+ await this.configManager.load();
32
+
33
+ // Run all checks
34
+ const checks: Check[] = [
35
+ await this.checkDocker(),
36
+ await this.checkNodejs(),
37
+ await this.checkNpm(),
38
+ await this.checkGit(),
39
+ await this.checkAPIKey(),
40
+ await this.checkDockkerImage(),
41
+ await this.checkDiskSpace(),
42
+ ];
43
+
44
+ // Output results
45
+ if (isJson) {
46
+ console.log(JSON.stringify(checks, null, 2));
47
+ } else {
48
+ this.printResults(checks);
49
+ }
50
+
51
+ // Attempt fixes if requested
52
+ if (_isFix) {
53
+ console.log('\n🔧 Attempting auto-remediation...\n');
54
+ for (const check of checks) {
55
+ if (check.status !== 'pass' && check.fixable) {
56
+ await this.attemptFix(check);
57
+ }
58
+ }
59
+
60
+ // Re-run checks after fixes
61
+ console.log('\n🏥 Running checks again...\n');
62
+ const rechecks: Check[] = [
63
+ await this.checkDocker(),
64
+ await this.checkDockkerImage(),
65
+ ];
66
+ this.printResults(rechecks);
67
+ }
68
+
69
+ // Return exit code based on failures
70
+ const failures = checks.filter((c) => c.status === 'fail').length;
71
+ return failures > 0 ? 1 : 0;
72
+ } catch (error) {
73
+ logger.error(`Doctor check failed: ${error}`);
74
+ return 1;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Check Docker installation and daemon
80
+ */
81
+ private async checkDocker(): Promise<Check> {
82
+ try {
83
+ execSync('docker --version', { stdio: 'ignore' });
84
+ execSync('docker ps', { stdio: 'ignore' });
85
+ return {
86
+ name: 'Docker',
87
+ status: 'pass',
88
+ message: '✓ Docker installed and daemon running',
89
+ };
90
+ } catch {
91
+ return {
92
+ name: 'Docker',
93
+ status: 'fail',
94
+ message: '❌ Docker not installed or daemon not running',
95
+ fixable: true,
96
+ };
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Check Node.js version
102
+ */
103
+ private async checkNodejs(): Promise<Check> {
104
+ try {
105
+ const version = execSync('node --version', { encoding: 'utf-8' }).trim();
106
+ const major = parseInt(version.replace('v', '').split('.')[0], 10);
107
+ if (major >= 24) {
108
+ return {
109
+ name: 'Node.js',
110
+ status: 'pass',
111
+ message: `✓ Node.js ${version}`,
112
+ };
113
+ } else {
114
+ return {
115
+ name: 'Node.js',
116
+ status: 'fail',
117
+ message: `❌ Node.js v24+ required, found ${version}`,
118
+ };
119
+ }
120
+ } catch {
121
+ return {
122
+ name: 'Node.js',
123
+ status: 'fail',
124
+ message: '❌ Node.js not installed',
125
+ };
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Check npm installation
131
+ */
132
+ private async checkNpm(): Promise<Check> {
133
+ try {
134
+ const version = execSync('npm --version', { encoding: 'utf-8' }).trim();
135
+ return {
136
+ name: 'npm',
137
+ status: 'pass',
138
+ message: `✓ npm ${version}`,
139
+ };
140
+ } catch {
141
+ return {
142
+ name: 'npm',
143
+ status: 'fail',
144
+ message: '❌ npm not installed',
145
+ };
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Check git installation
151
+ */
152
+ private async checkGit(): Promise<Check> {
153
+ try {
154
+ const version = execSync('git --version', { encoding: 'utf-8' }).trim();
155
+ return {
156
+ name: 'git',
157
+ status: 'pass',
158
+ message: `✓ ${version}`,
159
+ };
160
+ } catch {
161
+ return {
162
+ name: 'git',
163
+ status: 'fail',
164
+ message: '❌ git not installed',
165
+ };
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Check API key accessibility
171
+ */
172
+ private async checkAPIKey(): Promise<Check> {
173
+ try {
174
+ const secretsManager = new SecretsManager();
175
+ const apiKeyFile = this.configManager.get('auth.openrouter_api_key_file', '');
176
+
177
+ if (!apiKeyFile) {
178
+ return {
179
+ name: 'OpenRouter API Key',
180
+ status: 'warn',
181
+ message: '⚠️ API key file path not configured',
182
+ };
183
+ }
184
+
185
+ const key = await secretsManager.retrieve('openrouter_api_key');
186
+ if (key) {
187
+ return {
188
+ name: 'OpenRouter API Key',
189
+ status: 'pass',
190
+ message: '✓ API key found and readable',
191
+ };
192
+ } else {
193
+ return {
194
+ name: 'OpenRouter API Key',
195
+ status: 'fail',
196
+ message: '❌ API key not found. Run: kaseki-agent setup',
197
+ };
198
+ }
199
+ } catch (error) {
200
+ return {
201
+ name: 'OpenRouter API Key',
202
+ status: 'fail',
203
+ message: `❌ API key check failed: ${error}`,
204
+ };
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Check Docker image availability
210
+ */
211
+ private async checkDockkerImage(): Promise<Check> {
212
+ try {
213
+ const image = this.configManager.get('docker.image', '');
214
+
215
+ if (!image) {
216
+ return {
217
+ name: 'Docker Image',
218
+ status: 'fail',
219
+ message: '❌ Docker image not configured',
220
+ };
221
+ }
222
+
223
+ // Check if image exists locally
224
+ try {
225
+ execSync(`docker inspect ${image} > /dev/null 2>&1`, { stdio: 'ignore' });
226
+ return {
227
+ name: 'Docker Image',
228
+ status: 'pass',
229
+ message: `✓ Docker image available: ${image}`,
230
+ };
231
+ } catch {
232
+ return {
233
+ name: 'Docker Image',
234
+ status: 'warn',
235
+ message: `⚠️ Docker image not found locally: ${image}. Will auto-pull on first run.`,
236
+ fixable: true,
237
+ };
238
+ }
239
+ } catch (error) {
240
+ return {
241
+ name: 'Docker Image',
242
+ status: 'fail',
243
+ message: `❌ Docker image check failed: ${error}`,
244
+ };
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Check disk space
250
+ */
251
+ private async checkDiskSpace(): Promise<Check> {
252
+ try {
253
+ const kasekiRoot = this.configManager.get('directories.root', '/agents');
254
+ const result = execSync(`df -B1 ${kasekiRoot} | awk 'NR==2 {print $4}'`, {
255
+ encoding: 'utf-8',
256
+ }).trim();
257
+
258
+ const availableBytes = parseInt(result, 10);
259
+ const availableGB = availableBytes / (1024 ** 3);
260
+
261
+ if (availableGB > 10) {
262
+ return {
263
+ name: 'Disk Space',
264
+ status: 'pass',
265
+ message: `✓ Sufficient disk space available (${availableGB.toFixed(1)} GB)`,
266
+ };
267
+ } else if (availableGB > 1) {
268
+ return {
269
+ name: 'Disk Space',
270
+ status: 'warn',
271
+ message: `⚠️ Limited disk space: ${availableGB.toFixed(1)} GB available`,
272
+ };
273
+ } else {
274
+ return {
275
+ name: 'Disk Space',
276
+ status: 'fail',
277
+ message: `❌ Insufficient disk space: ${availableGB.toFixed(2)} GB available`,
278
+ };
279
+ }
280
+ } catch {
281
+ return {
282
+ name: 'Disk Space',
283
+ status: 'warn',
284
+ message: '⚠️ Could not determine disk space',
285
+ };
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Print check results in human-readable format
291
+ */
292
+ private printResults(checks: Check[]): void {
293
+ for (const check of checks) {
294
+ console.log(`${check.message}`);
295
+ }
296
+
297
+ const summary = {
298
+ pass: checks.filter((c) => c.status === 'pass').length,
299
+ warn: checks.filter((c) => c.status === 'warn').length,
300
+ fail: checks.filter((c) => c.status === 'fail').length,
301
+ };
302
+
303
+ console.log(
304
+ `\nSummary: ${summary.pass} passed, ${summary.warn} warnings, ${summary.fail} failed`
305
+ );
306
+
307
+ if (summary.fail > 0) {
308
+ console.log('Fix issues with: kaseki-agent doctor --fix');
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Attempt to fix identified issues
314
+ */
315
+ private async attemptFix(check: Check): Promise<void> {
316
+ if (check.name === 'Docker') {
317
+ console.log('Install Docker from: https://docs.docker.com/install/');
318
+ } else if (check.name === 'Docker Image') {
319
+ try {
320
+ console.log(`Pulling Docker image: ${this.configManager.get('docker.image')}...`);
321
+ const image = this.configManager.get('docker.image', '');
322
+ execSync(`docker pull ${image}`, { stdio: 'inherit' });
323
+ console.log('✓ Image pulled successfully');
324
+ } catch {
325
+ console.log('❌ Failed to pull Docker image');
326
+ }
327
+ }
328
+ }
329
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * List Command
3
+ * List all kaseki instances
4
+ */
5
+
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import { BaseCommand } from '../BaseCommand';
9
+ import { createLogger } from '../../logger';
10
+
11
+ const logger = createLogger('list-cmd');
12
+
13
+ interface InstanceSummary {
14
+ id: string;
15
+ status: string;
16
+ createdAt: string;
17
+ duration?: number;
18
+ exitCode?: number;
19
+ }
20
+
21
+ export class ListCommand extends BaseCommand {
22
+ async execute(args: string[]): Promise<number> {
23
+ try {
24
+ const { flags } = this.parseArgs(args);
25
+ const statusFilter = flags.get('status') as string | undefined;
26
+
27
+ console.log('📋 Kaseki Instances\n');
28
+
29
+ // Load configuration
30
+ await this.configManager.load();
31
+
32
+ const kasekiRoot = this.configManager.get('directories.root');
33
+ const resultsDir = path.join(kasekiRoot, 'kaseki-results');
34
+
35
+ // Read instances
36
+ const instances: InstanceSummary[] = [];
37
+
38
+ try {
39
+ const entries = await fs.readdir(resultsDir, { withFileTypes: true });
40
+
41
+ for (const entry of entries) {
42
+ if (entry.isDirectory() && entry.name.startsWith('kaseki-')) {
43
+ try {
44
+ const metadataPath = path.join(resultsDir, entry.name, 'metadata.json');
45
+ const content = await fs.readFile(metadataPath, 'utf-8');
46
+ const metadata = JSON.parse(content);
47
+
48
+ // Apply status filter
49
+ if (statusFilter && metadata.status !== statusFilter) {
50
+ continue;
51
+ }
52
+
53
+ instances.push({
54
+ id: metadata.id,
55
+ status: metadata.status,
56
+ createdAt: metadata.createdAt,
57
+ duration: metadata.stages?.['agent-run']?.duration,
58
+ exitCode: metadata.exitCode,
59
+ });
60
+ } catch (error) {
61
+ logger.debug(`Failed to read metadata for ${entry.name}: ${error}`);
62
+ }
63
+ }
64
+ }
65
+ } catch (error) {
66
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
67
+ logger.error(`Failed to read results directory: ${error}`);
68
+ return 1;
69
+ }
70
+ // Directory doesn't exist yet
71
+ }
72
+
73
+ // Sort by creation date (newest first)
74
+ instances.sort((a, b) =>
75
+ new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
76
+ );
77
+
78
+ // Display results
79
+ if (instances.length === 0) {
80
+ console.log('No instances found.');
81
+ return 0;
82
+ }
83
+
84
+ // Print as table
85
+ console.log('ID | Status | Created | Duration (s)');
86
+ console.log('----------------|-----------|------------------------|---------------');
87
+
88
+ for (const inst of instances) {
89
+ const id = inst.id.padEnd(15);
90
+ const status = inst.status.padEnd(9);
91
+ const created = new Date(inst.createdAt).toISOString().substring(0, 19);
92
+ const duration = inst.duration ? inst.duration.toFixed(1) : '-';
93
+
94
+ console.log(`${id} | ${status} | ${created} | ${duration}`);
95
+ }
96
+
97
+ console.log(`\nTotal: ${instances.length} instance(s)`);
98
+
99
+ return 0;
100
+ } catch (error) {
101
+ logger.error(`List failed: ${error}`);
102
+ return 1;
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Report Command
3
+ * Generate report for completed instance
4
+ */
5
+
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import { BaseCommand } from '../BaseCommand';
9
+ import { createLogger } from '../../logger';
10
+
11
+ const logger = createLogger('report-cmd');
12
+
13
+ export class ReportCommand extends BaseCommand {
14
+ async execute(args: string[]): Promise<number> {
15
+ try {
16
+ const { positional } = this.parseArgs(args);
17
+ const instanceId = positional[0];
18
+ void args; // TODO: use remaining args when implemented
19
+
20
+ if (!instanceId) {
21
+ console.error('Usage: kaseki-agent report <INSTANCE_ID>');
22
+ return 1;
23
+ }
24
+
25
+ console.log(`📊 Report: ${instanceId}\n`);
26
+
27
+ // Load configuration
28
+ await this.configManager.load();
29
+
30
+ const kasekiRoot = this.configManager.get('directories.root');
31
+ const resultsDir = path.join(kasekiRoot, 'kaseki-results', instanceId);
32
+
33
+ // Read metadata
34
+ try {
35
+ const metadataPath = path.join(resultsDir, 'metadata.json');
36
+ const content = await fs.readFile(metadataPath, 'utf-8');
37
+ const metadata = JSON.parse(content);
38
+
39
+ // Display metadata
40
+ console.log('Instance Information');
41
+ console.log('-------------------');
42
+ console.log(`ID: ${metadata.id}`);
43
+ console.log(`Status: ${metadata.status}`);
44
+ console.log(`Created: ${new Date(metadata.createdAt).toLocaleString()}`);
45
+
46
+ if (metadata.completedAt) {
47
+ console.log(`Completed: ${new Date(metadata.completedAt).toLocaleString()}`);
48
+ }
49
+
50
+ if (metadata.repoUrl) {
51
+ console.log(`Repo: ${metadata.repoUrl}`);
52
+ }
53
+
54
+ if (metadata.gitRef) {
55
+ console.log(`Ref: ${metadata.gitRef}`);
56
+ }
57
+
58
+ if (metadata.model) {
59
+ console.log(`Model: ${metadata.model}`);
60
+ }
61
+
62
+ // Display stages
63
+ if (metadata.stages && Object.keys(metadata.stages).length > 0) {
64
+ console.log('\nStages');
65
+ console.log('------');
66
+
67
+ for (const [stage, info] of Object.entries(metadata.stages)) {
68
+ const stageInfo = info as any;
69
+ console.log(`${stage}:`);
70
+ if (stageInfo.duration) {
71
+ console.log(` Duration: ${stageInfo.duration.toFixed(1)}s`);
72
+ }
73
+ if (stageInfo.exitCode !== undefined) {
74
+ console.log(` Exit Code: ${stageInfo.exitCode}`);
75
+ }
76
+ }
77
+ }
78
+
79
+ // Display summary
80
+ if (metadata.status === 'completed' && metadata.exitCode === 0) {
81
+ console.log('\n✅ Instance completed successfully');
82
+ } else if (metadata.status === 'completed') {
83
+ console.log(`\n❌ Instance failed with exit code ${metadata.exitCode}`);
84
+ } else {
85
+ console.log(`\n⏳ Instance status: ${metadata.status}`);
86
+ }
87
+
88
+ // Try to read and show summary
89
+ try {
90
+ const summaryPath = path.join(resultsDir, 'result-summary.md');
91
+ const summary = await fs.readFile(summaryPath, 'utf-8');
92
+ console.log('\nDetailed Summary');
93
+ console.log('----------------');
94
+ console.log(summary);
95
+ } catch {
96
+ // Summary file not found, that's okay
97
+ }
98
+
99
+ return metadata.exitCode === 0 ? 0 : 1;
100
+ } catch (error) {
101
+ console.error(`Instance not found: ${instanceId}`);
102
+ logger.debug(`Failed to read instance: ${error}`);
103
+ return 1;
104
+ }
105
+ } catch (error) {
106
+ logger.error(`Report failed: ${error}`);
107
+ return 1;
108
+ }
109
+ }
110
+ }