@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,131 @@
1
+ #!/usr/bin/env bash
2
+ # Integration-style tests for --dry-run behavior in run-kaseki.sh
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
7
+ RUNNER="$REPO_ROOT/run-kaseki.sh"
8
+
9
+ pass() { printf '✓ %s\n' "$1"; }
10
+ fail() { printf '✗ %s\n' "$1" >&2; exit 1; }
11
+
12
+ require_file() {
13
+ local file="$1"
14
+ [ -f "$file" ] || fail "Expected file to exist: $file"
15
+ }
16
+
17
+ json_field_equals() {
18
+ local file="$1" field="$2" expected="$3"
19
+ local actual
20
+ actual="$(node -e 'const fs=require("fs");const p=process.argv[1];const f=process.argv[2];const o=JSON.parse(fs.readFileSync(p,"utf8"));const v=o[f];process.stdout.write(v===undefined?"":String(v));' "$file" "$field")"
21
+ [ "$actual" = "$expected" ] || fail "Expected $file field '$field' to be '$expected' (got '$actual')"
22
+ }
23
+
24
+ assert_stage_detail() {
25
+ local stage_file="$1" stage_name="$2" detail_expected="$3"
26
+ awk -F '\t' -v stage="$stage_name" -v expected="$detail_expected" '
27
+ $1==stage { found=1; if ($4!=expected) { printf("detail mismatch for %s: expected %s got %s\n", stage, expected, $4) > "/dev/stderr"; exit 2 } }
28
+ END { if (!found) exit 3 }
29
+ ' "$stage_file" || fail "Expected stage '$stage_name' detail '$detail_expected' in $stage_file"
30
+ }
31
+
32
+ assert_file_empty() {
33
+ local file="$1"
34
+ [ -f "$file" ] || fail "Expected file to exist: $file"
35
+ [ ! -s "$file" ] || fail "Expected empty file: $file"
36
+ }
37
+
38
+ run_once() {
39
+ local root="$1" marker="$2"
40
+ local start end elapsed_ms code oldpwd
41
+ start="$(date +%s%3N)"
42
+ oldpwd="$(pwd)"
43
+ cd "$REPO_ROOT"
44
+ export KASEKI_ROOT="$root"
45
+ export KASEKI_LOG_DIR="$root/host-logs"
46
+ export OPENROUTER_API_KEY="dry-run-test-key"
47
+ export REPO_URL=""
48
+ export GIT_REF="main"
49
+ export KASEKI_VALIDATION_COMMANDS="printf SHOULD_NOT_RUN_${marker} > /tmp/kaseki-validation-$$-${marker}"
50
+ export TASK_PROMPT="dry-run behavior test"
51
+ export KASEKI_IMAGE="docker.io/cyanautomation/kaseki-agent:latest"
52
+
53
+ set +e
54
+ "$RUNNER" --dry-run >"$root/run-${marker}.stdout.log" 2>"$root/run-${marker}.stderr.log"
55
+ code=$?
56
+ set -e
57
+ cd "$oldpwd"
58
+ end="$(date +%s%3N)"
59
+ elapsed_ms=$((end-start))
60
+ echo "$code" > "$root/exit-${marker}.txt"
61
+ echo "$elapsed_ms" > "$root/runtime-${marker}.ms"
62
+ }
63
+
64
+ echo "=== Testing --dry-run runtime behavior ==="
65
+
66
+ tmp_root="$(mktemp -d)"
67
+ validation_marker_first="/tmp/kaseki-validation-$$-first"
68
+ validation_marker_second="/tmp/kaseki-validation-$$-second"
69
+ trap 'rm -rf "$tmp_root" "$validation_marker_first" "$validation_marker_second"' EXIT
70
+
71
+ [ ! -e "$validation_marker_first" ] || fail "Pre-existing validation marker found: $validation_marker_first"
72
+ [ ! -e "$validation_marker_second" ] || fail "Pre-existing validation marker found: $validation_marker_second"
73
+
74
+ run_once "$tmp_root" first
75
+ run1_exit="$(cat "$tmp_root/exit-first.txt")"
76
+
77
+ if [ "$run1_exit" != "0" ] && grep -q "missing required host dependencies: docker" "$tmp_root/run-first.stderr.log"; then
78
+ echo "⚠ Docker unavailable; running fallback dry-run smoke checks"
79
+ awk '
80
+ /KASEKI_DRY_RUN/ { seen_dry_run=1 }
81
+ /record_stage_timing "validation" "0" .*"dry_run=true"/ { seen_validation=1 }
82
+ /record_stage_timing "pi coding agent" "0" .*"dry_run=true"/ { seen_agent=1 }
83
+ END { exit (seen_dry_run && seen_validation && seen_agent) ? 0 : 1 }
84
+ ' "$REPO_ROOT/run-kaseki.sh" "$REPO_ROOT/kaseki-agent.sh" || fail "Fallback smoke check failed: dry-run behavior wiring incomplete"
85
+ pass "fallback smoke checks passed under missing docker dependency"
86
+ echo ""
87
+ echo "✅ Dry-run fallback checks passed!"
88
+ exit 0
89
+ fi
90
+
91
+ [ "$run1_exit" = "0" ] || fail "First dry-run invocation should exit 0 (got $run1_exit)"
92
+ pass "dry-run exits with expected code (0)"
93
+
94
+ command -v node >/dev/null 2>&1 || fail "Node.js is required for JSON assertions in dry-run integration checks"
95
+
96
+ result1="$tmp_root/kaseki-results/kaseki-1"
97
+ require_file "$result1/host-start.json"
98
+ require_file "$result1/metadata.json"
99
+ json_field_equals "$result1/host-start.json" "dry_run" "1"
100
+ json_field_equals "$result1/metadata.json" "dry_run" "1"
101
+ pass "host-start.json and metadata.json include dry_run=1"
102
+
103
+ require_file "$result1/stage-timings.tsv"
104
+ assert_stage_detail "$result1/stage-timings.tsv" "pi coding agent" "dry_run=true"
105
+ assert_stage_detail "$result1/stage-timings.tsv" "validation" "dry_run=true"
106
+ assert_stage_detail "$result1/stage-timings.tsv" "secret scan" "dry_run=true"
107
+ pass "stage timing details capture semantic dry-run skips"
108
+
109
+ assert_file_empty "$result1/pi-events.jsonl"
110
+ assert_file_empty "$result1/validation-timings.tsv"
111
+ [ ! -f "/tmp/kaseki-validation-$$-first" ] || fail "Validation command should not execute during dry-run"
112
+ pass "no external side effects (no real agent output / validation command execution)"
113
+
114
+ run_once "$tmp_root" second
115
+ run2_exit="$(cat "$tmp_root/exit-second.txt")"
116
+ [ "$run2_exit" = "0" ] || fail "Second dry-run invocation should exit 0 (got $run2_exit)"
117
+
118
+ result2="$tmp_root/kaseki-results/kaseki-2"
119
+ require_file "$result2/host-start.json"
120
+ require_file "$result2/metadata.json"
121
+ [ -d "$tmp_root/kaseki-results/kaseki-1" ] || fail "First result directory missing after second run"
122
+ [ -f "$tmp_root/kaseki-results/kaseki-1/host-start.json" ] || fail "First run outputs were overwritten"
123
+ [ ! -f "/tmp/kaseki-validation-$$-second" ] || fail "Validation command should not execute on second dry-run"
124
+ first_runtime_ms="$(cat "$tmp_root/runtime-first.ms")"
125
+ second_runtime_ms="$(cat "$tmp_root/runtime-second.ms")"
126
+ [ "$second_runtime_ms" -le $((first_runtime_ms + 1500)) ] || fail "Second run should stay within runtime guardrail (first=${first_runtime_ms}ms second=${second_runtime_ms}ms)"
127
+ pass "runtime tracked (first=${first_runtime_ms}ms second=${second_runtime_ms}ms)"
128
+ pass "second invocation creates kaseki-2 and preserves prior outputs"
129
+
130
+ echo ""
131
+ echo "✅ All --dry-run behavior tests passed!"
@@ -0,0 +1 @@
1
+ {"instance":"fixture-exit-0","exit_code":0,"pi_exit_code":0,"validation_exit_code":0,"quality_exit_code":0,"secret_scan_exit_code":0}
@@ -0,0 +1 @@
1
+ {"instance":"fixture-exit-1","exit_code":1,"pi_exit_code":1,"validation_exit_code":1,"quality_exit_code":1,"secret_scan_exit_code":1}
@@ -0,0 +1 @@
1
+ {"instance":"fixture-exit-invalid","exit_code":"invalid","pi_exit_code":"invalid","validation_exit_code":"invalid","quality_exit_code":"invalid","secret_scan_exit_code":"invalid"}
@@ -0,0 +1 @@
1
+ {"instance":"fixture-exit-str-0","exit_code":"0","pi_exit_code":"0","validation_exit_code":"0","quality_exit_code":"0","secret_scan_exit_code":"0"}
@@ -0,0 +1 @@
1
+ {"instance":"fixture-exit-str-1","exit_code":"1","pi_exit_code":"1","validation_exit_code":"1","quality_exit_code":"1","secret_scan_exit_code":"1"}
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ TEST_NAME="kaseki-api.integration.test"
5
+ API_KEY="sk-test-integration-key"
6
+ PORT="${KASEKI_TEST_API_PORT:-18080}"
7
+ BASE_URL="http://127.0.0.1:${PORT}/api"
8
+
9
+ TMP_ROOT="$(mktemp -d)"
10
+ if [[ -z "$TMP_ROOT" || ! -d "$TMP_ROOT" ]]; then
11
+ echo "[$TEST_NAME] ERROR: Failed to create temporary directory"
12
+ exit 1
13
+ fi
14
+ RESULTS_DIR="${TMP_ROOT}/results"
15
+ API_LOG_DIR="${TMP_ROOT}/api-logs"
16
+ FAKE_REPO_ROOT="${TMP_ROOT}/fake-repo"
17
+ FAKE_SCRIPT="${FAKE_REPO_ROOT}/scripts/kaseki-activate.sh"
18
+ SERVER_LOG="${TMP_ROOT}/server.log"
19
+
20
+ mkdir -p "$RESULTS_DIR" "$API_LOG_DIR" "${FAKE_REPO_ROOT}/scripts"
21
+
22
+ cleanup() {
23
+ local ec=$?
24
+ if [[ -n "${SERVER_PID:-}" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then
25
+ kill "$SERVER_PID" 2>/dev/null || true
26
+ wait "$SERVER_PID" 2>/dev/null || true
27
+ fi
28
+
29
+ if [[ $ec -ne 0 ]]; then
30
+ echo "[$TEST_NAME] FAILED (exit=$ec)"
31
+ echo "[$TEST_NAME] Diagnostics:"
32
+ [[ -f "$SERVER_LOG" ]] && tail -n 120 "$SERVER_LOG" | sed 's/^/[server] /'
33
+ [[ -d "$RESULTS_DIR" ]] && find "$RESULTS_DIR" -maxdepth 3 -type f | sed 's/^/[artifact] /' || true
34
+ fi
35
+
36
+ rm -rf "$TMP_ROOT"
37
+ }
38
+ trap cleanup EXIT
39
+
40
+ cat > "$FAKE_SCRIPT" <<'SCRIPT'
41
+ #!/usr/bin/env bash
42
+ set -euo pipefail
43
+ log_dir="${KASEKI_LOG_DIR:?missing KASEKI_LOG_DIR}"
44
+ mkdir -p "$log_dir"
45
+ printf '{"event":"start","stage":"bootstrap","detail":"boot"}\n' > "$log_dir/progress.jsonl"
46
+ printf 'fake stdout\n' > "$log_dir/stdout.log"
47
+ printf 'fake stderr\n' > "$log_dir/stderr.log"
48
+ printf '{"failure":null}\n' > "$log_dir/metadata.json"
49
+ sleep 0.2
50
+ printf '{"event":"done","stage":"complete","detail":"done"}\n' >> "$log_dir/progress.jsonl"
51
+ SCRIPT
52
+ chmod +x "$FAKE_SCRIPT"
53
+
54
+ echo "[$TEST_NAME] starting api server on :$PORT"
55
+ KASEKI_API_KEYS="$API_KEY" \
56
+ KASEKI_API_PORT="$PORT" \
57
+ KASEKI_RESULTS_DIR="$RESULTS_DIR" \
58
+ KASEKI_API_LOG_DIR="$API_LOG_DIR" \
59
+ KASEKI_API_MAX_CONCURRENT_RUNS=1 \
60
+ KASEKI_AGENT_TIMEOUT_SECONDS=30 \
61
+ PWD="$FAKE_REPO_ROOT" \
62
+ node dist/kaseki-api-service.js >"$SERVER_LOG" 2>&1 &
63
+ SERVER_PID=$!
64
+
65
+ health_ready=false
66
+ for _ in $(seq 1 80); do
67
+ code="$(curl -s -o /dev/null -w '%{http_code}' "$BASE_URL/health" || true)"
68
+ if [[ "$code" == "200" ]]; then
69
+ health_ready=true
70
+ break
71
+ fi
72
+ sleep 0.1
73
+ done
74
+
75
+ if [[ "$health_ready" != "true" ]]; then
76
+ echo "[$TEST_NAME] health endpoint did not become ready"
77
+ exit 1
78
+ fi
79
+
80
+ RUN_PAYLOAD='{"repoUrl":"https://github.com/example/repo"}'
81
+ RUN_RESP="$(curl -sS -X POST "$BASE_URL/runs" \
82
+ -H "Authorization: Bearer $API_KEY" \
83
+ -H 'Content-Type: application/json' \
84
+ --data "$RUN_PAYLOAD")"
85
+
86
+ JOB_ID="$(python3 - "$RUN_RESP" <<'PY'
87
+ import json, re, sys
88
+ try:
89
+ obj=json.loads(sys.argv[1])
90
+ except (json.JSONDecodeError, ValueError) as e:
91
+ raise SystemExit(f"API returned invalid JSON: {e}; response: {sys.argv[1][:200]}")
92
+ if obj.get('status') not in {'queued','running'}:
93
+ raise SystemExit(f"expected status queued|running, got {obj.get('status')}")
94
+ idv=obj.get('id','')
95
+ if not re.fullmatch(r'kaseki-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}', idv):
96
+ raise SystemExit(f"invalid job id format: {idv}")
97
+ print(idv)
98
+ PY
99
+ )"
100
+
101
+ LIST_RESP="$(curl -sS -H "Authorization: Bearer $API_KEY" "$BASE_URL/runs")"
102
+ python3 - "$LIST_RESP" "$JOB_ID" <<'PY'
103
+ import json, sys
104
+ try:
105
+ obj=json.loads(sys.argv[1])
106
+ except (json.JSONDecodeError, ValueError) as e:
107
+ raise SystemExit(f"API returned invalid JSON: {e}; response: {sys.argv[1][:200]}")
108
+ job_id=sys.argv[2]
109
+ if obj.get('total',0) < 1:
110
+ raise SystemExit('runs total is < 1')
111
+ runs=obj.get('runs',[])
112
+ match=[r for r in runs if r.get('id')==job_id]
113
+ if not match:
114
+ raise SystemExit('submitted run missing from list response')
115
+ PY
116
+
117
+ history=""
118
+ final=""
119
+ for _ in $(seq 1 120); do
120
+ STATUS_RESP="$(curl -sS -H "Authorization: Bearer $API_KEY" "$BASE_URL/runs/$JOB_ID/status")"
121
+ cur="$(python3 - "$STATUS_RESP" <<'PY'
122
+ import json, sys
123
+ try:
124
+ print(json.loads(sys.argv[1]).get('status',''))
125
+ except (json.JSONDecodeError, ValueError) as e:
126
+ raise SystemExit(f"API returned invalid JSON: {e}; response: {sys.argv[1][:200]}")
127
+ PY
128
+ )"
129
+ [[ -n "$history" ]] && history+=" "
130
+ history+="$cur"
131
+ if [[ "$cur" == "completed" || "$cur" == "failed" ]]; then
132
+ final="$cur"
133
+ break
134
+ fi
135
+ sleep 0.1
136
+ done
137
+
138
+ if [[ -z "$final" ]]; then
139
+ echo "[$TEST_NAME] job did not reach terminal state; history=$history"
140
+ exit 1
141
+ fi
142
+
143
+ python3 - "$history" <<'PY'
144
+ import sys
145
+ states=sys.argv[1].split()
146
+ allowed={
147
+ 'queued': {'queued','running','completed','failed'},
148
+ 'running': {'running','completed','failed'},
149
+ 'completed': {'completed'},
150
+ 'failed': {'failed'},
151
+ }
152
+ for a,b in zip(states, states[1:]):
153
+ if b not in allowed.get(a,set()):
154
+ raise SystemExit(f'invalid state transition: {a} -> {b}; full={states}')
155
+ PY
156
+
157
+ ART_DIR="$RESULTS_DIR/$JOB_ID"
158
+ for f in progress.jsonl metadata.json stdout.log stderr.log; do
159
+ if [[ ! -f "$ART_DIR/$f" ]]; then
160
+ echo "[$TEST_NAME] missing artifact file: $ART_DIR/$f"
161
+ exit 1
162
+ fi
163
+ done
164
+
165
+ echo "[$TEST_NAME] PASS job_id=$JOB_ID final=$final"
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ TEST_NAME="pi-event-filter-failure.test"
5
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
+
7
+ TMP_ROOT="$(mktemp -d)"
8
+ FAKE_BIN="$TMP_ROOT/bin"
9
+ mkdir -p "$FAKE_BIN" /results
10
+
11
+ cleanup() {
12
+ rm -rf "$TMP_ROOT"
13
+ }
14
+ trap cleanup EXIT
15
+
16
+ cat > "$FAKE_BIN/pi" <<'PI'
17
+ #!/usr/bin/env bash
18
+ if [[ "${1:-}" == "--version" ]]; then
19
+ echo "pi 0.0.0-test"
20
+ exit 0
21
+ fi
22
+ printf '{"type":"message","model":"fake-model"}\n'
23
+ exit 0
24
+ PI
25
+
26
+ cat > "$FAKE_BIN/kaseki-pi-progress-stream" <<'PS'
27
+ #!/usr/bin/env bash
28
+ cat
29
+ PS
30
+
31
+ cat > "$FAKE_BIN/kaseki-pi-event-filter" <<'EF'
32
+ #!/usr/bin/env bash
33
+ exit 7
34
+ EF
35
+
36
+ cat > "$FAKE_BIN/timeout" <<'TO'
37
+ #!/usr/bin/env bash
38
+ shift 2
39
+ "$@"
40
+ TO
41
+
42
+ cat > "$FAKE_BIN/npm" <<'NPM'
43
+ #!/usr/bin/env bash
44
+ exit 0
45
+ NPM
46
+
47
+ cat > "$FAKE_BIN/git" <<'GIT'
48
+ #!/usr/bin/env bash
49
+ case "${1:-}" in
50
+ clone) mkdir -p /workspace/repo; exit 0 ;;
51
+ checkout|config|add|commit) exit 0 ;;
52
+ status) exit 0 ;;
53
+ diff) exit 0 ;;
54
+ rev-parse) echo "abc123"; exit 0 ;;
55
+ *) exit 0 ;;
56
+ esac
57
+ GIT
58
+
59
+ chmod +x "$FAKE_BIN"/*
60
+
61
+ export PATH="$FAKE_BIN:$PATH"
62
+ export OPENROUTER_API_KEY="test"
63
+ export REPO_URL="https://example.com/repo.git"
64
+ export GIT_REF="main"
65
+ export TASK_PROMPT="test"
66
+ export KASEKI_VALIDATION_COMMANDS=":"
67
+ export KASEKI_ALLOW_EMPTY_DIFF=1
68
+
69
+ set +e
70
+ bash "$REPO_ROOT/kaseki-agent.sh" >"$TMP_ROOT/stdout.log" 2>"$TMP_ROOT/stderr.log"
71
+ code=$?
72
+ set -e
73
+
74
+ if [[ "$code" -eq 0 ]]; then
75
+ echo "[$TEST_NAME] expected non-zero exit when event filter fails"
76
+ exit 1
77
+ fi
78
+
79
+ grep -q 'pi_event_filter_failed' /results/progress.jsonl
80
+ grep -q 'kaseki-pi-event-filter' /results/metadata.json
81
+ grep -q 'ERROR: kaseki-pi-event-filter failed' /results/pi-stderr.log
82
+
83
+ echo "[$TEST_NAME] PASS"
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env bash
2
+ # Focused test: Verify the printf safety fix prevents "invalid option" error
3
+
4
+ set -uo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
7
+
8
+ echo "=== Testing Printf Safety Fix ==="
9
+ echo ""
10
+
11
+ # Extract and test the validate_numeric function
12
+ source <(sed -n '/^# Validate that a variable/,/^}/p' "$SCRIPT_DIR/kaseki-agent.sh")
13
+
14
+ echo "Test 1: validate_numeric rejects '-' (the bug trigger)"
15
+ if validate_numeric "test_var" "-" 2>/dev/null; then
16
+ echo " ✗ FAIL: validate_numeric should reject '-' but didn't"
17
+ exit 1
18
+ else
19
+ echo " ✓ PASS: validate_numeric correctly rejected '-'"
20
+ fi
21
+
22
+ echo ""
23
+ echo "Test 2: validate_numeric accepts valid numeric values"
24
+ if validate_numeric "test_var" "42" 2>/dev/null; then
25
+ echo " ✓ PASS: validate_numeric accepted '42'"
26
+ else
27
+ echo " ✗ FAIL: validate_numeric should accept '42' but didn't"
28
+ exit 1
29
+ fi
30
+
31
+ echo ""
32
+ echo "Test 3: Arithmetic with validated numeric values works"
33
+ restored_count=5
34
+ kept_count=3
35
+ if validate_numeric "restored_count" "$restored_count" 2>/dev/null && \
36
+ validate_numeric "kept_count" "$kept_count" 2>/dev/null; then
37
+ total_count=$((restored_count + kept_count))
38
+ echo " ✓ PASS: Arithmetic succeeded (5 + 3 = $total_count)"
39
+ else
40
+ echo " ✗ FAIL: Validation should have passed"
41
+ exit 1
42
+ fi
43
+
44
+ echo ""
45
+ echo "Test 4: Printf with validated numeric values doesn't fail"
46
+ if printf -- '- **Test:** %%d = %d\n' "$total_count" > /dev/null 2>&1; then
47
+ echo " ✓ PASS: Printf with %d format string succeeded with value $total_count"
48
+ else
49
+ echo " ✗ FAIL: Printf should have succeeded"
50
+ exit 1
51
+ fi
52
+
53
+ echo ""
54
+ echo "Test 5: Simulate the bug - unvalidated '-' would cause printf to fail"
55
+ # This would have been the original bug
56
+ unvalidated_count="-"
57
+ if printf 'test: %d\n' "$unvalidated_count" > /dev/null 2>&1; then
58
+ # This might succeed due to bash interpolation, but with real code it would fail
59
+ echo " ⓘ INFO: Bash accepted unquoted '-', but with proper quoting it would fail"
60
+ else
61
+ echo " ✓ PASS: Unvalidated '-' causes printf to fail"
62
+ fi
63
+
64
+ echo ""
65
+ echo "Test 6: Verify grep count fallback never returns '-'"
66
+ test_file=$(mktemp)
67
+ trap "rm -f '$test_file'" EXIT
68
+
69
+ # Empty file
70
+ count=$(grep -c 'pattern' "$test_file" 2>/dev/null || echo 0)
71
+ if [ "$count" = "-" ]; then
72
+ echo " ✗ FAIL: grep -c fallback returned '-'"
73
+ exit 1
74
+ else
75
+ echo " ✓ PASS: grep -c fallback returned '$count' (not '-')"
76
+ fi
77
+
78
+ echo ""
79
+ echo "Test 7: json_encode availability"
80
+ source <(sed -n '/^# Safely encode value/,/^}/p' "$SCRIPT_DIR/kaseki-agent.sh" | head -20)
81
+
82
+ output=$(printf 'test' | json_encode 2>/dev/null || true)
83
+ if [ -n "$output" ]; then
84
+ echo " ✓ PASS: json_encode produced output: $output"
85
+ else
86
+ echo " ⓘ INFO: json_encode fallback returned empty (expected if node unavailable)"
87
+ fi
88
+
89
+ echo ""
90
+ echo "=== All Critical Tests Passed ==="
91
+ echo ""
92
+ echo "Summary of fixes:"
93
+ echo " 1. ✓ validate_numeric() prevents dash/non-numeric values"
94
+ echo " 2. ✓ Arithmetic only happens after validation"
95
+ echo " 3. ✓ Printf calls use validated numeric arguments"
96
+ echo " 4. ✓ grep count fallback prevents dash values"
97
+ echo " 5. ✓ json_encode has error handling and fallback"
98
+ echo ""
99
+ echo "The 'printf: - : invalid option' error is now prevented."
@@ -0,0 +1,10 @@
1
+ {"timestamp":"2026-05-07T10:00:00Z","event":"file_evaluated","file":"src/test.ts","status":"kept","reason":"matched_allowlist"}
2
+ {"timestamp":"2026-05-07T10:00:01","event":"file_restored","file":"file1.txt","status":"restored","reason":"not_in_allowlist"}
3
+ {"timestamp":"2026-05-07T10:00:02","event":"file_restored","file":"file2.txt","status":"restored","reason":"not_in_allowlist"}
4
+ {"timestamp":"2026-05-07T10:00:03","event":"file_restored","file":"file3.txt","status":"restored","reason":"not_in_allowlist"}
5
+ {"timestamp":"2026-05-07T10:00:04","event":"file_restored","file":"file4.txt","status":"restored","reason":"not_in_allowlist"}
6
+ {"timestamp":"2026-05-07T10:00:05","event":"file_restored","file":"file5.txt","status":"restored","reason":"not_in_allowlist"}
7
+ {"timestamp":"2026-05-07T10:00:06","event":"file_restored","file":"file6.txt","status":"restored","reason":"not_in_allowlist"}
8
+ {"timestamp":"2026-05-07T10:00:07","event":"file_restored","file":"file7.txt","status":"restored","reason":"not_in_allowlist"}
9
+ {"timestamp":"2026-05-07T10:00:08","event":"file_restored","file":"file8.txt","status":"restored","reason":"not_in_allowlist"}
10
+ {"timestamp":"2026-05-07T10:00:09","event":"file_restored","file":"file9.txt","status":"restored","reason":"not_in_allowlist"}
File without changes