@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.
- package/.dockerignore +54 -0
- package/.eslintignore +11 -0
- package/.eslintrc.json +95 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +53 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +53 -0
- package/.github/ISSUE_TEMPLATE/security.md +51 -0
- package/.github/PULL_REQUEST_TEMPLATE/default.md +71 -0
- package/.github/dependabot.yml +38 -0
- package/.github/skills/dependency-cache-optimization/SKILL.md +526 -0
- package/.github/skills/docker-image-management/SKILL.md +532 -0
- package/.github/skills/frontend-design/SKILL.md +782 -0
- package/.github/skills/prompt-engineering/SKILL.md +360 -0
- package/.github/skills/quality-gate-config/SKILL.md +591 -0
- package/.github/skills/result-report-analysis/SKILL.md +576 -0
- package/.github/skills/test-automation/SKILL.md +593 -0
- package/.github/skills/workflow-diagnosis/SKILL.md +468 -0
- package/.github/workflows/build-docker-image.yml +453 -0
- package/.github/workflows/release.yml +68 -0
- package/.releaserc.json +135 -0
- package/CHANGELOG.md +117 -0
- package/CLAUDE.md +336 -0
- package/CONTRIBUTING.md +339 -0
- package/Dockerfile +217 -0
- package/README.md +1527 -0
- package/STYLE.md +521 -0
- package/add-js-extensions.d.ts +9 -0
- package/add-js-extensions.d.ts.map +1 -0
- package/add-js-extensions.js.map +1 -0
- package/dist/add-js-extensions.d.ts +9 -0
- package/dist/add-js-extensions.d.ts.map +1 -0
- package/dist/add-js-extensions.js +52 -0
- package/dist/add-js-extensions.js.map +1 -0
- package/dist/ansi-colors.d.ts +26 -0
- package/dist/ansi-colors.d.ts.map +1 -0
- package/dist/ansi-colors.js +51 -0
- package/dist/ansi-colors.js.map +1 -0
- package/dist/cli/BaseCommand.d.ts +18 -0
- package/dist/cli/BaseCommand.d.ts.map +1 -0
- package/dist/cli/BaseCommand.js +31 -0
- package/dist/cli/BaseCommand.js.map +1 -0
- package/dist/cli/KasekiCLI.d.ts +30 -0
- package/dist/cli/KasekiCLI.d.ts.map +1 -0
- package/dist/cli/KasekiCLI.js +134 -0
- package/dist/cli/KasekiCLI.js.map +1 -0
- package/dist/cli/commands/ConfigCommand.d.ts +13 -0
- package/dist/cli/commands/ConfigCommand.d.ts.map +1 -0
- package/dist/cli/commands/ConfigCommand.js +131 -0
- package/dist/cli/commands/ConfigCommand.js.map +1 -0
- package/dist/cli/commands/DoctorCommand.d.ts +45 -0
- package/dist/cli/commands/DoctorCommand.d.ts.map +1 -0
- package/dist/cli/commands/DoctorCommand.js +309 -0
- package/dist/cli/commands/DoctorCommand.js.map +1 -0
- package/dist/cli/commands/ListCommand.d.ts +9 -0
- package/dist/cli/commands/ListCommand.d.ts.map +1 -0
- package/dist/cli/commands/ListCommand.js +81 -0
- package/dist/cli/commands/ListCommand.js.map +1 -0
- package/dist/cli/commands/ReportCommand.d.ts +9 -0
- package/dist/cli/commands/ReportCommand.d.ts.map +1 -0
- package/dist/cli/commands/ReportCommand.js +98 -0
- package/dist/cli/commands/ReportCommand.js.map +1 -0
- package/dist/cli/commands/RunCommand.d.ts +13 -0
- package/dist/cli/commands/RunCommand.d.ts.map +1 -0
- package/dist/cli/commands/RunCommand.js +191 -0
- package/dist/cli/commands/RunCommand.js.map +1 -0
- package/dist/cli/commands/SecretsCommand.d.ts +9 -0
- package/dist/cli/commands/SecretsCommand.d.ts.map +1 -0
- package/dist/cli/commands/SecretsCommand.js +109 -0
- package/dist/cli/commands/SecretsCommand.js.map +1 -0
- package/dist/cli/commands/ServeCommand.d.ts +9 -0
- package/dist/cli/commands/ServeCommand.d.ts.map +1 -0
- package/dist/cli/commands/ServeCommand.js +50 -0
- package/dist/cli/commands/ServeCommand.js.map +1 -0
- package/dist/cli/commands/SetupCommand.d.ts +42 -0
- package/dist/cli/commands/SetupCommand.d.ts.map +1 -0
- package/dist/cli/commands/SetupCommand.js +249 -0
- package/dist/cli/commands/SetupCommand.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +130 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +395 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +446 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/docker/DockerManager.d.ts +69 -0
- package/dist/docker/DockerManager.d.ts.map +1 -0
- package/dist/docker/DockerManager.js +266 -0
- package/dist/docker/DockerManager.js.map +1 -0
- package/dist/event-aggregator.d.ts +71 -0
- package/dist/event-aggregator.d.ts.map +1 -0
- package/dist/event-aggregator.js +95 -0
- package/dist/event-aggregator.js.map +1 -0
- package/dist/github-app-token.d.ts +16 -0
- package/dist/github-app-token.d.ts.map +1 -0
- package/dist/github-app-token.js +148 -0
- package/dist/github-app-token.js.map +1 -0
- package/dist/idempotency-store.d.ts +61 -0
- package/dist/idempotency-store.d.ts.map +1 -0
- package/dist/idempotency-store.js +321 -0
- package/dist/idempotency-store.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/instance/InstanceManager.d.ts +81 -0
- package/dist/instance/InstanceManager.d.ts.map +1 -0
- package/dist/instance/InstanceManager.js +220 -0
- package/dist/instance/InstanceManager.js.map +1 -0
- package/dist/instance-metadata-reader.d.ts +48 -0
- package/dist/instance-metadata-reader.d.ts.map +1 -0
- package/dist/instance-metadata-reader.js +94 -0
- package/dist/instance-metadata-reader.js.map +1 -0
- package/dist/instance-state-derivation.d.ts +42 -0
- package/dist/instance-state-derivation.d.ts.map +1 -0
- package/dist/instance-state-derivation.js +133 -0
- package/dist/instance-state-derivation.js.map +1 -0
- package/dist/job-scheduler.d.ts +124 -0
- package/dist/job-scheduler.d.ts.map +1 -0
- package/dist/job-scheduler.js +992 -0
- package/dist/job-scheduler.js.map +1 -0
- package/dist/kaseki-api-client.d.ts +89 -0
- package/dist/kaseki-api-client.d.ts.map +1 -0
- package/dist/kaseki-api-client.js +405 -0
- package/dist/kaseki-api-client.js.map +1 -0
- package/dist/kaseki-api-config.d.ts +34 -0
- package/dist/kaseki-api-config.d.ts.map +1 -0
- package/dist/kaseki-api-config.js +113 -0
- package/dist/kaseki-api-config.js.map +1 -0
- package/dist/kaseki-api-routes.d.ts +13 -0
- package/dist/kaseki-api-routes.d.ts.map +1 -0
- package/dist/kaseki-api-routes.js +559 -0
- package/dist/kaseki-api-routes.js.map +1 -0
- package/dist/kaseki-api-service-wrapper.d.ts +43 -0
- package/dist/kaseki-api-service-wrapper.d.ts.map +1 -0
- package/dist/kaseki-api-service-wrapper.js +150 -0
- package/dist/kaseki-api-service-wrapper.js.map +1 -0
- package/dist/kaseki-api-service.d.ts +16 -0
- package/dist/kaseki-api-service.d.ts.map +1 -0
- package/dist/kaseki-api-service.js +143 -0
- package/dist/kaseki-api-service.js.map +1 -0
- package/dist/kaseki-api-types.d.ts +440 -0
- package/dist/kaseki-api-types.d.ts.map +1 -0
- package/dist/kaseki-api-types.js +64 -0
- package/dist/kaseki-api-types.js.map +1 -0
- package/dist/kaseki-cli-lib.d.ts +219 -0
- package/dist/kaseki-cli-lib.d.ts.map +1 -0
- package/dist/kaseki-cli-lib.js +523 -0
- package/dist/kaseki-cli-lib.js.map +1 -0
- package/dist/kaseki-cli.d.ts +38 -0
- package/dist/kaseki-cli.d.ts.map +1 -0
- package/dist/kaseki-cli.js +559 -0
- package/dist/kaseki-cli.js.map +1 -0
- package/dist/kaseki-report.d.ts +3 -0
- package/dist/kaseki-report.d.ts.map +1 -0
- package/dist/kaseki-report.js +140 -0
- package/dist/kaseki-report.js.map +1 -0
- package/dist/lib/subprocess-helpers.d.ts +98 -0
- package/dist/lib/subprocess-helpers.d.ts.map +1 -0
- package/dist/lib/subprocess-helpers.js +136 -0
- package/dist/lib/subprocess-helpers.js.map +1 -0
- package/dist/logger.d.ts +39 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +79 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +19 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +59 -0
- package/dist/metrics.js.map +1 -0
- package/dist/middleware/job-lookup.d.ts +27 -0
- package/dist/middleware/job-lookup.d.ts.map +1 -0
- package/dist/middleware/job-lookup.js +28 -0
- package/dist/middleware/job-lookup.js.map +1 -0
- package/dist/pi-event-filter.d.ts +3 -0
- package/dist/pi-event-filter.d.ts.map +1 -0
- package/dist/pi-event-filter.js +126 -0
- package/dist/pi-event-filter.js.map +1 -0
- package/dist/pi-progress-stream.d.ts +3 -0
- package/dist/pi-progress-stream.d.ts.map +1 -0
- package/dist/pi-progress-stream.js +205 -0
- package/dist/pi-progress-stream.js.map +1 -0
- package/dist/pi-progress-summarizer.d.ts +61 -0
- package/dist/pi-progress-summarizer.d.ts.map +1 -0
- package/dist/pi-progress-summarizer.js +246 -0
- package/dist/pi-progress-summarizer.js.map +1 -0
- package/dist/pre-flight-validator.d.ts +72 -0
- package/dist/pre-flight-validator.d.ts.map +1 -0
- package/dist/pre-flight-validator.js +513 -0
- package/dist/pre-flight-validator.js.map +1 -0
- package/dist/progress-stream-utils.d.ts +3 -0
- package/dist/progress-stream-utils.d.ts.map +1 -0
- package/dist/progress-stream-utils.js +15 -0
- package/dist/progress-stream-utils.js.map +1 -0
- package/dist/result-cache.d.ts +52 -0
- package/dist/result-cache.d.ts.map +1 -0
- package/dist/result-cache.js +134 -0
- package/dist/result-cache.js.map +1 -0
- package/dist/routes/artifact-routes.d.ts +10 -0
- package/dist/routes/artifact-routes.d.ts.map +1 -0
- package/dist/routes/artifact-routes.js +126 -0
- package/dist/routes/artifact-routes.js.map +1 -0
- package/dist/routes/log-routes.d.ts +8 -0
- package/dist/routes/log-routes.d.ts.map +1 -0
- package/dist/routes/log-routes.js +345 -0
- package/dist/routes/log-routes.js.map +1 -0
- package/dist/routes/status-routes.d.ts +8 -0
- package/dist/routes/status-routes.d.ts.map +1 -0
- package/dist/routes/status-routes.js +82 -0
- package/dist/routes/status-routes.js.map +1 -0
- package/dist/routes/webhook-routes.d.ts +6 -0
- package/dist/routes/webhook-routes.d.ts.map +1 -0
- package/dist/routes/webhook-routes.js +86 -0
- package/dist/routes/webhook-routes.js.map +1 -0
- package/dist/run-artifact-metadata-cache.d.ts +42 -0
- package/dist/run-artifact-metadata-cache.d.ts.map +1 -0
- package/dist/run-artifact-metadata-cache.js +139 -0
- package/dist/run-artifact-metadata-cache.js.map +1 -0
- package/dist/secret-value-cache.d.ts +13 -0
- package/dist/secret-value-cache.d.ts.map +1 -0
- package/dist/secret-value-cache.js +44 -0
- package/dist/secret-value-cache.js.map +1 -0
- package/dist/secrets/SecretsManager.d.ts +80 -0
- package/dist/secrets/SecretsManager.d.ts.map +1 -0
- package/dist/secrets/SecretsManager.js +306 -0
- package/dist/secrets/SecretsManager.js.map +1 -0
- package/dist/test-utils.d.ts +55 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +48 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/timestamp-tracker.d.ts +75 -0
- package/dist/timestamp-tracker.d.ts.map +1 -0
- package/dist/timestamp-tracker.js +121 -0
- package/dist/timestamp-tracker.js.map +1 -0
- package/dist/utils/failure-artifact-writer.d.ts +29 -0
- package/dist/utils/failure-artifact-writer.d.ts.map +1 -0
- package/dist/utils/failure-artifact-writer.js +157 -0
- package/dist/utils/failure-artifact-writer.js.map +1 -0
- package/dist/utils/file-helpers.d.ts +41 -0
- package/dist/utils/file-helpers.d.ts.map +1 -0
- package/dist/utils/file-helpers.js +143 -0
- package/dist/utils/file-helpers.js.map +1 -0
- package/dist/utils/http-client-factory.d.ts +46 -0
- package/dist/utils/http-client-factory.d.ts.map +1 -0
- package/dist/utils/http-client-factory.js +114 -0
- package/dist/utils/http-client-factory.js.map +1 -0
- package/dist/utils/progress-normalizer.d.ts +13 -0
- package/dist/utils/progress-normalizer.d.ts.map +1 -0
- package/dist/utils/progress-normalizer.js +57 -0
- package/dist/utils/progress-normalizer.js.map +1 -0
- package/dist/utils/response-helpers.d.ts +34 -0
- package/dist/utils/response-helpers.d.ts.map +1 -0
- package/dist/utils/response-helpers.js +78 -0
- package/dist/utils/response-helpers.js.map +1 -0
- package/dist/utils/route-helpers.d.ts +17 -0
- package/dist/utils/route-helpers.d.ts.map +1 -0
- package/dist/utils/route-helpers.js +22 -0
- package/dist/utils/route-helpers.js.map +1 -0
- package/dist/utils/status-response-builder.d.ts +23 -0
- package/dist/utils/status-response-builder.d.ts.map +1 -0
- package/dist/utils/status-response-builder.js +144 -0
- package/dist/utils/status-response-builder.js.map +1 -0
- package/dist/utils/type-guards.d.ts +37 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +45 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/dist/utils/utf8-helpers.d.ts +32 -0
- package/dist/utils/utf8-helpers.d.ts.map +1 -0
- package/dist/utils/utf8-helpers.js +97 -0
- package/dist/utils/utf8-helpers.js.map +1 -0
- package/dist/utils/webhook-event-builder.d.ts +26 -0
- package/dist/utils/webhook-event-builder.d.ts.map +1 -0
- package/dist/utils/webhook-event-builder.js +77 -0
- package/dist/utils/webhook-event-builder.js.map +1 -0
- package/dist/webhook-manager.d.ts +56 -0
- package/dist/webhook-manager.d.ts.map +1 -0
- package/dist/webhook-manager.js +359 -0
- package/dist/webhook-manager.js.map +1 -0
- package/docker/workspace-cache/package-lock.json +13 -0
- package/docker/workspace-cache/package.json +7 -0
- package/docker-compose.yml +53 -0
- package/docs/API.md +708 -0
- package/docs/BACKLOG.md +19 -0
- package/docs/BUILD_STRATEGY.md +404 -0
- package/docs/CLI.md +569 -0
- package/docs/DEPLOYMENT.md +521 -0
- package/docs/DEVELOPMENT.md +459 -0
- package/docs/DOCKER_SETUP.md +522 -0
- package/docs/ENHANCED_PROGRESS_LOGS.md +264 -0
- package/docs/IMPLEMENTATION_SUMMARY.md +549 -0
- package/docs/INTEGRATION_EXAMPLE.md +217 -0
- package/docs/NPM_SETUP.md +468 -0
- package/docs/PHASE1-4_IMPLEMENTATION.md +302 -0
- package/docs/PHASE1_COMPLETION.md +192 -0
- package/docs/PHASE2_COMPLETION.md +134 -0
- package/docs/PHASE6_MIGRATION.md +392 -0
- package/docs/PRINTF_SAFETY_FIX.md +282 -0
- package/docs/QUALITY_GATES.md +369 -0
- package/docs/SETUP_GUIDE.md +482 -0
- package/docs/TASK_PROMPT_TEMPLATES.md +533 -0
- package/docs/VALIDATION_FIX.md +139 -0
- package/docs/VERIFICATION_CHECKLIST.md +335 -0
- package/docs/repo-maturity.md +760 -0
- package/fix-tests.d.ts +9 -0
- package/fix-tests.d.ts.map +1 -0
- package/fix-tests.js.map +1 -0
- package/fix-tests.ts +53 -0
- package/jest.config.ts +31 -0
- package/kaseki +183 -0
- package/kaseki-agent.sh +1961 -0
- package/ops/logrotate/kaseki +10 -0
- package/package.json +83 -0
- package/perf/README.md +54 -0
- package/perf/pi-event-filter.benchmark.test.ts +98 -0
- package/run-kaseki-json.test.sh +106 -0
- package/run-kaseki.sh +990 -0
- package/scripts/allowlist-helper.sh +56 -0
- package/scripts/cleanup-kaseki.sh +168 -0
- package/scripts/deploy-pi-template.sh +293 -0
- package/scripts/docker-entrypoint.sh +71 -0
- package/scripts/dry-run-allowlist.sh +161 -0
- package/scripts/kaseki-activate.sh +396 -0
- package/scripts/kaseki-api.service +62 -0
- package/scripts/kaseki-container-entrypoint-wrapper.sh +119 -0
- package/scripts/kaseki-container-setup-remote.sh +172 -0
- package/scripts/kaseki-container-setup.sh +193 -0
- package/scripts/kaseki-healthcheck.sh +95 -0
- package/scripts/kaseki-install.sh +50 -0
- package/scripts/kaseki-maturity-score.sh +291 -0
- package/scripts/kaseki-performance-metrics.sh +122 -0
- package/scripts/kaseki-preflight.sh +270 -0
- package/scripts/kaseki-setup.sh +265 -0
- package/scripts/pi-setup-remote.sh +213 -0
- package/scripts/setup-github-labels.sh +42 -0
- package/scripts/suggest-allowlist.sh +68 -0
- package/scripts/templates/MULTI_HOST_DISTRIBUTED.md +337 -0
- package/scripts/templates/REST_API_SERVICE.md +490 -0
- package/scripts/templates/SINGLE_HOST_CLI.md +194 -0
- package/scripts/test-github-app.sh +248 -0
- package/src/add-js-extensions.ts +61 -0
- package/src/ansi-colors.test.ts +62 -0
- package/src/ansi-colors.ts +67 -0
- package/src/cli/BaseCommand.ts +40 -0
- package/src/cli/KasekiCLI.ts +154 -0
- package/src/cli/commands/ConfigCommand.ts +145 -0
- package/src/cli/commands/DoctorCommand.ts +329 -0
- package/src/cli/commands/ListCommand.ts +105 -0
- package/src/cli/commands/ReportCommand.ts +110 -0
- package/src/cli/commands/RunCommand.ts +218 -0
- package/src/cli/commands/SecretsCommand.ts +120 -0
- package/src/cli/commands/ServeCommand.ts +62 -0
- package/src/cli/commands/SetupCommand.ts +301 -0
- package/src/cli.ts +138 -0
- package/src/config/ConfigManager.ts +476 -0
- package/src/docker/DockerManager.ts +319 -0
- package/src/docker-entrypoint-packaging.test.ts +33 -0
- package/src/event-aggregator.test.ts +117 -0
- package/src/event-aggregator.ts +126 -0
- package/src/github-app-token.ts +215 -0
- package/src/idempotency-store.test.ts +117 -0
- package/src/idempotency-store.ts +385 -0
- package/src/index.ts +89 -0
- package/src/instance/InstanceManager.ts +285 -0
- package/src/instance-metadata-reader.test.ts +190 -0
- package/src/instance-metadata-reader.ts +129 -0
- package/src/instance-state-derivation.test.ts +263 -0
- package/src/instance-state-derivation.ts +148 -0
- package/src/job-scheduler.test.ts +1236 -0
- package/src/job-scheduler.ts +1117 -0
- package/src/kaseki-api-client.ts +488 -0
- package/src/kaseki-api-config.test.ts +315 -0
- package/src/kaseki-api-config.ts +175 -0
- package/src/kaseki-api-routes.test.ts +1615 -0
- package/src/kaseki-api-routes.ts +643 -0
- package/src/kaseki-api-service-wrapper.ts +188 -0
- package/src/kaseki-api-service.test.ts +418 -0
- package/src/kaseki-api-service.ts +192 -0
- package/src/kaseki-api-types.ts +320 -0
- package/src/kaseki-cli-lib.test.ts +552 -0
- package/src/kaseki-cli-lib.ts +760 -0
- package/src/kaseki-cli.ts +682 -0
- package/src/kaseki-report.test.ts +118 -0
- package/src/kaseki-report.ts +192 -0
- package/src/lib/subprocess-helpers.ts +177 -0
- package/src/logger.ts +114 -0
- package/src/metrics.ts +66 -0
- package/src/middleware/job-lookup.test.ts +113 -0
- package/src/middleware/job-lookup.ts +45 -0
- package/src/pi-event-filter.test.ts +183 -0
- package/src/pi-event-filter.ts +183 -0
- package/src/pi-progress-stream.ts +287 -0
- package/src/pi-progress-summarizer.test.ts +302 -0
- package/src/pi-progress-summarizer.ts +287 -0
- package/src/pre-flight-validator.test.ts +512 -0
- package/src/pre-flight-validator.ts +618 -0
- package/src/progress-stream-utils.test.ts +35 -0
- package/src/progress-stream-utils.ts +14 -0
- package/src/result-cache.test.ts +195 -0
- package/src/result-cache.ts +181 -0
- package/src/routes/artifact-routes.ts +169 -0
- package/src/routes/log-routes.ts +391 -0
- package/src/routes/status-routes.ts +92 -0
- package/src/routes/webhook-routes.ts +97 -0
- package/src/run-artifact-metadata-cache.test.ts +80 -0
- package/src/run-artifact-metadata-cache.ts +184 -0
- package/src/secret-value-cache.test.ts +66 -0
- package/src/secret-value-cache.ts +55 -0
- package/src/secrets/SecretsManager.ts +343 -0
- package/src/test-utils.ts +81 -0
- package/src/timestamp-tracker.test.ts +134 -0
- package/src/timestamp-tracker.ts +132 -0
- package/src/utils/failure-artifact-writer.ts +187 -0
- package/src/utils/file-helpers.test.ts +235 -0
- package/src/utils/file-helpers.ts +150 -0
- package/src/utils/http-client-factory.test.ts +245 -0
- package/src/utils/http-client-factory.ts +157 -0
- package/src/utils/progress-normalizer.test.ts +442 -0
- package/src/utils/progress-normalizer.ts +68 -0
- package/src/utils/response-helpers.test.ts +122 -0
- package/src/utils/response-helpers.ts +101 -0
- package/src/utils/route-helpers.ts +30 -0
- package/src/utils/status-response-builder.ts +159 -0
- package/src/utils/type-guards.ts +52 -0
- package/src/utils/utf8-helpers.ts +102 -0
- package/src/utils/webhook-event-builder.test.ts +143 -0
- package/src/utils/webhook-event-builder.ts +87 -0
- package/src/webhook-manager.test.ts +152 -0
- package/src/webhook-manager.ts +445 -0
- package/templates/allowlist-api-route.txt +7 -0
- package/templates/allowlist-comprehensive.txt +8 -0
- package/templates/allowlist-parser-fix.txt +6 -0
- package/templates/allowlist-ui-component.txt +9 -0
- package/templates/allowlist-utility.txt +9 -0
- package/test/actual-model-metadata.test.sh +102 -0
- package/test/dry-run.test.sh +131 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-0.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-1.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-invalid.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-str-0.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-str-1.json +1 -0
- package/test/kaseki-api.integration.test.sh +165 -0
- package/test/pi-event-filter-failure.test.sh +83 -0
- package/test/printf-safety-focused.test.sh +99 -0
- package/test/printf-safety-results/results/restoration.jsonl +10 -0
- package/test/printf-safety-results/results/test.jsonl +0 -0
- package/test/printf-safety.test.sh +297 -0
- package/test/validation-fix.test.sh +79 -0
- package/test/validation-integration.test.sh +109 -0
- package/tests/allowlist-glob.test.sh +61 -0
- package/tests/dependency-cache-key.test.sh +48 -0
- package/tests/dependency-restore-mode.test.sh +48 -0
- package/tests/doctor-template-parity.test.sh +95 -0
- package/tests/github-operations.test.sh +142 -0
- package/tests/npm-install-flags.test.sh +58 -0
- package/tests/quality-gates.test.sh +178 -0
- package/tests/repo-memory.test.sh +103 -0
- package/tests/restore-disallowed-changes.test.sh +80 -0
- package/tests/validation-missing-npm-scripts.test.sh +93 -0
- package/tests/validation-strict-mode.test.sh +118 -0
- package/tsconfig.changed.json +7 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets Manager
|
|
3
|
+
*
|
|
4
|
+
* Secure credential storage with keyring integration
|
|
5
|
+
* - Primary: Linux keyring (pass)
|
|
6
|
+
* - Fallback: File-based storage (~/.kaseki/secrets/) with 0600 permissions
|
|
7
|
+
*
|
|
8
|
+
* Note: macOS Keychain and Windows Credential Manager support can be added
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import os from 'os';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
14
|
+
import { createLogger } from '../logger.js';
|
|
15
|
+
const logger = createLogger('secrets');
|
|
16
|
+
/**
|
|
17
|
+
* File-based secrets store (fallback, headless systems)
|
|
18
|
+
*/
|
|
19
|
+
export class FileSecretsStore {
|
|
20
|
+
baseDir;
|
|
21
|
+
constructor(baseDir) {
|
|
22
|
+
this.baseDir = baseDir || path.join(os.homedir(), '.kaseki', 'secrets');
|
|
23
|
+
}
|
|
24
|
+
async store(key, value) {
|
|
25
|
+
try {
|
|
26
|
+
await fs.mkdir(this.baseDir, { recursive: true, mode: 0o700 });
|
|
27
|
+
const filePath = path.join(this.baseDir, key);
|
|
28
|
+
// Write with restrictive permissions (0600 - owner read/write only)
|
|
29
|
+
await fs.writeFile(filePath, value, {
|
|
30
|
+
mode: 0o600,
|
|
31
|
+
flag: 'w',
|
|
32
|
+
});
|
|
33
|
+
logger.debug(`Secret stored: ${key} -> ${filePath}`);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new Error(`Failed to store secret: ${error}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async retrieve(key) {
|
|
40
|
+
try {
|
|
41
|
+
const filePath = path.join(this.baseDir, key);
|
|
42
|
+
const stat = await fs.stat(filePath);
|
|
43
|
+
// Security check: verify file permissions are restrictive
|
|
44
|
+
if ((stat.mode & 0o077) !== 0) {
|
|
45
|
+
logger.warn(`Secret file has overly permissive permissions: ${filePath}`);
|
|
46
|
+
}
|
|
47
|
+
const value = await fs.readFile(filePath, 'utf-8');
|
|
48
|
+
return value.trim();
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (error.code === 'ENOENT') {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Failed to retrieve secret: ${error}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async delete(key) {
|
|
58
|
+
try {
|
|
59
|
+
const filePath = path.join(this.baseDir, key);
|
|
60
|
+
await fs.unlink(filePath);
|
|
61
|
+
logger.debug(`Secret deleted: ${key}`);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (error.code !== 'ENOENT') {
|
|
65
|
+
throw new Error(`Failed to delete secret: ${error}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async list() {
|
|
70
|
+
try {
|
|
71
|
+
const files = await fs.readdir(this.baseDir);
|
|
72
|
+
return files;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error.code === 'ENOENT') {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Linux pass (password-store) backed secrets
|
|
84
|
+
* Requires: pass package installed and initialized
|
|
85
|
+
*/
|
|
86
|
+
export class PassSecretsStore {
|
|
87
|
+
prefix;
|
|
88
|
+
constructor(prefix = 'kaseki-agent') {
|
|
89
|
+
this.prefix = prefix;
|
|
90
|
+
}
|
|
91
|
+
getPassKey(key) {
|
|
92
|
+
return `${this.prefix}/${key}`;
|
|
93
|
+
}
|
|
94
|
+
isPassAvailable() {
|
|
95
|
+
try {
|
|
96
|
+
execSync('command -v pass', { shell: '/bin/bash', stdio: 'ignore' });
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
isPassInitialized() {
|
|
104
|
+
try {
|
|
105
|
+
execSync('pass ls > /dev/null 2>&1', { shell: '/bin/bash', stdio: 'ignore' });
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async store(key, value) {
|
|
113
|
+
if (!this.isPassAvailable()) {
|
|
114
|
+
throw new Error('pass (password-store) not installed. Install with: sudo apt install pass');
|
|
115
|
+
}
|
|
116
|
+
if (!this.isPassInitialized()) {
|
|
117
|
+
throw new Error('pass (password-store) not initialized. Run: pass init');
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
// Use echo + pass insert to avoid interactive prompt
|
|
121
|
+
const passKey = this.getPassKey(key);
|
|
122
|
+
execSync(`echo "${value.replace(/"/g, '\\"')}" | pass insert -f "${passKey}"`, {
|
|
123
|
+
shell: '/bin/bash',
|
|
124
|
+
});
|
|
125
|
+
logger.debug(`Secret stored in pass: ${passKey}`);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
throw new Error(`Failed to store secret in pass: ${error}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async retrieve(key) {
|
|
132
|
+
if (!this.isPassAvailable()) {
|
|
133
|
+
logger.debug('pass not available, skipping keyring retrieval');
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const passKey = this.getPassKey(key);
|
|
138
|
+
const result = execSync(`pass show "${passKey}" 2>/dev/null || echo ""`, {
|
|
139
|
+
shell: '/bin/bash',
|
|
140
|
+
encoding: 'utf-8',
|
|
141
|
+
});
|
|
142
|
+
return result.trim() || null;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
logger.debug(`Failed to retrieve secret from pass: ${error}`);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async delete(key) {
|
|
150
|
+
if (!this.isPassAvailable()) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const passKey = this.getPassKey(key);
|
|
155
|
+
execSync(`pass rm -f "${passKey}"`, { shell: '/bin/bash' });
|
|
156
|
+
logger.debug(`Secret deleted from pass: ${passKey}`);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
throw new Error(`Failed to delete secret from pass: ${error}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async list() {
|
|
163
|
+
if (!this.isPassAvailable()) {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const result = execSync(`pass ls 2>/dev/null | grep "^${this.prefix}/" || echo ""`, {
|
|
168
|
+
shell: '/bin/bash',
|
|
169
|
+
encoding: 'utf-8',
|
|
170
|
+
});
|
|
171
|
+
return result
|
|
172
|
+
.split('\n')
|
|
173
|
+
.filter((line) => line.trim())
|
|
174
|
+
.map((line) => line.replace(`${this.prefix}/`, ''));
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
logger.debug(`Failed to list secrets from pass: ${error}`);
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Secrets Manager - Main interface
|
|
184
|
+
* Tries keyring first, falls back to file storage
|
|
185
|
+
*/
|
|
186
|
+
export class SecretsManager {
|
|
187
|
+
fileStore;
|
|
188
|
+
passStore;
|
|
189
|
+
usePassIfAvailable;
|
|
190
|
+
constructor(usePassIfAvailable = true) {
|
|
191
|
+
this.fileStore = new FileSecretsStore();
|
|
192
|
+
this.passStore = new PassSecretsStore();
|
|
193
|
+
this.usePassIfAvailable = usePassIfAvailable;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Store a secret with automatic fallback
|
|
197
|
+
*/
|
|
198
|
+
async store(key, value) {
|
|
199
|
+
if (this.usePassIfAvailable && this.isPassAvailable()) {
|
|
200
|
+
try {
|
|
201
|
+
await this.passStore.store(key, value);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
logger.warn(`Keyring storage failed, falling back to file storage: ${error}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
await this.fileStore.store(key, value);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Retrieve a secret (tries keyring first, then file)
|
|
212
|
+
*/
|
|
213
|
+
async retrieve(key) {
|
|
214
|
+
// Try file-based first (where users might have stored it)
|
|
215
|
+
const fileValue = await this.fileStore.retrieve(key);
|
|
216
|
+
if (fileValue) {
|
|
217
|
+
return fileValue;
|
|
218
|
+
}
|
|
219
|
+
// Try keyring if available
|
|
220
|
+
if (this.usePassIfAvailable && this.isPassAvailable()) {
|
|
221
|
+
const passValue = await this.passStore.retrieve(key);
|
|
222
|
+
if (passValue) {
|
|
223
|
+
return passValue;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Delete a secret from both stores
|
|
230
|
+
*/
|
|
231
|
+
async delete(key) {
|
|
232
|
+
try {
|
|
233
|
+
await this.fileStore.delete(key);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
logger.debug(`Failed to delete from file store: ${error}`);
|
|
237
|
+
}
|
|
238
|
+
if (this.usePassIfAvailable && this.isPassAvailable()) {
|
|
239
|
+
try {
|
|
240
|
+
await this.passStore.delete(key);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
logger.debug(`Failed to delete from keyring: ${error}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* List all stored secrets
|
|
249
|
+
*/
|
|
250
|
+
async list() {
|
|
251
|
+
const secrets = new Map();
|
|
252
|
+
// List from file store
|
|
253
|
+
const fileKeys = await this.fileStore.list();
|
|
254
|
+
for (const key of fileKeys) {
|
|
255
|
+
const value = await this.fileStore.retrieve(key);
|
|
256
|
+
if (value) {
|
|
257
|
+
secrets.set(key, `file:${path.join(os.homedir(), '.kaseki', 'secrets', key)}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// List from keyring
|
|
261
|
+
if (this.usePassIfAvailable && this.isPassAvailable()) {
|
|
262
|
+
const passKeys = await this.passStore.list();
|
|
263
|
+
for (const key of passKeys) {
|
|
264
|
+
secrets.set(key, `keyring:${key}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return secrets;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Check if pass is available
|
|
271
|
+
*/
|
|
272
|
+
isPassAvailable() {
|
|
273
|
+
try {
|
|
274
|
+
execSync('command -v pass', { shell: '/bin/bash', stdio: 'ignore' });
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Initialize/setup keyring (interactive)
|
|
283
|
+
*/
|
|
284
|
+
async initializeKeyring() {
|
|
285
|
+
if (!this.isPassAvailable()) {
|
|
286
|
+
throw new Error('pass (password-store) not installed');
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
execSync('pass init 2>&1', { shell: '/bin/bash', stdio: 'inherit' });
|
|
290
|
+
logger.info('Keyring initialized successfully');
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
throw new Error(`Failed to initialize keyring: ${error}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get recommended storage method for system
|
|
298
|
+
*/
|
|
299
|
+
getRecommendedStore() {
|
|
300
|
+
if (this.isPassAvailable()) {
|
|
301
|
+
return 'keyring (pass)';
|
|
302
|
+
}
|
|
303
|
+
return 'file (~/.kaseki/secrets/)';
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=SecretsManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecretsManager.js","sourceRoot":"","sources":["../../src/secrets/SecretsManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared generic test utilities and fixtures for unit and integration tests.
|
|
3
|
+
* Consolidates common test setup patterns to reduce duplication.
|
|
4
|
+
*
|
|
5
|
+
* This module contains reusable test factories and types that can be imported
|
|
6
|
+
* by multiple test files. For API-route-specific test setup, see kaseki-api-routes.test.ts.
|
|
7
|
+
*/
|
|
8
|
+
import type { KasekiApiConfig } from './kaseki-api-config';
|
|
9
|
+
/**
|
|
10
|
+
* Test-specific config type with jest.fn() mocks.
|
|
11
|
+
*/
|
|
12
|
+
export interface TestScheduler {
|
|
13
|
+
getQueueStatus: jest.Mock;
|
|
14
|
+
getReadiness: jest.Mock;
|
|
15
|
+
getJob: jest.Mock;
|
|
16
|
+
submitJob: jest.Mock;
|
|
17
|
+
listJobs: jest.Mock;
|
|
18
|
+
cancelJob: jest.Mock;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Possible job statuses for mock scheduler.
|
|
22
|
+
*/
|
|
23
|
+
export type MockJobStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
24
|
+
/**
|
|
25
|
+
* Mock job object for tests.
|
|
26
|
+
*/
|
|
27
|
+
export interface MockJob {
|
|
28
|
+
id: string;
|
|
29
|
+
status: MockJobStatus;
|
|
30
|
+
createdAt: Date;
|
|
31
|
+
resultDir?: string;
|
|
32
|
+
exitCode?: number;
|
|
33
|
+
failureClass?: string;
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates a mock scheduler with standard behavior for tests.
|
|
38
|
+
* Customize by providing jobData to override default getJob behavior.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* const scheduler = createMockScheduler();
|
|
42
|
+
* scheduler.getReadiness.mockReturnValue({ ready: false, reasons: ['error'] });
|
|
43
|
+
*/
|
|
44
|
+
export declare function createMockScheduler(jobData?: {
|
|
45
|
+
[jobId: string]: MockJob;
|
|
46
|
+
}): TestScheduler;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a standard test configuration object.
|
|
49
|
+
* Pass resultsDir to set the directory; other params use reasonable defaults.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const config = createTestConfig('/tmp/results');
|
|
53
|
+
*/
|
|
54
|
+
export declare function createTestConfig(resultsDir: string): KasekiApiConfig;
|
|
55
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC;IACxB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;IACrB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEzF;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,aAAa,CASzF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAcpE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared generic test utilities and fixtures for unit and integration tests.
|
|
3
|
+
* Consolidates common test setup patterns to reduce duplication.
|
|
4
|
+
*
|
|
5
|
+
* This module contains reusable test factories and types that can be imported
|
|
6
|
+
* by multiple test files. For API-route-specific test setup, see kaseki-api-routes.test.ts.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Creates a mock scheduler with standard behavior for tests.
|
|
10
|
+
* Customize by providing jobData to override default getJob behavior.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const scheduler = createMockScheduler();
|
|
14
|
+
* scheduler.getReadiness.mockReturnValue({ ready: false, reasons: ['error'] });
|
|
15
|
+
*/
|
|
16
|
+
export function createMockScheduler(jobData) {
|
|
17
|
+
return {
|
|
18
|
+
getQueueStatus: jest.fn(() => ({ pending: 0, running: 0, maxConcurrent: 1 })),
|
|
19
|
+
getReadiness: jest.fn(() => ({ ready: true, reasons: [] })),
|
|
20
|
+
getJob: jest.fn((id) => jobData?.[id]),
|
|
21
|
+
submitJob: jest.fn(),
|
|
22
|
+
listJobs: jest.fn(() => []),
|
|
23
|
+
cancelJob: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates a standard test configuration object.
|
|
28
|
+
* Pass resultsDir to set the directory; other params use reasonable defaults.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const config = createTestConfig('/tmp/results');
|
|
32
|
+
*/
|
|
33
|
+
export function createTestConfig(resultsDir) {
|
|
34
|
+
return {
|
|
35
|
+
port: 0,
|
|
36
|
+
apiKeys: ['test-key'],
|
|
37
|
+
resultsDir,
|
|
38
|
+
maxConcurrentRuns: 1,
|
|
39
|
+
defaultTaskMode: 'patch',
|
|
40
|
+
maxDiffBytes: 200000,
|
|
41
|
+
agentTimeoutSeconds: 1200,
|
|
42
|
+
logLevel: 'info',
|
|
43
|
+
artifactCacheMaxEntries: 20,
|
|
44
|
+
artifactCacheTtlMs: 5 * 60 * 1000,
|
|
45
|
+
artifactCacheMaxFileBytes: 10 * 1024 * 1024,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkCH;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAsC;IACxE,OAAO;QACL,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7E,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3D,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE;QACpB,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QAC3B,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO;QACL,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,CAAC,UAAU,CAAC;QACrB,UAAU;QACV,iBAAiB,EAAE,CAAC;QACpB,eAAe,EAAE,OAAgB;QACjC,YAAY,EAAE,MAAM;QACpB,mBAAmB,EAAE,IAAI;QACzB,QAAQ,EAAE,MAAe;QACzB,uBAAuB,EAAE,EAAE;QAC3B,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACjC,yBAAyB,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KAC5C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* timestamp-tracker.ts
|
|
3
|
+
*
|
|
4
|
+
* Encapsulates timestamp tracking logic for Pi event stream processing.
|
|
5
|
+
* Safely parses ISO timestamps, tracks min/max values, and converts to epoch milliseconds.
|
|
6
|
+
*/
|
|
7
|
+
export interface TimestampRange {
|
|
8
|
+
first: string | null;
|
|
9
|
+
last: string | null;
|
|
10
|
+
minEpochMs: number | null;
|
|
11
|
+
maxEpochMs: number | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* TimestampTracker manages timestamp observations from an event stream.
|
|
15
|
+
*
|
|
16
|
+
* Responsibilities:
|
|
17
|
+
* - Parse and record ISO 8601 timestamps
|
|
18
|
+
* - Track first and last observed timestamps (as ISO strings)
|
|
19
|
+
* - Track min/max epoch milliseconds for duration calculation
|
|
20
|
+
* - Provide safe conversion from ISO string to epoch milliseconds
|
|
21
|
+
* - Handle malformed timestamps gracefully
|
|
22
|
+
*/
|
|
23
|
+
export declare class TimestampTracker {
|
|
24
|
+
private first;
|
|
25
|
+
private last;
|
|
26
|
+
private minEpochMs;
|
|
27
|
+
private maxEpochMs;
|
|
28
|
+
/**
|
|
29
|
+
* Convert ISO 8601 string to epoch milliseconds.
|
|
30
|
+
* Returns null if the string cannot be parsed.
|
|
31
|
+
*/
|
|
32
|
+
private parseToEpochMs;
|
|
33
|
+
/**
|
|
34
|
+
* Record an ISO timestamp observation.
|
|
35
|
+
* Safely handles malformed timestamps by ignoring them.
|
|
36
|
+
*/
|
|
37
|
+
record(timestamp: string | null): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get epoch milliseconds for a given ISO timestamp string.
|
|
40
|
+
* Useful for extracting individual timestamp conversions.
|
|
41
|
+
*/
|
|
42
|
+
getEpochMs(timestamp: string | null): number | null;
|
|
43
|
+
/**
|
|
44
|
+
* Get the first recorded timestamp (ISO string).
|
|
45
|
+
* Returns null if no timestamps have been recorded.
|
|
46
|
+
*/
|
|
47
|
+
firstTimestamp(): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Get the last recorded timestamp (ISO string).
|
|
50
|
+
* Returns null if no timestamps have been recorded.
|
|
51
|
+
*/
|
|
52
|
+
lastTimestamp(): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Get the first timestamp as epoch milliseconds.
|
|
55
|
+
* If first timestamp string exists but is malformed, attempts parse; otherwise
|
|
56
|
+
* uses tracked minEpochMs (which may be different if timestamps came from different sources).
|
|
57
|
+
*/
|
|
58
|
+
firstEpochMs(): number | null;
|
|
59
|
+
/**
|
|
60
|
+
* Get the last timestamp as epoch milliseconds.
|
|
61
|
+
* If last timestamp string exists but is malformed, attempts parse; otherwise
|
|
62
|
+
* uses tracked maxEpochMs (which may be different if timestamps came from different sources).
|
|
63
|
+
*/
|
|
64
|
+
lastEpochMs(): number | null;
|
|
65
|
+
/**
|
|
66
|
+
* Calculate duration in milliseconds between first and last recorded epochs.
|
|
67
|
+
* Returns null if either bound is missing or invalid.
|
|
68
|
+
*/
|
|
69
|
+
durationMs(): number | null;
|
|
70
|
+
/**
|
|
71
|
+
* Get complete timestamp range information.
|
|
72
|
+
*/
|
|
73
|
+
range(): TimestampRange;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=timestamp-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timestamp-tracker.d.ts","sourceRoot":"","sources":["../src/timestamp-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,UAAU,CAAuB;IAEzC;;;OAGG;IACH,OAAO,CAAC,cAAc;IAMtB;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAmBtC;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI;IAInD;;;OAGG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;;OAGG;IACH,aAAa,IAAI,MAAM,GAAG,IAAI;IAI9B;;;;OAIG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAM7B;;;;OAIG;IACH,WAAW,IAAI,MAAM,GAAG,IAAI;IAM5B;;;OAGG;IACH,UAAU,IAAI,MAAM,GAAG,IAAI;IAO3B;;OAEG;IACH,KAAK,IAAI,cAAc;CAQxB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* timestamp-tracker.ts
|
|
3
|
+
*
|
|
4
|
+
* Encapsulates timestamp tracking logic for Pi event stream processing.
|
|
5
|
+
* Safely parses ISO timestamps, tracks min/max values, and converts to epoch milliseconds.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* TimestampTracker manages timestamp observations from an event stream.
|
|
9
|
+
*
|
|
10
|
+
* Responsibilities:
|
|
11
|
+
* - Parse and record ISO 8601 timestamps
|
|
12
|
+
* - Track first and last observed timestamps (as ISO strings)
|
|
13
|
+
* - Track min/max epoch milliseconds for duration calculation
|
|
14
|
+
* - Provide safe conversion from ISO string to epoch milliseconds
|
|
15
|
+
* - Handle malformed timestamps gracefully
|
|
16
|
+
*/
|
|
17
|
+
export class TimestampTracker {
|
|
18
|
+
first = null;
|
|
19
|
+
last = null;
|
|
20
|
+
minEpochMs = null;
|
|
21
|
+
maxEpochMs = null;
|
|
22
|
+
/**
|
|
23
|
+
* Convert ISO 8601 string to epoch milliseconds.
|
|
24
|
+
* Returns null if the string cannot be parsed.
|
|
25
|
+
*/
|
|
26
|
+
parseToEpochMs(timestamp) {
|
|
27
|
+
if (!timestamp)
|
|
28
|
+
return null;
|
|
29
|
+
const epochMs = Date.parse(timestamp);
|
|
30
|
+
return Number.isFinite(epochMs) ? epochMs : null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Record an ISO timestamp observation.
|
|
34
|
+
* Safely handles malformed timestamps by ignoring them.
|
|
35
|
+
*/
|
|
36
|
+
record(timestamp) {
|
|
37
|
+
if (!timestamp)
|
|
38
|
+
return;
|
|
39
|
+
// Track first and last as ISO strings
|
|
40
|
+
if (this.first === null) {
|
|
41
|
+
this.first = timestamp;
|
|
42
|
+
}
|
|
43
|
+
this.last = timestamp;
|
|
44
|
+
// Track min/max as epoch milliseconds for duration calculation
|
|
45
|
+
const epochMs = this.parseToEpochMs(timestamp);
|
|
46
|
+
if (epochMs !== null) {
|
|
47
|
+
this.minEpochMs =
|
|
48
|
+
this.minEpochMs === null ? epochMs : Math.min(this.minEpochMs, epochMs);
|
|
49
|
+
this.maxEpochMs =
|
|
50
|
+
this.maxEpochMs === null ? epochMs : Math.max(this.maxEpochMs, epochMs);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get epoch milliseconds for a given ISO timestamp string.
|
|
55
|
+
* Useful for extracting individual timestamp conversions.
|
|
56
|
+
*/
|
|
57
|
+
getEpochMs(timestamp) {
|
|
58
|
+
return this.parseToEpochMs(timestamp);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get the first recorded timestamp (ISO string).
|
|
62
|
+
* Returns null if no timestamps have been recorded.
|
|
63
|
+
*/
|
|
64
|
+
firstTimestamp() {
|
|
65
|
+
return this.first;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the last recorded timestamp (ISO string).
|
|
69
|
+
* Returns null if no timestamps have been recorded.
|
|
70
|
+
*/
|
|
71
|
+
lastTimestamp() {
|
|
72
|
+
return this.last;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the first timestamp as epoch milliseconds.
|
|
76
|
+
* If first timestamp string exists but is malformed, attempts parse; otherwise
|
|
77
|
+
* uses tracked minEpochMs (which may be different if timestamps came from different sources).
|
|
78
|
+
*/
|
|
79
|
+
firstEpochMs() {
|
|
80
|
+
if (this.minEpochMs !== null)
|
|
81
|
+
return this.minEpochMs;
|
|
82
|
+
if (this.first !== null)
|
|
83
|
+
return this.parseToEpochMs(this.first);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the last timestamp as epoch milliseconds.
|
|
88
|
+
* If last timestamp string exists but is malformed, attempts parse; otherwise
|
|
89
|
+
* uses tracked maxEpochMs (which may be different if timestamps came from different sources).
|
|
90
|
+
*/
|
|
91
|
+
lastEpochMs() {
|
|
92
|
+
if (this.maxEpochMs !== null)
|
|
93
|
+
return this.maxEpochMs;
|
|
94
|
+
if (this.last !== null)
|
|
95
|
+
return this.parseToEpochMs(this.last);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Calculate duration in milliseconds between first and last recorded epochs.
|
|
100
|
+
* Returns null if either bound is missing or invalid.
|
|
101
|
+
*/
|
|
102
|
+
durationMs() {
|
|
103
|
+
const first = this.firstEpochMs();
|
|
104
|
+
const last = this.lastEpochMs();
|
|
105
|
+
if (first === null || last === null)
|
|
106
|
+
return null;
|
|
107
|
+
return Math.max(0, last - first);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get complete timestamp range information.
|
|
111
|
+
*/
|
|
112
|
+
range() {
|
|
113
|
+
return {
|
|
114
|
+
first: this.first,
|
|
115
|
+
last: this.last,
|
|
116
|
+
minEpochMs: this.minEpochMs,
|
|
117
|
+
maxEpochMs: this.maxEpochMs,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=timestamp-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timestamp-tracker.js","sourceRoot":"","sources":["../src/timestamp-tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Job } from '../kaseki-api-types';
|
|
2
|
+
export type CleanupResult = {
|
|
3
|
+
attempted: boolean;
|
|
4
|
+
ok?: boolean;
|
|
5
|
+
detail?: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Handles writing failure artifacts (failure.json, analysis.md, result-summary.md, etc.)
|
|
9
|
+
* when a job fails before complete diagnostics are available.
|
|
10
|
+
*/
|
|
11
|
+
export declare class FailureArtifactWriter {
|
|
12
|
+
private resultsDir;
|
|
13
|
+
constructor(resultsDir: string);
|
|
14
|
+
/**
|
|
15
|
+
* Write API finalization artifacts when job fails before container diagnostics.
|
|
16
|
+
*/
|
|
17
|
+
writeFailureArtifacts(job: Job, cleanup: CleanupResult, options?: {
|
|
18
|
+
stdoutTail?: Buffer<ArrayBufferLike>;
|
|
19
|
+
stderrTail?: Buffer<ArrayBufferLike>;
|
|
20
|
+
lastStage?: string;
|
|
21
|
+
}): void;
|
|
22
|
+
private writeFailureJson;
|
|
23
|
+
private writeResultSummary;
|
|
24
|
+
private writeAnalysis;
|
|
25
|
+
private writeMetadata;
|
|
26
|
+
private writeStderrLog;
|
|
27
|
+
private decodeUtf8Tail;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=failure-artifact-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failure-artifact-writer.d.ts","sourceRoot":"","sources":["../../src/utils/failure-artifact-writer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,qBAAa,qBAAqB;IACpB,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,MAAM;IAEtC;;OAEG;IACH,qBAAqB,CACnB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3G,IAAI;IAoBP,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,aAAa;IAyCrB,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,cAAc;CAIvB"}
|