@atolis-hq/wake 0.2.97 → 0.3.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/README.md +5 -5
- package/dist/src/activities/agent/agent-activity-definition.js +26 -0
- package/dist/src/activities/agent/agent-activity.js +171 -0
- package/dist/src/activities/agent/agent-result.js +149 -0
- package/dist/src/activities/contracts/activity.js +10 -0
- package/dist/src/activities/contracts/config.js +2 -0
- package/dist/src/activities/contracts/event-schema.js +302 -0
- package/dist/src/activities/contracts/events.js +42 -0
- package/dist/src/activities/contracts/identifiers.js +29 -0
- package/dist/src/activities/contracts/registry.js +71 -0
- package/dist/src/activities/contracts/streams.js +17 -0
- package/dist/src/activities/contracts/vocabulary.js +58 -0
- package/dist/src/activities/index.js +21 -0
- package/dist/src/activities/pr/activity-support.js +111 -0
- package/dist/src/activities/pr/application.js +158 -0
- package/dist/src/activities/pr/approve.js +85 -0
- package/dist/src/activities/pr/capability.js +11 -0
- package/dist/src/activities/pr/decision-claim.js +76 -0
- package/dist/src/activities/pr/event-drafts.js +66 -0
- package/dist/src/activities/pr/intent.js +37 -0
- package/dist/src/activities/pr/merge-authority-gate.js +14 -0
- package/dist/src/activities/pr/merge.js +110 -0
- package/dist/src/activities/pr/policy.js +135 -0
- package/dist/src/activities/pr/projection.js +130 -0
- package/dist/src/activities/pr/vocabulary.js +30 -0
- package/dist/src/activities/review/authorization.js +22 -0
- package/dist/src/activities/review/contracts.js +22 -0
- package/dist/src/activities/review/signals.js +3 -0
- package/dist/src/bootstrap/analytics-projection.js +26 -0
- package/dist/src/bootstrap/board-projection.js +337 -0
- package/dist/src/bootstrap/composition-root.js +382 -0
- package/dist/src/bootstrap/config/load-config.js +51 -0
- package/dist/src/bootstrap/config/root-schema.js +134 -0
- package/dist/src/bootstrap/external-ref.js +12 -0
- package/dist/src/bootstrap/fake-provider-files.js +44 -0
- package/dist/src/bootstrap/fake-scenarios.js +22 -0
- package/dist/src/bootstrap/index.js +48 -0
- package/dist/src/bootstrap/initialise.js +436 -0
- package/dist/src/bootstrap/paths.js +15 -0
- package/dist/src/bootstrap/projection-runtime.js +27 -0
- package/dist/src/bootstrap/runner-quota-reporter.js +21 -0
- package/dist/src/bootstrap/runner-registry.js +30 -0
- package/dist/src/bootstrap/schedule-checkpoint-store.js +49 -0
- package/dist/src/bootstrap/self-update-application.js +195 -0
- package/dist/src/bootstrap/self-update-failure-log.js +33 -0
- package/dist/src/bootstrap/source-update-port.js +47 -0
- package/dist/src/bootstrap/status-publish-activity.js +42 -0
- package/dist/src/bootstrap/surface-api-applications.js +325 -0
- package/dist/src/bootstrap/surface-api-execution-applications.js +95 -0
- package/dist/src/bootstrap/surface-api-metadata.js +12 -0
- package/dist/src/bootstrap/surface-api-projection-pages.js +22 -0
- package/dist/src/bootstrap/surface-api-run-context.js +5 -0
- package/dist/src/bootstrap/surface-api-transcripts.js +57 -0
- package/dist/src/bootstrap/surface-api-work-applications.js +199 -0
- package/dist/src/bootstrap/surface-applications.js +7 -0
- package/dist/src/bootstrap/surface-cli-applications.js +701 -0
- package/dist/src/bootstrap/update-ledger.js +61 -0
- package/dist/src/bootstrap/update-maintenance-lease.js +176 -0
- package/dist/src/{version.js → bootstrap/version.js} +35 -51
- package/dist/src/control-plane/application/advance-once.js +184 -0
- package/dist/src/control-plane/application/control-plane-projection.js +42 -0
- package/dist/src/control-plane/application/control-plane-service.js +42 -0
- package/dist/src/control-plane/application/intake-pipeline.js +29 -0
- package/dist/src/control-plane/application/runner-control-service.js +66 -0
- package/dist/src/control-plane/application/runner-pipeline.js +57 -0
- package/dist/src/control-plane/application/schedule-service.js +47 -0
- package/dist/src/control-plane/application/work-cancellation-policy.js +31 -0
- package/dist/src/control-plane/contracts/commands.js +10 -0
- package/dist/src/control-plane/contracts/config.js +22 -0
- package/dist/src/control-plane/contracts/events.js +81 -0
- package/dist/src/control-plane/contracts/streams.js +5 -0
- package/dist/src/control-plane/domain/dispatch-policy.js +15 -0
- package/dist/src/control-plane/domain/quota-policy.js +26 -0
- package/dist/src/control-plane/domain/runner-quota.js +35 -0
- package/dist/src/control-plane/domain/schedule-policy.js +46 -0
- package/dist/src/control-plane/index.js +20 -0
- package/dist/src/control-plane/infrastructure/intake-host.js +24 -0
- package/dist/src/control-plane/infrastructure/resident-host.js +45 -0
- package/dist/src/control-plane/infrastructure/tick-host.js +35 -0
- package/dist/src/execution/application/activation-claim.js +50 -0
- package/dist/src/execution/application/active-run-cancellation.js +14 -0
- package/dist/src/execution/application/execution-activity.js +97 -0
- package/dist/src/execution/application/execution-projection.js +17 -0
- package/dist/src/execution/application/execution-service.js +372 -0
- package/dist/src/execution/application/execution-validation.js +26 -0
- package/dist/src/execution/application/recovery-service.js +212 -0
- package/dist/src/execution/application/run-lifecycle.js +115 -0
- package/dist/src/execution/application/run-liveness-service.js +80 -0
- package/dist/src/execution/application/run-repository.js +27 -0
- package/dist/src/execution/contracts/commands.js +1 -0
- package/dist/src/execution/contracts/config.js +35 -0
- package/dist/src/execution/contracts/control-plane.js +1 -0
- package/dist/src/execution/contracts/event-factory.js +53 -0
- package/dist/src/execution/contracts/events.js +274 -0
- package/dist/src/execution/contracts/identifiers.js +5 -0
- package/dist/src/execution/contracts/liveness.js +1 -0
- package/dist/src/execution/contracts/results.js +1 -0
- package/dist/src/execution/contracts/runner.js +15 -0
- package/dist/src/execution/contracts/streams.js +10 -0
- package/dist/src/execution/contracts/views.js +1 -0
- package/dist/src/execution/contracts/vocabulary.js +43 -0
- package/dist/src/execution/contracts/workspace.js +1 -0
- package/dist/src/execution/domain/run-result.js +34 -0
- package/dist/src/execution/domain/run.js +142 -0
- package/dist/src/execution/index.js +31 -0
- package/dist/src/execution/infrastructure/agent-runner-adapter.js +114 -0
- package/dist/src/execution/infrastructure/process-execution.js +29 -0
- package/dist/src/execution/infrastructure/prompt-templates.js +42 -0
- package/dist/src/execution/infrastructure/runners/claude.js +120 -0
- package/dist/src/execution/infrastructure/runners/codex.js +143 -0
- package/dist/src/execution/infrastructure/runners/command.js +4 -0
- package/dist/src/execution/infrastructure/runners/cursor.js +69 -0
- package/dist/src/execution/infrastructure/runners/fake-scenarios.js +99 -0
- package/dist/src/execution/infrastructure/runners/fake.js +65 -0
- package/dist/src/execution/infrastructure/runners/registry.js +26 -0
- package/dist/src/execution/infrastructure/transcript-store.js +223 -0
- package/dist/src/execution/infrastructure/transcripts.js +11 -0
- package/dist/src/execution/infrastructure/workspace/fake-workspace.js +19 -0
- package/dist/src/execution/infrastructure/workspace/git-workspace.js +241 -0
- package/dist/src/integrations/application/agent-run-publication-reactor.js +111 -0
- package/dist/src/integrations/application/artifact-registration-reactor.js +159 -0
- package/dist/src/integrations/application/poll-service.js +25 -0
- package/dist/src/integrations/application/terminal-agent-run-report.js +40 -0
- package/dist/src/integrations/application/work-admission.js +31 -0
- package/dist/src/integrations/application/work-conclusion.js +19 -0
- package/dist/src/integrations/contracts/artifact-events.js +60 -0
- package/dist/src/integrations/contracts/artifact-vocabulary.js +9 -0
- package/dist/src/integrations/contracts/config.js +14 -0
- package/dist/src/integrations/contracts/identifiers.js +5 -0
- package/dist/src/integrations/contracts/intake-rules.js +14 -0
- package/dist/src/integrations/contracts/intake.js +1 -0
- package/dist/src/integrations/contracts/outcome-vocabulary.js +7 -0
- package/dist/src/integrations/contracts/provider.js +37 -0
- package/dist/src/integrations/contracts/streams.js +10 -0
- package/dist/src/integrations/delivery/application/delivery-outcome-reactor.js +75 -0
- package/dist/src/integrations/delivery/application/delivery-projector.js +165 -0
- package/dist/src/integrations/delivery/application/delivery-service.js +173 -0
- package/dist/src/integrations/delivery/contracts/commands.js +1 -0
- package/dist/src/integrations/delivery/contracts/config.js +1 -0
- package/dist/src/integrations/delivery/contracts/event-factory.js +18 -0
- package/dist/src/integrations/delivery/contracts/events.js +86 -0
- package/dist/src/integrations/delivery/contracts/intents.js +89 -0
- package/dist/src/integrations/delivery/contracts/views.js +1 -0
- package/dist/src/integrations/delivery/contracts/vocabulary.js +22 -0
- package/dist/src/integrations/fake/durable-delivery-provider.js +48 -0
- package/dist/src/integrations/fake/external-sink.js +9 -0
- package/dist/src/integrations/fake/external-source.js +44 -0
- package/dist/src/integrations/fake/inbound-translator.js +130 -0
- package/dist/src/integrations/fake/provider.js +95 -0
- package/dist/src/integrations/github/application/agent-context-reader.js +54 -0
- package/dist/src/integrations/github/application/agent-run-comment.js +94 -0
- package/dist/src/integrations/github/application/comment-history-reader.js +43 -0
- package/dist/src/integrations/github/application/inbound-context.js +10 -0
- package/dist/src/integrations/github/application/inbound-review-signals.js +159 -0
- package/dist/src/integrations/github/application/inbound-translator.js +231 -0
- package/dist/src/integrations/github/application/inbound-watch-gate-signals.js +84 -0
- package/dist/src/integrations/github/application/intake-policy.js +23 -0
- package/dist/src/integrations/github/application/outbound-translator.js +47 -0
- package/dist/src/integrations/github/application/poll-service.js +29 -0
- package/dist/src/integrations/github/application/pull-request-translation.js +10 -0
- package/dist/src/integrations/github/application/resource-links.js +8 -0
- package/dist/src/integrations/github/application/review-command-translator.js +16 -0
- package/dist/src/integrations/github/application/wake-labels.js +95 -0
- package/dist/src/integrations/github/contracts/config.js +47 -0
- package/dist/src/integrations/github/contracts/events.js +127 -0
- package/dist/src/integrations/github/contracts/external-key.js +19 -0
- package/dist/src/integrations/github/contracts/payloads.js +9 -0
- package/dist/src/integrations/github/contracts/vocabulary.js +55 -0
- package/dist/src/integrations/github/index.js +31 -0
- package/dist/src/integrations/github/infrastructure/client-reads.js +214 -0
- package/dist/src/integrations/github/infrastructure/client.js +132 -0
- package/dist/src/integrations/github/infrastructure/content-fingerprint.js +10 -0
- package/dist/src/integrations/github/infrastructure/delivery.js +31 -0
- package/dist/src/integrations/github/infrastructure/etag-cache.js +56 -0
- package/dist/src/integrations/github/infrastructure/gh-auth.js +19 -0
- package/dist/src/integrations/github/infrastructure/issue-source.js +109 -0
- package/dist/src/integrations/github/infrastructure/pr-source.js +186 -0
- package/dist/src/integrations/github/infrastructure/review-source.js +70 -0
- package/dist/src/integrations/github/infrastructure/source.js +108 -0
- package/dist/src/integrations/github/provider.js +96 -0
- package/dist/src/integrations/index.js +30 -0
- package/dist/src/kernel/contracts/checkpoint-store.js +1 -0
- package/dist/src/kernel/contracts/clock.js +1 -0
- package/dist/src/kernel/contracts/commands.js +1 -0
- package/dist/src/kernel/contracts/event-journal.js +2 -0
- package/dist/src/kernel/contracts/event-schema.js +54 -0
- package/dist/src/kernel/contracts/events.js +11 -0
- package/dist/src/kernel/contracts/id-generator.js +1 -0
- package/dist/src/kernel/contracts/identifiers.js +8 -0
- package/dist/src/kernel/contracts/projection-store.js +1 -0
- package/dist/src/kernel/contracts/relations.js +1 -0
- package/dist/src/kernel/contracts/schema.js +17 -0
- package/dist/src/kernel/contracts/vocabulary.js +6 -0
- package/dist/src/kernel/domain/event-envelope.js +29 -0
- package/dist/src/kernel/domain/match-mode.js +11 -0
- package/dist/src/kernel/domain/relation.js +10 -0
- package/dist/src/kernel/index.js +17 -0
- package/dist/src/{lib/clock.js → kernel/infrastructure/system-clock.js} +3 -3
- package/dist/src/kernel/infrastructure/ulid-id-generator.js +9 -0
- package/dist/src/main.js +137 -1030
- package/dist/src/orchestration/application/accept-activity-outcome.js +25 -0
- package/dist/src/orchestration/application/accept-signal.js +35 -0
- package/dist/src/orchestration/application/advance-workflow.js +160 -0
- package/dist/src/orchestration/application/coordination-claims.js +107 -0
- package/dist/src/orchestration/application/group-budget-recorder.js +43 -0
- package/dist/src/orchestration/application/orchestration-projection.js +20 -0
- package/dist/src/orchestration/application/orchestration-repository.js +36 -0
- package/dist/src/orchestration/application/orchestration-service.js +82 -0
- package/dist/src/orchestration/application/request-child.js +118 -0
- package/dist/src/orchestration/application/signal-reactor.js +17 -0
- package/dist/src/orchestration/application/start-workflow.js +51 -0
- package/dist/src/orchestration/application/watch-reactor.js +82 -0
- package/dist/src/orchestration/contracts/activity-outcome.js +18 -0
- package/dist/src/orchestration/contracts/commands.js +1 -0
- package/dist/src/orchestration/contracts/config.js +128 -0
- package/dist/src/orchestration/contracts/event-decoder.js +263 -0
- package/dist/src/orchestration/contracts/events.js +41 -0
- package/dist/src/orchestration/contracts/identifiers.js +35 -0
- package/dist/src/orchestration/contracts/streams.js +38 -0
- package/dist/src/orchestration/contracts/views.js +1 -0
- package/dist/src/orchestration/contracts/vocabulary.js +30 -0
- package/dist/src/orchestration/domain/activation-policy.js +55 -0
- package/dist/src/orchestration/domain/approval-defaults.js +17 -0
- package/dist/src/orchestration/domain/child-policy.js +63 -0
- package/dist/src/orchestration/domain/compiler.js +162 -0
- package/dist/src/orchestration/domain/coordination-events.js +25 -0
- package/dist/src/orchestration/domain/decision-events.js +47 -0
- package/dist/src/orchestration/domain/interpreter.js +49 -0
- package/dist/src/orchestration/domain/operator-retry-policy.js +34 -0
- package/dist/src/orchestration/domain/retry-policy.js +26 -0
- package/dist/src/orchestration/domain/signal-policy.js +120 -0
- package/dist/src/orchestration/domain/supplemental-policy.js +61 -0
- package/dist/src/orchestration/domain/transition.js +55 -0
- package/dist/src/orchestration/domain/workflow-graph.js +41 -0
- package/dist/src/orchestration/domain/workflow-instance-events.js +236 -0
- package/dist/src/orchestration/domain/workflow-instance.js +41 -0
- package/dist/src/orchestration/domain/workflow-selector.js +21 -0
- package/dist/src/orchestration/index.js +19 -0
- package/dist/src/persistence/application/projection-runner.js +79 -0
- package/dist/src/persistence/filesystem/file-checkpoint-store.js +35 -0
- package/dist/src/persistence/filesystem/file-event-journal.js +143 -0
- package/dist/src/persistence/filesystem/file-lock.js +91 -0
- package/dist/src/persistence/filesystem/file-projection-store.js +64 -0
- package/dist/src/persistence/index.js +8 -0
- package/dist/src/persistence/memory/in-memory-checkpoint-store.js +14 -0
- package/dist/src/persistence/memory/in-memory-event-journal.js +88 -0
- package/dist/src/persistence/memory/in-memory-projection-store.js +17 -0
- package/dist/src/resources/application/lookup-projections.js +48 -0
- package/dist/src/resources/application/resource-lookup.js +16 -0
- package/dist/src/resources/application/resource-projections.js +81 -0
- package/dist/src/resources/application/resource-repository.js +18 -0
- package/dist/src/resources/application/resource-service.js +83 -0
- package/dist/src/resources/contracts/commands.js +1 -0
- package/dist/src/resources/contracts/config.js +2 -0
- package/dist/src/resources/contracts/events.js +83 -0
- package/dist/src/resources/contracts/identifiers.js +15 -0
- package/dist/src/resources/contracts/streams.js +6 -0
- package/dist/src/resources/contracts/views.js +1 -0
- package/dist/src/resources/contracts/vocabulary.js +67 -0
- package/dist/src/resources/domain/correlation.js +8 -0
- package/dist/src/resources/domain/resource.js +58 -0
- package/dist/src/resources/index.js +14 -0
- package/dist/src/surfaces/api/contracts/activities.js +1 -0
- package/dist/src/surfaces/api/contracts/board.js +2 -0
- package/dist/src/surfaces/api/contracts/common.js +46 -0
- package/dist/src/surfaces/api/contracts/control-plane.js +5 -0
- package/dist/src/surfaces/api/contracts/events.js +1 -0
- package/dist/src/surfaces/api/contracts/execution.js +1 -0
- package/dist/src/surfaces/api/contracts/index.js +13 -0
- package/dist/src/surfaces/api/contracts/observability.js +1 -0
- package/dist/src/surfaces/api/contracts/orchestration.js +1 -0
- package/dist/src/surfaces/api/contracts/resources.js +1 -0
- package/dist/src/surfaces/api/contracts/status.js +1 -0
- package/dist/src/surfaces/api/contracts/system.js +1 -0
- package/dist/src/surfaces/api/contracts/transport-values.js +39 -0
- package/dist/src/surfaces/api/contracts/work.js +17 -0
- package/dist/src/surfaces/api/http-server.js +121 -0
- package/dist/src/surfaces/api/presenters/activities.js +1 -0
- package/dist/src/surfaces/api/presenters/board.js +3 -0
- package/dist/src/surfaces/api/presenters/control-plane.js +1 -0
- package/dist/src/surfaces/api/presenters/events.js +1 -0
- package/dist/src/surfaces/api/presenters/execution.js +59 -0
- package/dist/src/surfaces/api/presenters/observability.js +1 -0
- package/dist/src/surfaces/api/presenters/orchestration.js +19 -0
- package/dist/src/surfaces/api/presenters/resources.js +15 -0
- package/dist/src/surfaces/api/presenters/status.js +3 -0
- package/dist/src/surfaces/api/presenters/system.js +14 -0
- package/dist/src/surfaces/api/presenters/work.js +16 -0
- package/dist/src/surfaces/api/problem-details.js +9 -0
- package/dist/src/surfaces/api/router.js +13 -0
- package/dist/src/surfaces/api/routes/activities.js +1 -0
- package/dist/src/surfaces/api/routes/applications.js +1 -0
- package/dist/src/surfaces/api/routes/commands.js +82 -0
- package/dist/src/surfaces/api/routes/control-plane.js +6 -0
- package/dist/src/surfaces/api/routes/events.js +1 -0
- package/dist/src/surfaces/api/routes/execution.js +8 -0
- package/dist/src/surfaces/api/routes/index.js +18 -0
- package/dist/src/surfaces/api/routes/observability.js +1 -0
- package/dist/src/surfaces/api/routes/orchestration.js +1 -0
- package/dist/src/surfaces/api/routes/pagination.js +78 -0
- package/dist/src/surfaces/api/routes/read.js +135 -0
- package/dist/src/surfaces/api/routes/resources.js +1 -0
- package/dist/src/surfaces/api/routes/responses.js +67 -0
- package/dist/src/surfaces/api/routes/system.js +1 -0
- package/dist/src/surfaces/api/routes/work.js +9 -0
- package/dist/src/surfaces/cli/commands/api.js +1 -0
- package/dist/src/surfaces/cli/commands/audit.js +10 -0
- package/dist/src/surfaces/cli/commands/correlate.js +2 -0
- package/dist/src/surfaces/cli/commands/doctor.js +6 -0
- package/dist/src/surfaces/cli/commands/init.js +39 -0
- package/dist/src/surfaces/cli/commands/sandbox-entrypoint.js +33 -0
- package/dist/src/surfaces/cli/commands/sandbox-setup.js +29 -0
- package/dist/src/surfaces/cli/commands/sandbox.js +105 -0
- package/dist/src/surfaces/cli/commands/self-update.js +38 -0
- package/dist/src/surfaces/cli/commands/smoke.js +16 -0
- package/dist/src/surfaces/cli/commands/start.js +1 -0
- package/dist/src/surfaces/cli/commands/stop.js +13 -0
- package/dist/src/surfaces/cli/commands/tick.js +1 -0
- package/dist/src/surfaces/cli/commands/ui.js +2 -0
- package/dist/src/surfaces/cli/commands/validate-state.js +5 -0
- package/dist/src/surfaces/cli/infrastructure/docker-cli.js +221 -0
- package/dist/src/surfaces/cli/infrastructure/process-log.js +86 -0
- package/dist/src/surfaces/cli/main.js +140 -0
- package/dist/src/surfaces/cli/usage.js +33 -0
- package/dist/src/surfaces/contracts/config.js +34 -0
- package/dist/src/surfaces/index.js +47 -0
- package/dist/src/surfaces/web-assets/assets/index-Bfn4FwZG.css +1 -0
- package/dist/src/surfaces/web-assets/assets/index-ipB6JPGU.js +1090 -0
- package/dist/src/surfaces/web-assets/index.html +13 -0
- package/dist/src/surfaces/web-host/asset-source.js +1 -0
- package/dist/src/surfaces/web-host/packaged-assets.js +44 -0
- package/dist/src/work/application/work-projection.js +59 -0
- package/dist/src/work/application/work-repository.js +18 -0
- package/dist/src/work/application/work-service.js +117 -0
- package/dist/src/work/contracts/commands.js +1 -0
- package/dist/src/work/contracts/config.js +2 -0
- package/dist/src/work/contracts/events.js +103 -0
- package/dist/src/work/contracts/identifiers.js +5 -0
- package/dist/src/work/contracts/streams.js +6 -0
- package/dist/src/work/contracts/views.js +1 -0
- package/dist/src/work/contracts/vocabulary.js +6 -0
- package/dist/src/work/domain/work-item.js +89 -0
- package/dist/src/work/index.js +11 -0
- package/docker/Dockerfile +10 -6
- package/docker/Dockerfile.packaged +3 -3
- package/package.json +29 -4
- package/prompts/implement.md +2 -2
- package/dist/src/adapters/claude/claude-runner.js +0 -529
- package/dist/src/adapters/codex/codex-runner.js +0 -503
- package/dist/src/adapters/cursor/cursor-runner.js +0 -418
- package/dist/src/adapters/docker/docker-cli.js +0 -150
- package/dist/src/adapters/fake/fake-artifact-verifier.js +0 -14
- package/dist/src/adapters/fake/fake-github-pull-request-activity-source.js +0 -77
- package/dist/src/adapters/fake/fake-resource-index.js +0 -21
- package/dist/src/adapters/fake/fake-runner.js +0 -77
- package/dist/src/adapters/fake/fake-ticketing-system.js +0 -185
- package/dist/src/adapters/fake/fake-workspace-manager.js +0 -81
- package/dist/src/adapters/fs/resource-index.js +0 -126
- package/dist/src/adapters/fs/self-update-ledger.js +0 -17
- package/dist/src/adapters/fs/state-store.js +0 -775
- package/dist/src/adapters/git/git-workspace-manager.js +0 -289
- package/dist/src/adapters/github/github-artifact-verifier.js +0 -38
- package/dist/src/adapters/github/github-auth.js +0 -16
- package/dist/src/adapters/github/github-client.js +0 -249
- package/dist/src/adapters/github/github-etag-cache.js +0 -57
- package/dist/src/adapters/github/github-issues-work-source.js +0 -692
- package/dist/src/adapters/github/github-pull-request-activity-source.js +0 -584
- package/dist/src/adapters/github/github-pull-request-merge-actor.js +0 -45
- package/dist/src/adapters/http/ui-assets.js +0 -1188
- package/dist/src/adapters/http/ui-data.js +0 -1107
- package/dist/src/adapters/http/ui-server.js +0 -458
- package/dist/src/adapters/runner/cli-command.js +0 -73
- package/dist/src/adapters/runner/prompt-templates.js +0 -76
- package/dist/src/adapters/runner/runner-cli-adapter.js +0 -112
- package/dist/src/adapters/runner/runner-registry.js +0 -139
- package/dist/src/adapters/runner/runtime-events.js +0 -32
- package/dist/src/adapters/runner/stage-prompt.js +0 -268
- package/dist/src/adapters/runner/transcripts.js +0 -25
- package/dist/src/cli/audit-command.js +0 -36
- package/dist/src/cli/correlate-command.js +0 -62
- package/dist/src/cli/doctor-command.js +0 -48
- package/dist/src/cli/init-command.js +0 -18
- package/dist/src/cli/sandbox-command.js +0 -258
- package/dist/src/cli/sandbox-entrypoint-command.js +0 -88
- package/dist/src/cli/sandbox-exec-logging.js +0 -7
- package/dist/src/cli/sandbox-resume.js +0 -79
- package/dist/src/cli/sandbox-setup-command.js +0 -31
- package/dist/src/cli/scaffold-assets.js +0 -100
- package/dist/src/cli/self-update-command.js +0 -198
- package/dist/src/cli/startup-preflight.js +0 -134
- package/dist/src/cli/stop-command.js +0 -46
- package/dist/src/cli/ui-command.js +0 -27
- package/dist/src/config/defaults.js +0 -10
- package/dist/src/config/discover-config-files.js +0 -11
- package/dist/src/config/load-config.js +0 -69
- package/dist/src/config/split-config.js +0 -14
- package/dist/src/core/active-run-recovery.js +0 -44
- package/dist/src/core/approval-intents.js +0 -16
- package/dist/src/core/audit-events.js +0 -82
- package/dist/src/core/control-plane.js +0 -192
- package/dist/src/core/event-builders.js +0 -153
- package/dist/src/core/event-resolver.js +0 -249
- package/dist/src/core/lifecycle-service.js +0 -8
- package/dist/src/core/live-execution.js +0 -81
- package/dist/src/core/outbox.js +0 -198
- package/dist/src/core/policy-engine.js +0 -389
- package/dist/src/core/projection-updater.js +0 -693
- package/dist/src/core/quota-backoff.js +0 -69
- package/dist/src/core/run-lease.js +0 -38
- package/dist/src/core/scheduled-workflow-source.js +0 -199
- package/dist/src/core/sink-router.js +0 -107
- package/dist/src/core/stale-run-reconciler.js +0 -352
- package/dist/src/core/tick-runner.js +0 -2442
- package/dist/src/core/workspace-cleanup.js +0 -117
- package/dist/src/domain/branch-naming.js +0 -14
- package/dist/src/domain/custom-commands.js +0 -58
- package/dist/src/domain/event-types.js +0 -158
- package/dist/src/domain/manual-labels.js +0 -1
- package/dist/src/domain/resource-uri.js +0 -38
- package/dist/src/domain/runner-routing.js +0 -127
- package/dist/src/domain/runtime-events.js +0 -36
- package/dist/src/domain/schema.js +0 -1233
- package/dist/src/domain/sources.js +0 -16
- package/dist/src/domain/stages.js +0 -36
- package/dist/src/domain/work-item-labels.js +0 -48
- package/dist/src/domain/work-item-lifecycle.js +0 -10
- package/dist/src/domain/work-item-status.js +0 -33
- package/dist/src/domain/workflows.js +0 -159
- package/dist/src/lib/deep-merge.js +0 -14
- package/dist/src/lib/detached-process-logging.js +0 -46
- package/dist/src/lib/event-log.js +0 -21
- package/dist/src/lib/format.js +0 -41
- package/dist/src/lib/json-file.js +0 -23
- package/dist/src/lib/lock.js +0 -181
- package/dist/src/lib/log-rotation.js +0 -42
- package/dist/src/lib/paths.js +0 -52
- package/dist/src/lib/process-identity.js +0 -54
- package/dist/src/lib/state-health.js +0 -30
- package/dist/src/lib/work-id.js +0 -19
- package/dist/src/lib/yaml-file.js +0 -20
- package/templates/SETUP.md +0 -115
- /package/dist/src/{core → activities/pr}/contracts.js +0 -0
- /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
export function createUpdateLedger(wakeRoot) {
|
|
4
|
+
const path = join(wakeRoot, '.wake', 'update-ledger.json');
|
|
5
|
+
return {
|
|
6
|
+
async read() {
|
|
7
|
+
return (await readState(path)).lastHealthyTag ?? null;
|
|
8
|
+
},
|
|
9
|
+
async begin(tag) {
|
|
10
|
+
const state = await readState(path);
|
|
11
|
+
await writeState(path, { ...state, pendingTag: tag });
|
|
12
|
+
},
|
|
13
|
+
async write(tag) {
|
|
14
|
+
const state = await readState(path);
|
|
15
|
+
await writeState(path, {
|
|
16
|
+
lastHealthyTag: tag,
|
|
17
|
+
...(state.badTags === undefined ? {} : { badTags: state.badTags }),
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
async isBad(tag) {
|
|
21
|
+
return (await readState(path)).badTags?.includes(tag) ?? false;
|
|
22
|
+
},
|
|
23
|
+
async recordBad(tag) {
|
|
24
|
+
const state = await readState(path);
|
|
25
|
+
await writeState(path, { ...state, badTags: [...new Set([...(state.badTags ?? []), tag])] });
|
|
26
|
+
},
|
|
27
|
+
async recover() {
|
|
28
|
+
const state = await readState(path);
|
|
29
|
+
if (state.pendingTag === undefined)
|
|
30
|
+
return null;
|
|
31
|
+
await writeState(path, {
|
|
32
|
+
...(state.lastHealthyTag === undefined ? {} : { lastHealthyTag: state.lastHealthyTag }),
|
|
33
|
+
...(state.badTags === undefined ? {} : { badTags: state.badTags }),
|
|
34
|
+
});
|
|
35
|
+
return state.lastHealthyTag ?? null;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function readState(path) {
|
|
40
|
+
try {
|
|
41
|
+
const value = JSON.parse(await readFile(path, 'utf8'));
|
|
42
|
+
return {
|
|
43
|
+
...(typeof value.lastHealthyTag === 'string' ? { lastHealthyTag: value.lastHealthyTag } : {}),
|
|
44
|
+
...(typeof value.pendingTag === 'string' ? { pendingTag: value.pendingTag } : {}),
|
|
45
|
+
...(Array.isArray(value.badTags) && value.badTags.every((tag) => typeof tag === 'string')
|
|
46
|
+
? { badTags: value.badTags }
|
|
47
|
+
: {}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (error.code === 'ENOENT')
|
|
52
|
+
return {};
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function writeState(path, state) {
|
|
57
|
+
await mkdir(dirname(path), { recursive: true });
|
|
58
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
59
|
+
await writeFile(temporary, `${JSON.stringify(state)}\n`, 'utf8');
|
|
60
|
+
await rename(temporary, path);
|
|
61
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { defineClosedVocabulary } from '../kernel/index.js';
|
|
5
|
+
import { acquireFileLock } from '../persistence/index.js';
|
|
6
|
+
export const UpdateMaintenancePhase = defineClosedVocabulary({
|
|
7
|
+
Quiescing: 'quiescing',
|
|
8
|
+
Updating: 'updating',
|
|
9
|
+
RollingBack: 'rolling-back',
|
|
10
|
+
Failed: 'failed',
|
|
11
|
+
});
|
|
12
|
+
export function createUpdateMaintenanceLease(wakeRoot, now = () => new Date().toISOString(), createAttemptId = randomUUID, isProcessAlive) {
|
|
13
|
+
const path = join(wakeRoot, '.wake', 'update-maintenance.json');
|
|
14
|
+
const acquire = async (tag, retryFailed = false) => withLeaseLock(path, async () => {
|
|
15
|
+
const existing = await readState(path);
|
|
16
|
+
if (existing !== null &&
|
|
17
|
+
!(existing.phase === UpdateMaintenancePhase.Failed && (existing.tag !== tag || retryFailed)))
|
|
18
|
+
return existing;
|
|
19
|
+
const initial = {
|
|
20
|
+
attemptId: createAttemptId(),
|
|
21
|
+
tag,
|
|
22
|
+
phase: UpdateMaintenancePhase.Quiescing,
|
|
23
|
+
startedAt: now(),
|
|
24
|
+
};
|
|
25
|
+
await writeState(path, initial);
|
|
26
|
+
return initial;
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
async read() {
|
|
30
|
+
return readState(path);
|
|
31
|
+
},
|
|
32
|
+
acquire,
|
|
33
|
+
async runExclusive(tag, retryFailed, operation) {
|
|
34
|
+
return withAttemptLock(path, isProcessAlive, async () => operation(await acquire(tag, retryFailed)));
|
|
35
|
+
},
|
|
36
|
+
async transition(phase, attemptId) {
|
|
37
|
+
return withLeaseLock(path, async () => {
|
|
38
|
+
const current = await requireState(path);
|
|
39
|
+
requireOwnership(current, attemptId);
|
|
40
|
+
if (!canTransition(current.phase, phase)) {
|
|
41
|
+
throw new Error(`Invalid maintenance lease transition from ${current.phase} to ${phase}`);
|
|
42
|
+
}
|
|
43
|
+
const next = { ...current, phase };
|
|
44
|
+
await writeState(path, next);
|
|
45
|
+
return next;
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
async fail(error, attemptId) {
|
|
49
|
+
return withLeaseLock(path, async () => {
|
|
50
|
+
const current = await requireState(path);
|
|
51
|
+
requireOwnership(current, attemptId);
|
|
52
|
+
if (current.phase === UpdateMaintenancePhase.Failed)
|
|
53
|
+
return current;
|
|
54
|
+
const next = {
|
|
55
|
+
...current,
|
|
56
|
+
phase: UpdateMaintenancePhase.Failed,
|
|
57
|
+
failure: error instanceof Error ? error.message : String(error),
|
|
58
|
+
};
|
|
59
|
+
await writeState(path, next);
|
|
60
|
+
return next;
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
async clear(attemptId) {
|
|
64
|
+
await withLeaseLock(path, async () => {
|
|
65
|
+
const current = await readState(path);
|
|
66
|
+
if (current === null) {
|
|
67
|
+
if (attemptId !== undefined)
|
|
68
|
+
throw new Error('No maintenance lease is active');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
requireOwnership(current, attemptId);
|
|
72
|
+
await rm(path, { force: true });
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function requireOwnership(state, attemptId) {
|
|
78
|
+
if (attemptId !== undefined && state.attemptId !== attemptId)
|
|
79
|
+
throw new Error(`Maintenance attempt ${attemptId} no longer owns the lease`);
|
|
80
|
+
}
|
|
81
|
+
function canTransition(from, to) {
|
|
82
|
+
return ((from === UpdateMaintenancePhase.Quiescing && to === UpdateMaintenancePhase.Updating) ||
|
|
83
|
+
(from === UpdateMaintenancePhase.Updating && to === UpdateMaintenancePhase.RollingBack));
|
|
84
|
+
}
|
|
85
|
+
async function requireState(path) {
|
|
86
|
+
const state = await readState(path);
|
|
87
|
+
if (state === null)
|
|
88
|
+
throw new Error('No maintenance lease is active');
|
|
89
|
+
return state;
|
|
90
|
+
}
|
|
91
|
+
async function readState(path) {
|
|
92
|
+
try {
|
|
93
|
+
return parseState(JSON.parse(await readFile(path, 'utf8')));
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error.code === 'ENOENT')
|
|
97
|
+
return null;
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function parseState(value) {
|
|
102
|
+
if (typeof value !== 'object' ||
|
|
103
|
+
value === null ||
|
|
104
|
+
typeof value.attemptId !== 'string' ||
|
|
105
|
+
typeof value.tag !== 'string' ||
|
|
106
|
+
!isPhase(value.phase) ||
|
|
107
|
+
typeof value.startedAt !== 'string' ||
|
|
108
|
+
('failure' in value && typeof value.failure !== 'string')) {
|
|
109
|
+
throw new Error('Invalid maintenance lease state');
|
|
110
|
+
}
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
function isPhase(value) {
|
|
114
|
+
return (value === UpdateMaintenancePhase.Quiescing ||
|
|
115
|
+
value === UpdateMaintenancePhase.Updating ||
|
|
116
|
+
value === UpdateMaintenancePhase.RollingBack ||
|
|
117
|
+
value === UpdateMaintenancePhase.Failed);
|
|
118
|
+
}
|
|
119
|
+
async function writeState(path, state) {
|
|
120
|
+
await mkdir(dirname(path), { recursive: true });
|
|
121
|
+
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
122
|
+
await writeFile(temporary, `${JSON.stringify(state)}\n`, 'utf8');
|
|
123
|
+
await rename(temporary, path);
|
|
124
|
+
}
|
|
125
|
+
async function withLeaseLock(path, operation) {
|
|
126
|
+
const lockPath = `${path}.lock`;
|
|
127
|
+
while (true) {
|
|
128
|
+
let lock;
|
|
129
|
+
try {
|
|
130
|
+
lock = await acquireFileLock(lockPath, { staleAfterMs: 60_000 });
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (error.code !== 'EPERM')
|
|
134
|
+
throw error;
|
|
135
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (lock.acquired) {
|
|
139
|
+
try {
|
|
140
|
+
return await operation();
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await lock.release();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function withAttemptLock(path, isProcessAlive, operation) {
|
|
150
|
+
const lockPath = `${path}.attempt.lock`;
|
|
151
|
+
while (true) {
|
|
152
|
+
let lock;
|
|
153
|
+
try {
|
|
154
|
+
lock = await acquireFileLock(lockPath, {
|
|
155
|
+
staleAfterMs: 60_000,
|
|
156
|
+
staleRequiresDeadProcess: true,
|
|
157
|
+
...(isProcessAlive === undefined ? {} : { isProcessAlive }),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (error.code !== 'EPERM')
|
|
162
|
+
throw error;
|
|
163
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (lock.acquired) {
|
|
167
|
+
try {
|
|
168
|
+
return await operation();
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
await lock.release();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -2,7 +2,7 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
const defaultRepoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
5
|
+
const defaultRepoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
6
6
|
function gitOutputFromRoot(repoRoot, args) {
|
|
7
7
|
try {
|
|
8
8
|
return execFileSync('git', args, {
|
|
@@ -24,104 +24,88 @@ function defaultReadTextFile(path) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
function defaultListTextFiles(path) {
|
|
27
|
-
if (!existsSync(path))
|
|
27
|
+
if (!existsSync(path))
|
|
28
28
|
return [];
|
|
29
|
-
}
|
|
30
29
|
const files = [];
|
|
31
30
|
for (const entry of readdirSync(path, { withFileTypes: true })) {
|
|
32
31
|
const entryPath = resolve(path, entry.name);
|
|
33
|
-
if (entry.isDirectory())
|
|
32
|
+
if (entry.isDirectory())
|
|
34
33
|
files.push(...defaultListTextFiles(entryPath));
|
|
35
|
-
}
|
|
36
34
|
else if (entry.isFile()) {
|
|
37
35
|
const content = defaultReadTextFile(entryPath);
|
|
38
|
-
if (content !== undefined)
|
|
36
|
+
if (content !== undefined)
|
|
39
37
|
files.push({ path: entryPath, content });
|
|
40
|
-
}
|
|
41
38
|
}
|
|
42
39
|
}
|
|
43
40
|
return files;
|
|
44
41
|
}
|
|
45
42
|
function currentHeadHash(repoRoot, readTextFile) {
|
|
46
43
|
const head = readTextFile(resolve(repoRoot, '.git', 'HEAD'))?.trim();
|
|
47
|
-
if (head === undefined || head.length === 0)
|
|
44
|
+
if (head === undefined || head.length === 0)
|
|
48
45
|
return '';
|
|
49
|
-
|
|
50
|
-
if (!head.startsWith('ref: ')) {
|
|
46
|
+
if (!head.startsWith('ref: '))
|
|
51
47
|
return head;
|
|
52
|
-
|
|
53
|
-
const refPath = head.slice('ref: '.length).trim();
|
|
54
|
-
return readTextFile(resolve(repoRoot, '.git', ...refPath.split('/')))?.trim() ?? '';
|
|
48
|
+
return (readTextFile(resolve(repoRoot, '.git', ...head.slice('ref: '.length).trim().split('/')))?.trim() ?? '');
|
|
55
49
|
}
|
|
56
|
-
function
|
|
50
|
+
function exactTagFromGitFiles(repoRoot, readTextFile, listTextFiles) {
|
|
51
|
+
const headHash = currentHeadHash(repoRoot, readTextFile);
|
|
52
|
+
if (headHash.length === 0)
|
|
53
|
+
return '';
|
|
57
54
|
const tagsRoot = resolve(repoRoot, '.git', 'refs', 'tags');
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
const root = tagsRoot.replaceAll('\\', '/');
|
|
56
|
+
const looseTags = listTextFiles(tagsRoot).map((file) => ({
|
|
57
|
+
name: file.path.replaceAll('\\', '/').slice(root.length + 1),
|
|
60
58
|
hash: file.content.trim(),
|
|
61
59
|
}));
|
|
60
|
+
return ([...looseTags, ...packedTagRefs(repoRoot, readTextFile)].find((tag) => tag.hash === headHash)
|
|
61
|
+
?.name ?? '');
|
|
62
62
|
}
|
|
63
63
|
function packedTagRefs(repoRoot, readTextFile) {
|
|
64
64
|
const packedRefs = readTextFile(resolve(repoRoot, '.git', 'packed-refs'));
|
|
65
|
-
if (packedRefs === undefined)
|
|
65
|
+
if (packedRefs === undefined)
|
|
66
66
|
return [];
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
let previousTag;
|
|
67
|
+
const tags = [];
|
|
68
|
+
let precedingTag;
|
|
70
69
|
for (const line of packedRefs.split(/\r?\n/)) {
|
|
71
|
-
if (line.length === 0 || line.startsWith('#'))
|
|
70
|
+
if (line.length === 0 || line.startsWith('#'))
|
|
72
71
|
continue;
|
|
73
|
-
}
|
|
74
72
|
if (line.startsWith('^')) {
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
}
|
|
73
|
+
if (precedingTag !== undefined)
|
|
74
|
+
precedingTag.hash = line.slice(1).trim();
|
|
78
75
|
continue;
|
|
79
76
|
}
|
|
80
|
-
|
|
77
|
+
precedingTag = undefined;
|
|
81
78
|
const [hash, ref] = line.split(' ');
|
|
82
79
|
if (hash !== undefined && ref?.startsWith('refs/tags/') === true) {
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
precedingTag = { name: ref.slice('refs/tags/'.length), hash };
|
|
81
|
+
tags.push(precedingTag);
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
function exactTagFromGitFiles(repoRoot, readTextFile, listTextFiles) {
|
|
90
|
-
const headHash = currentHeadHash(repoRoot, readTextFile);
|
|
91
|
-
if (headHash.length === 0) {
|
|
92
|
-
return '';
|
|
93
|
-
}
|
|
94
|
-
const matchingTag = [
|
|
95
|
-
...looseTagRefs(repoRoot, listTextFiles),
|
|
96
|
-
...packedTagRefs(repoRoot, readTextFile),
|
|
97
|
-
].find((tag) => tag.hash === headHash);
|
|
98
|
-
return matchingTag?.name ?? '';
|
|
84
|
+
return tags;
|
|
99
85
|
}
|
|
86
|
+
// Mirrors legacy src/version.ts: exact tag at HEAD, else latest tag + short hash, else
|
|
87
|
+
// short hash, else a dev placeholder. Packaged installs get a literal value baked in at
|
|
88
|
+
// build time by scripts/embed-version.mjs, so the git plumbing here only runs from source.
|
|
100
89
|
export function resolveWakeVersion(options = {}) {
|
|
101
90
|
const repoRoot = options.repoRoot ?? defaultRepoRoot;
|
|
102
91
|
const gitOutput = options.gitOutput ?? ((args) => gitOutputFromRoot(repoRoot, args));
|
|
103
92
|
const readTextFile = options.readTextFile ?? defaultReadTextFile;
|
|
104
93
|
const listTextFiles = options.listTextFiles ?? defaultListTextFiles;
|
|
105
94
|
const exactTag = gitOutput(['describe', '--tags', '--exact-match', 'HEAD']);
|
|
106
|
-
if (exactTag.length > 0)
|
|
95
|
+
if (exactTag.length > 0)
|
|
107
96
|
return exactTag;
|
|
108
|
-
}
|
|
109
97
|
const exactFileTag = exactTagFromGitFiles(repoRoot, readTextFile, listTextFiles);
|
|
110
|
-
if (exactFileTag.length > 0)
|
|
98
|
+
if (exactFileTag.length > 0)
|
|
111
99
|
return exactFileTag;
|
|
112
|
-
}
|
|
113
100
|
const latestTag = gitOutput(['describe', '--tags', '--abbrev=0']);
|
|
114
101
|
const shortHash = gitOutput(['rev-parse', '--short', 'HEAD']);
|
|
115
|
-
if (latestTag.length > 0 && shortHash.length > 0)
|
|
102
|
+
if (latestTag.length > 0 && shortHash.length > 0)
|
|
116
103
|
return `${latestTag}+g${shortHash}`;
|
|
117
|
-
|
|
118
|
-
if (shortHash.length > 0) {
|
|
104
|
+
if (shortHash.length > 0)
|
|
119
105
|
return `g${shortHash}`;
|
|
120
|
-
}
|
|
121
106
|
const headHash = currentHeadHash(repoRoot, readTextFile);
|
|
122
|
-
if (headHash.length > 0)
|
|
107
|
+
if (headHash.length > 0)
|
|
123
108
|
return `g${headHash.slice(0, 7)}`;
|
|
124
|
-
}
|
|
125
109
|
return '0.1.0-dev';
|
|
126
110
|
}
|
|
127
|
-
export const wakeVersion = "
|
|
111
|
+
export const wakeVersion = "g9e7311e";
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { RunStatus, WorkspaceMode } from '../../execution/index.js';
|
|
2
|
+
import { correlationId, EventActorKind, } from '../../kernel/index.js';
|
|
3
|
+
import { WorkflowStatus } from '../../orchestration/index.js';
|
|
4
|
+
import { WorkStatus } from '../../work/index.js';
|
|
5
|
+
import { ControlStreamKind } from '../contracts/streams.js';
|
|
6
|
+
import { DispatchPolicy } from '../domain/dispatch-policy.js';
|
|
7
|
+
export function createAdvanceOnce(orchestration, execution, resources, clock, dependencies) {
|
|
8
|
+
const runnerIneligibility = dependencies.runnerIneligibility ?? (async () => new Set());
|
|
9
|
+
const isDispatchPaused = dependencies.isDispatchPaused ?? (async () => false);
|
|
10
|
+
const workspaceRecovery = dependencies.workspaceRecovery;
|
|
11
|
+
const transcriptRetention = dependencies.transcriptRetention;
|
|
12
|
+
const dispatchPolicy = dependencies.dispatchPolicy ?? new DispatchPolicy({ maxDispatches: 1 });
|
|
13
|
+
const context = (cause) => ({
|
|
14
|
+
commandId: dependencies.ids.next('command'),
|
|
15
|
+
correlationId: correlationId(cause),
|
|
16
|
+
occurredAt: clock.now().toISOString(),
|
|
17
|
+
actor: { kind: EventActorKind.System, id: ControlStreamKind.Global },
|
|
18
|
+
});
|
|
19
|
+
return async (options) => {
|
|
20
|
+
if (options.maxProgress < 1)
|
|
21
|
+
return { kind: 'exhausted', progressCount: 0 };
|
|
22
|
+
if (await isDispatchPaused())
|
|
23
|
+
return { kind: 'paused' };
|
|
24
|
+
if (workspaceRecovery !== undefined) {
|
|
25
|
+
await workspaceRecovery.recover(await execution.list(), {
|
|
26
|
+
isPaused: isDispatchPaused,
|
|
27
|
+
retainWorkItem: async (workItemId) => {
|
|
28
|
+
const work = await dependencies.work?.get(workItemId);
|
|
29
|
+
return work?.state === WorkStatus.Open && work.deleted !== true;
|
|
30
|
+
},
|
|
31
|
+
onWorkspaceReclaimed: async (workItemId) => {
|
|
32
|
+
if (await isDispatchPaused())
|
|
33
|
+
return false;
|
|
34
|
+
const work = await dependencies.work?.get(workItemId);
|
|
35
|
+
if (work?.state !== WorkStatus.Closed)
|
|
36
|
+
return true;
|
|
37
|
+
try {
|
|
38
|
+
return (await transcriptRetention?.markClosedWorkItem(workItemId)) ?? true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (await isDispatchPaused())
|
|
47
|
+
return { kind: 'paused' };
|
|
48
|
+
await execution.recoverActive?.(ControlStreamKind.Global);
|
|
49
|
+
if (await isDispatchPaused())
|
|
50
|
+
return { kind: 'paused' };
|
|
51
|
+
if (transcriptRetention !== undefined) {
|
|
52
|
+
for (const workItemId of (await dependencies.closedWorkItemIds?.()) ?? []) {
|
|
53
|
+
if (await isDispatchPaused())
|
|
54
|
+
return { kind: 'paused' };
|
|
55
|
+
try {
|
|
56
|
+
await transcriptRetention.markClosedWorkItem(workItemId);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Retention is operational filesystem maintenance, not Run lifecycle state.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (await isDispatchPaused())
|
|
64
|
+
return { kind: 'paused' };
|
|
65
|
+
try {
|
|
66
|
+
await transcriptRetention?.sweep();
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Retention is operational filesystem maintenance, not Run lifecycle state.
|
|
70
|
+
}
|
|
71
|
+
if (await isDispatchPaused())
|
|
72
|
+
return { kind: 'paused' };
|
|
73
|
+
await orchestration.reconcileChildCompletions(context('child-completion-reconciliation'));
|
|
74
|
+
if (await isDispatchPaused())
|
|
75
|
+
return { kind: 'paused' };
|
|
76
|
+
const rawPending = await orchestration.listPendingActivations(options.workItemId);
|
|
77
|
+
const pending = (await Promise.all(rawPending.map(async (candidate) => {
|
|
78
|
+
const work = await dependencies.work?.get(candidate.workflow.workItemId);
|
|
79
|
+
return work?.frozen || work?.deleted ? null : candidate;
|
|
80
|
+
}))).filter((candidate) => candidate !== null);
|
|
81
|
+
const blocked = ((await orchestration.listAll?.()) ?? []).flatMap((workflow) => workflow.status === WorkflowStatus.Blocked &&
|
|
82
|
+
workflow.pendingActivation !== undefined &&
|
|
83
|
+
(options.workItemId === undefined || workflow.workItemId === options.workItemId)
|
|
84
|
+
? [{ workflow, activation: workflow.pendingActivation }]
|
|
85
|
+
: []);
|
|
86
|
+
const recovery = await findUnresolvedTerminal([...pending, ...blocked], execution);
|
|
87
|
+
if (recovery !== undefined) {
|
|
88
|
+
if (await isDispatchPaused())
|
|
89
|
+
return { kind: 'paused' };
|
|
90
|
+
if (recovery.run.status === RunStatus.Succeeded) {
|
|
91
|
+
await orchestration.acceptOutcome({
|
|
92
|
+
workflowInstanceId: recovery.item.workflow.workflowInstanceId,
|
|
93
|
+
activationId: recovery.item.activation.activationId,
|
|
94
|
+
outcome: recovery.run.outcome,
|
|
95
|
+
}, context(recovery.run.runId));
|
|
96
|
+
return {
|
|
97
|
+
kind: 'progressed',
|
|
98
|
+
activationId: recovery.item.activation.activationId,
|
|
99
|
+
runId: recovery.run.runId,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
await orchestration.resolveExecutionFailure?.(recovery.item.workflow.workflowInstanceId, {
|
|
103
|
+
activationId: recovery.item.activation.activationId,
|
|
104
|
+
runId: recovery.run.runId,
|
|
105
|
+
reason: recovery.run.failure?.message ?? 'execution failed',
|
|
106
|
+
}, context(recovery.run.runId));
|
|
107
|
+
return {
|
|
108
|
+
kind: WorkflowStatus.Blocked,
|
|
109
|
+
workflowInstanceId: recovery.item.workflow.workflowInstanceId,
|
|
110
|
+
reason: recovery.run.failure?.message ?? 'execution failed',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const allRuns = await execution.list();
|
|
114
|
+
const selectedCandidate = dispatchPolicy.select(await Promise.all(pending.map(async (item, requestedPosition) => ({
|
|
115
|
+
workItemId: item.workflow.workItemId,
|
|
116
|
+
activationId: item.activation.activationId,
|
|
117
|
+
requestedPosition,
|
|
118
|
+
hasActiveRun: (await execution.list(item.activation.activationId)).some((run) => run.status === RunStatus.Started) ||
|
|
119
|
+
allRuns.some((run) => run.status === RunStatus.Started &&
|
|
120
|
+
run.workflowInstanceId === item.workflow.workflowInstanceId &&
|
|
121
|
+
run.workspace?.mode === WorkspaceMode.Branch),
|
|
122
|
+
cancelled: false,
|
|
123
|
+
}))))[0];
|
|
124
|
+
const selected = selectedCandidate === undefined
|
|
125
|
+
? undefined
|
|
126
|
+
: pending.find((item) => item.activation.activationId === selectedCandidate.activationId);
|
|
127
|
+
if (selected === undefined) {
|
|
128
|
+
const waiting = (await orchestration.listWaiting()).find((view) => view !== null);
|
|
129
|
+
return waiting === undefined
|
|
130
|
+
? { kind: 'no-work' }
|
|
131
|
+
: { kind: WorkflowStatus.Waiting, workflowInstanceId: waiting.workflowInstanceId };
|
|
132
|
+
}
|
|
133
|
+
// Recheck at the dispatch boundary so maintenance cannot race a selected activation.
|
|
134
|
+
if (await isDispatchPaused())
|
|
135
|
+
return { kind: 'paused' };
|
|
136
|
+
await orchestration.markActivationStarted(selected.workflow.workflowInstanceId, selected.activation.activationId, context(selected.activation.activationId));
|
|
137
|
+
const correlated = await resources.correlationsForWork(selected.workflow.workItemId);
|
|
138
|
+
const resourceViews = (await Promise.all(correlated.map((entry) => resources.get(entry.resourceId)))).filter((resource) => resource !== null);
|
|
139
|
+
const ineligible = await runnerIneligibility();
|
|
140
|
+
const run = await execution.attempt(selected.activation, {
|
|
141
|
+
workItemId: selected.workflow.workItemId,
|
|
142
|
+
workflowInstanceId: selected.workflow.workflowInstanceId,
|
|
143
|
+
orchestrationGroupId: selected.workflow.orchestrationGroupId,
|
|
144
|
+
resources: resourceViews,
|
|
145
|
+
sessionPolicy: selected.workflow.parentWorkflowInstanceId === undefined ? 'resume-stage' : 'fresh',
|
|
146
|
+
awaitImmediateCompletion: true,
|
|
147
|
+
...(ineligible.size === 0 ? {} : { ineligibleRunners: ineligible }),
|
|
148
|
+
});
|
|
149
|
+
if (run.status === RunStatus.Succeeded && run.outcome !== undefined) {
|
|
150
|
+
if (await isDispatchPaused())
|
|
151
|
+
return { kind: 'paused' };
|
|
152
|
+
await orchestration.acceptOutcome({
|
|
153
|
+
workflowInstanceId: selected.workflow.workflowInstanceId,
|
|
154
|
+
activationId: selected.activation.activationId,
|
|
155
|
+
outcome: run.outcome,
|
|
156
|
+
}, context(run.runId));
|
|
157
|
+
}
|
|
158
|
+
if (isExecutionFailureTerminal(run.status))
|
|
159
|
+
await orchestration.resolveExecutionFailure?.(selected.workflow.workflowInstanceId, {
|
|
160
|
+
activationId: selected.activation.activationId,
|
|
161
|
+
runId: run.runId,
|
|
162
|
+
reason: run.failure?.message ?? 'execution failed',
|
|
163
|
+
}, context(run.runId));
|
|
164
|
+
return run.status === RunStatus.Succeeded || run.status === RunStatus.Started
|
|
165
|
+
? { kind: 'progressed', activationId: selected.activation.activationId, runId: run.runId }
|
|
166
|
+
: {
|
|
167
|
+
kind: WorkflowStatus.Blocked,
|
|
168
|
+
workflowInstanceId: selected.workflow.workflowInstanceId,
|
|
169
|
+
reason: run.failure?.message ?? 'execution failed',
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function findUnresolvedTerminal(pending, execution) {
|
|
174
|
+
for (const item of pending) {
|
|
175
|
+
const run = (await execution.list(item.activation.activationId)).find((candidate) => (candidate.status === RunStatus.Succeeded && candidate.outcome !== undefined) ||
|
|
176
|
+
isExecutionFailureTerminal(candidate.status));
|
|
177
|
+
if (run !== undefined && !item.workflow.acceptedOutcomes.includes(item.activation.activationId))
|
|
178
|
+
return { item, run };
|
|
179
|
+
}
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
function isExecutionFailureTerminal(status) {
|
|
183
|
+
return (status === RunStatus.Failed || status === RunStatus.Cancelled || status === RunStatus.Ambiguous);
|
|
184
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ControlEventType, selectControlEvent } from '../contracts/events.js';
|
|
2
|
+
import { ControlStreamKind } from '../contracts/streams.js';
|
|
3
|
+
export function ineligibleRunners(view, now) {
|
|
4
|
+
const current = Date.parse(now);
|
|
5
|
+
return new Set(Object.entries(view.runnerPauses)
|
|
6
|
+
.filter(([, pause]) => pause.resumeAt === undefined || Date.parse(pause.resumeAt) > current)
|
|
7
|
+
.map(([runnerName]) => runnerName));
|
|
8
|
+
}
|
|
9
|
+
export const controlPlaneProjection = {
|
|
10
|
+
name: ControlStreamKind.Global,
|
|
11
|
+
select(event) {
|
|
12
|
+
return selectControlEvent(event) === null ? null : { key: 'global' };
|
|
13
|
+
},
|
|
14
|
+
initial: () => ({ pausedUntil: null, runnerPauses: {} }),
|
|
15
|
+
project(previous, envelope) {
|
|
16
|
+
const event = selectControlEvent(envelope);
|
|
17
|
+
if (event === null)
|
|
18
|
+
return previous;
|
|
19
|
+
switch (event.eventType) {
|
|
20
|
+
case ControlEventType.DispatchPaused:
|
|
21
|
+
return { ...previous, pausedUntil: event.payload.resumeAt, reason: event.payload.reason };
|
|
22
|
+
case ControlEventType.DispatchResumed:
|
|
23
|
+
return withoutDispatchPause(previous);
|
|
24
|
+
case ControlEventType.RunnerPaused:
|
|
25
|
+
return {
|
|
26
|
+
...previous,
|
|
27
|
+
runnerPauses: { ...previous.runnerPauses, [event.payload.runnerName]: event.payload },
|
|
28
|
+
};
|
|
29
|
+
case ControlEventType.RunnerResumed: {
|
|
30
|
+
const { [event.payload.runnerName]: _, ...runnerPauses } = previous.runnerPauses;
|
|
31
|
+
return { ...previous, runnerPauses };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
function withoutDispatchPause(previous) {
|
|
37
|
+
const { reason: _, ...rest } = previous;
|
|
38
|
+
return { ...rest, pausedUntil: null };
|
|
39
|
+
}
|
|
40
|
+
export const controlPlaneProjectionDefinitions = [
|
|
41
|
+
controlPlaneProjection,
|
|
42
|
+
];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EventActorKind, correlationId, } from '../../kernel/index.js';
|
|
2
|
+
import { ControlEventType, createControlEventDraft, selectControlEvent, } from '../contracts/events.js';
|
|
3
|
+
import { controlPlaneStream } from '../contracts/streams.js';
|
|
4
|
+
export function createControlPlaneService(input) {
|
|
5
|
+
return {
|
|
6
|
+
pause: (key) => change(input, key, 'pause'),
|
|
7
|
+
resume: (key) => change(input, key, 'resume'),
|
|
8
|
+
async isPaused() {
|
|
9
|
+
let paused = false;
|
|
10
|
+
for (const envelope of await input.journal.readStream(controlPlaneStream())) {
|
|
11
|
+
const event = selectControlEvent(envelope);
|
|
12
|
+
if (event?.eventType === ControlEventType.DispatchPaused)
|
|
13
|
+
paused = true;
|
|
14
|
+
if (event?.eventType === ControlEventType.DispatchResumed)
|
|
15
|
+
paused = false;
|
|
16
|
+
}
|
|
17
|
+
return paused;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async function change(input, idempotencyKey, operation) {
|
|
22
|
+
const stream = controlPlaneStream();
|
|
23
|
+
const events = await input.journal.readStream(stream);
|
|
24
|
+
const eventType = operation === 'pause' ? ControlEventType.DispatchPaused : ControlEventType.DispatchResumed;
|
|
25
|
+
const correlation = correlationId(`control:${operation}:${idempotencyKey}`);
|
|
26
|
+
if (events.some((event) => event.eventType === eventType && event.correlationId === correlation))
|
|
27
|
+
return;
|
|
28
|
+
const currentlyPaused = await createControlPlaneService(input).isPaused();
|
|
29
|
+
if ((operation === 'pause' && currentlyPaused) || (operation === 'resume' && !currentlyPaused))
|
|
30
|
+
return;
|
|
31
|
+
const occurredAt = input.clock.now().toISOString();
|
|
32
|
+
const context = {
|
|
33
|
+
commandId: input.ids.next('command'),
|
|
34
|
+
correlationId: correlation,
|
|
35
|
+
occurredAt,
|
|
36
|
+
actor: { kind: EventActorKind.Operator, id: 'web' },
|
|
37
|
+
};
|
|
38
|
+
const event = operation === 'pause'
|
|
39
|
+
? createControlEventDraft(ControlEventType.DispatchPaused, { resumeAt: '9999-12-31T23:59:59.999Z', reason: 'paused by operator' }, context)
|
|
40
|
+
: createControlEventDraft(ControlEventType.DispatchResumed, { resumedAt: occurredAt }, context);
|
|
41
|
+
await input.journal.append(stream, events.length, [event]);
|
|
42
|
+
}
|