@telora/daemon 0.12.33
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/.env.example +64 -0
- package/README.md +229 -0
- package/build-info.json +4 -0
- package/dist/activity-tracker.d.ts +13 -0
- package/dist/activity-tracker.d.ts.map +1 -0
- package/dist/activity-tracker.js +19 -0
- package/dist/activity-tracker.js.map +1 -0
- package/dist/agent-state.d.ts +45 -0
- package/dist/agent-state.d.ts.map +1 -0
- package/dist/agent-state.js +61 -0
- package/dist/agent-state.js.map +1 -0
- package/dist/audit-hooks.d.ts +12 -0
- package/dist/audit-hooks.d.ts.map +1 -0
- package/dist/audit-hooks.js +45 -0
- package/dist/audit-hooks.js.map +1 -0
- package/dist/auto-update.d.ts +42 -0
- package/dist/auto-update.d.ts.map +1 -0
- package/dist/auto-update.js +96 -0
- package/dist/auto-update.js.map +1 -0
- package/dist/branch-status.d.ts +40 -0
- package/dist/branch-status.d.ts.map +1 -0
- package/dist/branch-status.js +107 -0
- package/dist/branch-status.js.map +1 -0
- package/dist/completion-detector.d.ts +87 -0
- package/dist/completion-detector.d.ts.map +1 -0
- package/dist/completion-detector.js +160 -0
- package/dist/completion-detector.js.map +1 -0
- package/dist/completion-handler.d.ts +48 -0
- package/dist/completion-handler.d.ts.map +1 -0
- package/dist/completion-handler.js +200 -0
- package/dist/completion-handler.js.map +1 -0
- package/dist/condition-evaluators.d.ts +31 -0
- package/dist/condition-evaluators.d.ts.map +1 -0
- package/dist/condition-evaluators.js +416 -0
- package/dist/condition-evaluators.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +311 -0
- package/dist/config.js.map +1 -0
- package/dist/control-state.d.ts +41 -0
- package/dist/control-state.d.ts.map +1 -0
- package/dist/control-state.js +204 -0
- package/dist/control-state.js.map +1 -0
- package/dist/crash-recovery-cleanup.d.ts +21 -0
- package/dist/crash-recovery-cleanup.d.ts.map +1 -0
- package/dist/crash-recovery-cleanup.js +198 -0
- package/dist/crash-recovery-cleanup.js.map +1 -0
- package/dist/crash-recovery-scan.d.ts +19 -0
- package/dist/crash-recovery-scan.d.ts.map +1 -0
- package/dist/crash-recovery-scan.js +145 -0
- package/dist/crash-recovery-scan.js.map +1 -0
- package/dist/crash-recovery-types.d.ts +54 -0
- package/dist/crash-recovery-types.d.ts.map +1 -0
- package/dist/crash-recovery-types.js +13 -0
- package/dist/crash-recovery-types.js.map +1 -0
- package/dist/crash-recovery.d.ts +88 -0
- package/dist/crash-recovery.d.ts.map +1 -0
- package/dist/crash-recovery.js +448 -0
- package/dist/crash-recovery.js.map +1 -0
- package/dist/daemon-logs.d.ts +19 -0
- package/dist/daemon-logs.d.ts.map +1 -0
- package/dist/daemon-logs.js +81 -0
- package/dist/daemon-logs.js.map +1 -0
- package/dist/daemon-process.d.ts +154 -0
- package/dist/daemon-process.d.ts.map +1 -0
- package/dist/daemon-process.js +427 -0
- package/dist/daemon-process.js.map +1 -0
- package/dist/dag-validator.d.ts +52 -0
- package/dist/dag-validator.d.ts.map +1 -0
- package/dist/dag-validator.js +199 -0
- package/dist/dag-validator.js.map +1 -0
- package/dist/delivery-guards.d.ts +41 -0
- package/dist/delivery-guards.d.ts.map +1 -0
- package/dist/delivery-guards.js +195 -0
- package/dist/delivery-guards.js.map +1 -0
- package/dist/delivery-lifecycle.d.ts +110 -0
- package/dist/delivery-lifecycle.d.ts.map +1 -0
- package/dist/delivery-lifecycle.js +353 -0
- package/dist/delivery-lifecycle.js.map +1 -0
- package/dist/delivery-merge.d.ts +17 -0
- package/dist/delivery-merge.d.ts.map +1 -0
- package/dist/delivery-merge.js +89 -0
- package/dist/delivery-merge.js.map +1 -0
- package/dist/dependency-resolver.d.ts +77 -0
- package/dist/dependency-resolver.d.ts.map +1 -0
- package/dist/dependency-resolver.js +337 -0
- package/dist/dependency-resolver.js.map +1 -0
- package/dist/evaluation-context.d.ts +49 -0
- package/dist/evaluation-context.d.ts.map +1 -0
- package/dist/evaluation-context.js +98 -0
- package/dist/evaluation-context.js.map +1 -0
- package/dist/git-activity.d.ts +24 -0
- package/dist/git-activity.d.ts.map +1 -0
- package/dist/git-activity.js +97 -0
- package/dist/git-activity.js.map +1 -0
- package/dist/git-branch.d.ts +33 -0
- package/dist/git-branch.d.ts.map +1 -0
- package/dist/git-branch.js +88 -0
- package/dist/git-branch.js.map +1 -0
- package/dist/git-integration.d.ts +27 -0
- package/dist/git-integration.d.ts.map +1 -0
- package/dist/git-integration.js +82 -0
- package/dist/git-integration.js.map +1 -0
- package/dist/git-merge-helpers.d.ts +48 -0
- package/dist/git-merge-helpers.d.ts.map +1 -0
- package/dist/git-merge-helpers.js +105 -0
- package/dist/git-merge-helpers.js.map +1 -0
- package/dist/git-merge-lock.d.ts +67 -0
- package/dist/git-merge-lock.d.ts.map +1 -0
- package/dist/git-merge-lock.js +157 -0
- package/dist/git-merge-lock.js.map +1 -0
- package/dist/git-merge-strategies.d.ts +39 -0
- package/dist/git-merge-strategies.d.ts.map +1 -0
- package/dist/git-merge-strategies.js +127 -0
- package/dist/git-merge-strategies.js.map +1 -0
- package/dist/git-merge.d.ts +80 -0
- package/dist/git-merge.d.ts.map +1 -0
- package/dist/git-merge.js +373 -0
- package/dist/git-merge.js.map +1 -0
- package/dist/git-state-detector.d.ts +24 -0
- package/dist/git-state-detector.d.ts.map +1 -0
- package/dist/git-state-detector.js +122 -0
- package/dist/git-state-detector.js.map +1 -0
- package/dist/git-types.d.ts +40 -0
- package/dist/git-types.d.ts.map +1 -0
- package/dist/git-types.js +23 -0
- package/dist/git-types.js.map +1 -0
- package/dist/git-utils.d.ts +28 -0
- package/dist/git-utils.d.ts.map +1 -0
- package/dist/git-utils.js +57 -0
- package/dist/git-utils.js.map +1 -0
- package/dist/git.d.ts +24 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +64 -0
- package/dist/git.js.map +1 -0
- package/dist/guard-engine.d.ts +19 -0
- package/dist/guard-engine.d.ts.map +1 -0
- package/dist/guard-engine.js +21 -0
- package/dist/guard-engine.js.map +1 -0
- package/dist/guard-evaluator.d.ts +47 -0
- package/dist/guard-evaluator.d.ts.map +1 -0
- package/dist/guard-evaluator.js +193 -0
- package/dist/guard-evaluator.js.map +1 -0
- package/dist/heartbeat.d.ts +73 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +306 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +493 -0
- package/dist/index.js.map +1 -0
- package/dist/listener-auto-advance.d.ts +29 -0
- package/dist/listener-auto-advance.d.ts.map +1 -0
- package/dist/listener-auto-advance.js +172 -0
- package/dist/listener-auto-advance.js.map +1 -0
- package/dist/listener-review.d.ts +37 -0
- package/dist/listener-review.d.ts.map +1 -0
- package/dist/listener-review.js +217 -0
- package/dist/listener-review.js.map +1 -0
- package/dist/listener.d.ts +57 -0
- package/dist/listener.d.ts.map +1 -0
- package/dist/listener.js +361 -0
- package/dist/listener.js.map +1 -0
- package/dist/log-manager.d.ts +18 -0
- package/dist/log-manager.d.ts.map +1 -0
- package/dist/log-manager.js +18 -0
- package/dist/log-manager.js.map +1 -0
- package/dist/otlp-log-parser.d.ts +21 -0
- package/dist/otlp-log-parser.d.ts.map +1 -0
- package/dist/otlp-log-parser.js +143 -0
- package/dist/otlp-log-parser.js.map +1 -0
- package/dist/otlp-metric-parser.d.ts +20 -0
- package/dist/otlp-metric-parser.d.ts.map +1 -0
- package/dist/otlp-metric-parser.js +113 -0
- package/dist/otlp-metric-parser.js.map +1 -0
- package/dist/otlp-port-manager.d.ts +26 -0
- package/dist/otlp-port-manager.d.ts.map +1 -0
- package/dist/otlp-port-manager.js +130 -0
- package/dist/otlp-port-manager.js.map +1 -0
- package/dist/otlp-receiver.d.ts +51 -0
- package/dist/otlp-receiver.d.ts.map +1 -0
- package/dist/otlp-receiver.js +663 -0
- package/dist/otlp-receiver.js.map +1 -0
- package/dist/otlp-types.d.ts +92 -0
- package/dist/otlp-types.d.ts.map +1 -0
- package/dist/otlp-types.js +133 -0
- package/dist/otlp-types.js.map +1 -0
- package/dist/output-monitor.d.ts +33 -0
- package/dist/output-monitor.d.ts.map +1 -0
- package/dist/output-monitor.js +67 -0
- package/dist/output-monitor.js.map +1 -0
- package/dist/planning-prompt-builder.d.ts +67 -0
- package/dist/planning-prompt-builder.d.ts.map +1 -0
- package/dist/planning-prompt-builder.js +515 -0
- package/dist/planning-prompt-builder.js.map +1 -0
- package/dist/prompt-builder.d.ts +14 -0
- package/dist/prompt-builder.d.ts.map +1 -0
- package/dist/prompt-builder.js +174 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/qa-crash-recovery.d.ts +77 -0
- package/dist/qa-crash-recovery.d.ts.map +1 -0
- package/dist/qa-crash-recovery.js +243 -0
- package/dist/qa-crash-recovery.js.map +1 -0
- package/dist/qa-dev-server.d.ts +73 -0
- package/dist/qa-dev-server.d.ts.map +1 -0
- package/dist/qa-dev-server.js +279 -0
- package/dist/qa-dev-server.js.map +1 -0
- package/dist/qa-orchestrator.d.ts +79 -0
- package/dist/qa-orchestrator.d.ts.map +1 -0
- package/dist/qa-orchestrator.js +349 -0
- package/dist/qa-orchestrator.js.map +1 -0
- package/dist/qa-port-allocator.d.ts +34 -0
- package/dist/qa-port-allocator.d.ts.map +1 -0
- package/dist/qa-port-allocator.js +75 -0
- package/dist/qa-port-allocator.js.map +1 -0
- package/dist/qa-provisioner.d.ts +33 -0
- package/dist/qa-provisioner.d.ts.map +1 -0
- package/dist/qa-provisioner.js +141 -0
- package/dist/qa-provisioner.js.map +1 -0
- package/dist/qa-state.d.ts +93 -0
- package/dist/qa-state.d.ts.map +1 -0
- package/dist/qa-state.js +74 -0
- package/dist/qa-state.js.map +1 -0
- package/dist/queries/control-state.d.ts +25 -0
- package/dist/queries/control-state.d.ts.map +1 -0
- package/dist/queries/control-state.js +34 -0
- package/dist/queries/control-state.js.map +1 -0
- package/dist/queries/daemon-connection.d.ts +25 -0
- package/dist/queries/daemon-connection.d.ts.map +1 -0
- package/dist/queries/daemon-connection.js +28 -0
- package/dist/queries/daemon-connection.js.map +1 -0
- package/dist/queries/deliveries.d.ts +100 -0
- package/dist/queries/deliveries.d.ts.map +1 -0
- package/dist/queries/deliveries.js +184 -0
- package/dist/queries/deliveries.js.map +1 -0
- package/dist/queries/git-activity.d.ts +20 -0
- package/dist/queries/git-activity.d.ts.map +1 -0
- package/dist/queries/git-activity.js +22 -0
- package/dist/queries/git-activity.js.map +1 -0
- package/dist/queries/guards.d.ts +47 -0
- package/dist/queries/guards.d.ts.map +1 -0
- package/dist/queries/guards.js +138 -0
- package/dist/queries/guards.js.map +1 -0
- package/dist/queries/index.d.ts +19 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/index.js +17 -0
- package/dist/queries/index.js.map +1 -0
- package/dist/queries/issues.d.ts +41 -0
- package/dist/queries/issues.d.ts.map +1 -0
- package/dist/queries/issues.js +67 -0
- package/dist/queries/issues.js.map +1 -0
- package/dist/queries/qa.d.ts +79 -0
- package/dist/queries/qa.d.ts.map +1 -0
- package/dist/queries/qa.js +85 -0
- package/dist/queries/qa.js.map +1 -0
- package/dist/queries/roles.d.ts +13 -0
- package/dist/queries/roles.d.ts.map +1 -0
- package/dist/queries/roles.js +39 -0
- package/dist/queries/roles.js.map +1 -0
- package/dist/queries/schemas.d.ts +777 -0
- package/dist/queries/schemas.d.ts.map +1 -0
- package/dist/queries/schemas.js +391 -0
- package/dist/queries/schemas.js.map +1 -0
- package/dist/queries/sessions.d.ts +64 -0
- package/dist/queries/sessions.d.ts.map +1 -0
- package/dist/queries/sessions.js +100 -0
- package/dist/queries/sessions.js.map +1 -0
- package/dist/queries/shared.d.ts +61 -0
- package/dist/queries/shared.d.ts.map +1 -0
- package/dist/queries/shared.js +187 -0
- package/dist/queries/shared.js.map +1 -0
- package/dist/queries/strategies.d.ts +69 -0
- package/dist/queries/strategies.d.ts.map +1 -0
- package/dist/queries/strategies.js +80 -0
- package/dist/queries/strategies.js.map +1 -0
- package/dist/queries/workflows.d.ts +17 -0
- package/dist/queries/workflows.d.ts.map +1 -0
- package/dist/queries/workflows.js +49 -0
- package/dist/queries/workflows.js.map +1 -0
- package/dist/queries/worktrees.d.ts +38 -0
- package/dist/queries/worktrees.d.ts.map +1 -0
- package/dist/queries/worktrees.js +37 -0
- package/dist/queries/worktrees.js.map +1 -0
- package/dist/self-update.d.ts +94 -0
- package/dist/self-update.d.ts.map +1 -0
- package/dist/self-update.js +438 -0
- package/dist/self-update.js.map +1 -0
- package/dist/session-lifecycle.d.ts +77 -0
- package/dist/session-lifecycle.d.ts.map +1 -0
- package/dist/session-lifecycle.js +379 -0
- package/dist/session-lifecycle.js.map +1 -0
- package/dist/shutdown-state.d.ts +17 -0
- package/dist/shutdown-state.d.ts.map +1 -0
- package/dist/shutdown-state.js +22 -0
- package/dist/shutdown-state.js.map +1 -0
- package/dist/spawn-cooldown.d.ts +14 -0
- package/dist/spawn-cooldown.d.ts.map +1 -0
- package/dist/spawn-cooldown.js +34 -0
- package/dist/spawn-cooldown.js.map +1 -0
- package/dist/spawn-environment.d.ts +35 -0
- package/dist/spawn-environment.d.ts.map +1 -0
- package/dist/spawn-environment.js +48 -0
- package/dist/spawn-environment.js.map +1 -0
- package/dist/spawner-liveness.d.ts +23 -0
- package/dist/spawner-liveness.d.ts.map +1 -0
- package/dist/spawner-liveness.js +99 -0
- package/dist/spawner-liveness.js.map +1 -0
- package/dist/spawner-resolution.d.ts +27 -0
- package/dist/spawner-resolution.d.ts.map +1 -0
- package/dist/spawner-resolution.js +99 -0
- package/dist/spawner-resolution.js.map +1 -0
- package/dist/spawner-timeout.d.ts +32 -0
- package/dist/spawner-timeout.d.ts.map +1 -0
- package/dist/spawner-timeout.js +124 -0
- package/dist/spawner-timeout.js.map +1 -0
- package/dist/spawner.d.ts +77 -0
- package/dist/spawner.d.ts.map +1 -0
- package/dist/spawner.js +734 -0
- package/dist/spawner.js.map +1 -0
- package/dist/strategy-completion.d.ts +110 -0
- package/dist/strategy-completion.d.ts.map +1 -0
- package/dist/strategy-completion.js +434 -0
- package/dist/strategy-completion.js.map +1 -0
- package/dist/strategy-engine.d.ts +47 -0
- package/dist/strategy-engine.d.ts.map +1 -0
- package/dist/strategy-engine.js +419 -0
- package/dist/strategy-engine.js.map +1 -0
- package/dist/strategy-executor.d.ts +93 -0
- package/dist/strategy-executor.d.ts.map +1 -0
- package/dist/strategy-executor.js +775 -0
- package/dist/strategy-executor.js.map +1 -0
- package/dist/strategy-lifecycle.d.ts +61 -0
- package/dist/strategy-lifecycle.d.ts.map +1 -0
- package/dist/strategy-lifecycle.js +516 -0
- package/dist/strategy-lifecycle.js.map +1 -0
- package/dist/strategy-merge.d.ts +72 -0
- package/dist/strategy-merge.d.ts.map +1 -0
- package/dist/strategy-merge.js +371 -0
- package/dist/strategy-merge.js.map +1 -0
- package/dist/strategy-prompt-builder.d.ts +62 -0
- package/dist/strategy-prompt-builder.d.ts.map +1 -0
- package/dist/strategy-prompt-builder.js +538 -0
- package/dist/strategy-prompt-builder.js.map +1 -0
- package/dist/strategy-provisioning.d.ts +16 -0
- package/dist/strategy-provisioning.d.ts.map +1 -0
- package/dist/strategy-provisioning.js +119 -0
- package/dist/strategy-provisioning.js.map +1 -0
- package/dist/strategy-team-state.d.ts +24 -0
- package/dist/strategy-team-state.d.ts.map +1 -0
- package/dist/strategy-team-state.js +43 -0
- package/dist/strategy-team-state.js.map +1 -0
- package/dist/strategy-teardown.d.ts +24 -0
- package/dist/strategy-teardown.d.ts.map +1 -0
- package/dist/strategy-teardown.js +158 -0
- package/dist/strategy-teardown.js.map +1 -0
- package/dist/strategy-worktree-state.d.ts +47 -0
- package/dist/strategy-worktree-state.d.ts.map +1 -0
- package/dist/strategy-worktree-state.js +104 -0
- package/dist/strategy-worktree-state.js.map +1 -0
- package/dist/supabase.d.ts +36 -0
- package/dist/supabase.d.ts.map +1 -0
- package/dist/supabase.js +50 -0
- package/dist/supabase.js.map +1 -0
- package/dist/task-converter.d.ts +61 -0
- package/dist/task-converter.d.ts.map +1 -0
- package/dist/task-converter.js +286 -0
- package/dist/task-converter.js.map +1 -0
- package/dist/task-dag-builder.d.ts +14 -0
- package/dist/task-dag-builder.d.ts.map +1 -0
- package/dist/task-dag-builder.js +17 -0
- package/dist/task-dag-builder.js.map +1 -0
- package/dist/team-prompt-base.d.ts +114 -0
- package/dist/team-prompt-base.d.ts.map +1 -0
- package/dist/team-prompt-base.js +531 -0
- package/dist/team-prompt-base.js.map +1 -0
- package/dist/team-prompt-variants.d.ts +27 -0
- package/dist/team-prompt-variants.d.ts.map +1 -0
- package/dist/team-prompt-variants.js +134 -0
- package/dist/team-prompt-variants.js.map +1 -0
- package/dist/team-spawner.d.ts +50 -0
- package/dist/team-spawner.d.ts.map +1 -0
- package/dist/team-spawner.js +410 -0
- package/dist/team-spawner.js.map +1 -0
- package/dist/telemetry-writer.d.ts +66 -0
- package/dist/telemetry-writer.d.ts.map +1 -0
- package/dist/telemetry-writer.js +96 -0
- package/dist/telemetry-writer.js.map +1 -0
- package/dist/trigger-executor.d.ts +56 -0
- package/dist/trigger-executor.d.ts.map +1 -0
- package/dist/trigger-executor.js +313 -0
- package/dist/trigger-executor.js.map +1 -0
- package/dist/types/config.d.ts +60 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +5 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/dag.d.ts +53 -0
- package/dist/types/dag.d.ts.map +1 -0
- package/dist/types/dag.js +5 -0
- package/dist/types/dag.js.map +1 -0
- package/dist/types/delivery.d.ts +71 -0
- package/dist/types/delivery.d.ts.map +1 -0
- package/dist/types/delivery.js +5 -0
- package/dist/types/delivery.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +15 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/issue.d.ts +22 -0
- package/dist/types/issue.d.ts.map +1 -0
- package/dist/types/issue.js +5 -0
- package/dist/types/issue.js.map +1 -0
- package/dist/types/merge.d.ts +28 -0
- package/dist/types/merge.d.ts.map +1 -0
- package/dist/types/merge.js +5 -0
- package/dist/types/merge.js.map +1 -0
- package/dist/types/session.d.ts +98 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +5 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/strategy.d.ts +175 -0
- package/dist/types/strategy.d.ts.map +1 -0
- package/dist/types/strategy.js +5 -0
- package/dist/types/strategy.js.map +1 -0
- package/dist/types/workflow.d.ts +34 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +9 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/unified-init.d.ts +16 -0
- package/dist/unified-init.d.ts.map +1 -0
- package/dist/unified-init.js +183 -0
- package/dist/unified-init.js.map +1 -0
- package/dist/unified-shell-config.d.ts +34 -0
- package/dist/unified-shell-config.d.ts.map +1 -0
- package/dist/unified-shell-config.js +238 -0
- package/dist/unified-shell-config.js.map +1 -0
- package/dist/unified-shell-status.d.ts +15 -0
- package/dist/unified-shell-status.d.ts.map +1 -0
- package/dist/unified-shell-status.js +100 -0
- package/dist/unified-shell-status.js.map +1 -0
- package/dist/unified-shell.d.ts +50 -0
- package/dist/unified-shell.d.ts.map +1 -0
- package/dist/unified-shell.js +682 -0
- package/dist/unified-shell.js.map +1 -0
- package/dist/version-check.d.ts +19 -0
- package/dist/version-check.d.ts.map +1 -0
- package/dist/version-check.js +67 -0
- package/dist/version-check.js.map +1 -0
- package/dist/workflow-engine.d.ts +95 -0
- package/dist/workflow-engine.d.ts.map +1 -0
- package/dist/workflow-engine.js +165 -0
- package/dist/workflow-engine.js.map +1 -0
- package/dist/worktree-merge.d.ts +23 -0
- package/dist/worktree-merge.d.ts.map +1 -0
- package/dist/worktree-merge.js +57 -0
- package/dist/worktree-merge.js.map +1 -0
- package/dist/worktree-safety.d.ts +48 -0
- package/dist/worktree-safety.d.ts.map +1 -0
- package/dist/worktree-safety.js +113 -0
- package/dist/worktree-safety.js.map +1 -0
- package/dist/worktree-strategy.d.ts +69 -0
- package/dist/worktree-strategy.d.ts.map +1 -0
- package/dist/worktree-strategy.js +214 -0
- package/dist/worktree-strategy.js.map +1 -0
- package/dist/worktree.d.ts +159 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +512 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +76 -0
- package/scripts/telora-daemon-wrapper.sh +31 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Completion handler - processes agent exit events.
|
|
3
|
+
*
|
|
4
|
+
* Handles the post-completion lifecycle for the legacy per-delivery model:
|
|
5
|
+
* - Querying open issues and session counts
|
|
6
|
+
* - Workflow-driven transition determination
|
|
7
|
+
* - Guard evaluation at stage transitions
|
|
8
|
+
* - Merge operations (integration branch, CI/CD)
|
|
9
|
+
* - Delivery status updates and session finalization
|
|
10
|
+
* - Worktree cleanup and re-poll triggering
|
|
11
|
+
*
|
|
12
|
+
* For the strategy team model, see delivery-lifecycle.ts which provides
|
|
13
|
+
* reusable functions (evaluateGuardsForDeliveryTransition, mergeDeliveryBranch,
|
|
14
|
+
* advanceDeliveryStage) that the team lead calls directly.
|
|
15
|
+
*/
|
|
16
|
+
import { updateSession, updateDeliveryStatus, getDeliveryIssues, getDeliverySessionCount, reportGitState } from './supabase.js';
|
|
17
|
+
import { removeWorktree } from './git.js';
|
|
18
|
+
import { getStageByName, determineTransition } from './workflow-engine.js';
|
|
19
|
+
import { evaluateGuardsForDeliveryTransition, mergeDeliveryBranch } from './delivery-lifecycle.js';
|
|
20
|
+
import { recordSessionCompleted, recordActivity } from './heartbeat.js';
|
|
21
|
+
import { triggerCheck } from './listener.js';
|
|
22
|
+
const MAX_RETRY_ATTEMPTS = 5;
|
|
23
|
+
/**
|
|
24
|
+
* Handle agent process exit.
|
|
25
|
+
*
|
|
26
|
+
* This is the main post-completion handler that runs when a Claude Code agent
|
|
27
|
+
* process exits. It determines the workflow transition, evaluates guards,
|
|
28
|
+
* performs merge operations, and updates delivery/session status.
|
|
29
|
+
*/
|
|
30
|
+
export async function handleAgentCompletion(code, signal, params) {
|
|
31
|
+
const { config, context, runningAgent, workflow, branchName, currentStageId, timedOut, timeoutMs, sessionId, deliveryId, completionDetector, stdoutLogStream, stderrStream, jsonlStream, runningAgents, } = params;
|
|
32
|
+
console.log(`Agent for "${context.delivery.name}" exited with code ${code}, signal ${signal}`);
|
|
33
|
+
recordActivity();
|
|
34
|
+
// Clear timeout timers
|
|
35
|
+
if (runningAgent.warningTimer)
|
|
36
|
+
clearTimeout(runningAgent.warningTimer);
|
|
37
|
+
if (runningAgent.timeoutTimer)
|
|
38
|
+
clearTimeout(runningAgent.timeoutTimer);
|
|
39
|
+
// Clean up completion detector
|
|
40
|
+
completionDetector?.destroy();
|
|
41
|
+
runningAgents.delete(sessionId);
|
|
42
|
+
// Close log streams
|
|
43
|
+
stdoutLogStream.end();
|
|
44
|
+
stderrStream.end();
|
|
45
|
+
jsonlStream.end();
|
|
46
|
+
// Report worktree_complete now that the agent has finished (success or failure)
|
|
47
|
+
reportGitState(deliveryId, 'worktree_complete').catch(err => console.warn(`[reportGitState] worktree_complete failed:`, err.message));
|
|
48
|
+
// Query issues and session count for transition decision
|
|
49
|
+
let openIssueCount = 0;
|
|
50
|
+
let attemptCount = 0;
|
|
51
|
+
if (code === 0) {
|
|
52
|
+
try {
|
|
53
|
+
const [issues, count] = await Promise.all([
|
|
54
|
+
getDeliveryIssues(deliveryId),
|
|
55
|
+
getDeliverySessionCount(deliveryId),
|
|
56
|
+
]);
|
|
57
|
+
openIssueCount = issues.filter(i => i.status !== 'Done').length;
|
|
58
|
+
attemptCount = count;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
console.warn(`Failed to query issues/sessions for "${context.delivery.name}":`, err.message);
|
|
62
|
+
// Fall through with 0 open issues (treat as all done) to avoid blocking on API errors
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
try {
|
|
67
|
+
attemptCount = await getDeliverySessionCount(deliveryId);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
console.warn(`Failed to query session count for "${context.delivery.name}":`, err.message);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Build failure reason for non-zero exits
|
|
74
|
+
const failureReason = code !== 0
|
|
75
|
+
? (timedOut
|
|
76
|
+
? `Timeout exceeded (${timeoutMs / 60000} min limit)`
|
|
77
|
+
: signal
|
|
78
|
+
? `Terminated by signal: ${signal}`
|
|
79
|
+
: `Exit code: ${code}`)
|
|
80
|
+
: undefined;
|
|
81
|
+
// Determine transition via workflow engine
|
|
82
|
+
const transition = currentStageId
|
|
83
|
+
? determineTransition({
|
|
84
|
+
workflow,
|
|
85
|
+
currentStageId,
|
|
86
|
+
exitCode: code ?? 1,
|
|
87
|
+
openIssueCount,
|
|
88
|
+
attemptCount,
|
|
89
|
+
maxRetries: MAX_RETRY_ATTEMPTS,
|
|
90
|
+
failureReason,
|
|
91
|
+
})
|
|
92
|
+
: {
|
|
93
|
+
// No workflow stage -- legacy fallback
|
|
94
|
+
nextStage: null,
|
|
95
|
+
workflowTransition: null,
|
|
96
|
+
shouldMerge: code === 0 && openIssueCount === 0,
|
|
97
|
+
shouldTriggerRepoll: code === 0 && openIssueCount === 0,
|
|
98
|
+
sessionStatus: (code === 0 && openIssueCount === 0 ? 'completed' : 'failed'),
|
|
99
|
+
exitReason: failureReason ?? (openIssueCount === 0 ? 'Completed.' : `${openIssueCount} open issues.`),
|
|
100
|
+
};
|
|
101
|
+
let { exitReason } = transition;
|
|
102
|
+
let { shouldMerge, shouldTriggerRepoll, sessionStatus } = transition;
|
|
103
|
+
// -- Guard evaluation at stage transitions --
|
|
104
|
+
const evalResult = await evaluateGuardsForDeliveryTransition({
|
|
105
|
+
deliveryId,
|
|
106
|
+
organizationId: context.delivery.organization_id,
|
|
107
|
+
workflowTransition: transition.workflowTransition ?? null,
|
|
108
|
+
exitCode: code ?? 1,
|
|
109
|
+
policyFailureMode: config.policyFailureMode,
|
|
110
|
+
deliveryName: context.delivery.name,
|
|
111
|
+
sessionId,
|
|
112
|
+
});
|
|
113
|
+
const evalBlocked = evalResult.blocked;
|
|
114
|
+
if (evalBlocked) {
|
|
115
|
+
shouldMerge = evalResult.shouldMerge;
|
|
116
|
+
shouldTriggerRepoll = evalResult.shouldTriggerRepoll;
|
|
117
|
+
sessionStatus = evalResult.sessionStatus;
|
|
118
|
+
exitReason = evalResult.exitReason;
|
|
119
|
+
}
|
|
120
|
+
else if (evalResult.exitReason && evalResult.exitReason !== exitReason) {
|
|
121
|
+
exitReason += ` ${evalResult.exitReason}`;
|
|
122
|
+
}
|
|
123
|
+
// Determine delivery status from transition
|
|
124
|
+
let deliveryStatus;
|
|
125
|
+
let deliveryStageId;
|
|
126
|
+
if (evalBlocked) {
|
|
127
|
+
// Guard already set delivery to 'paused' -- don't overwrite
|
|
128
|
+
deliveryStatus = 'paused';
|
|
129
|
+
deliveryStageId = currentStageId;
|
|
130
|
+
}
|
|
131
|
+
else if (transition.nextStage) {
|
|
132
|
+
deliveryStatus = transition.nextStage.name;
|
|
133
|
+
deliveryStageId = transition.nextStage.id;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// Staying on current stage means re-queuing
|
|
137
|
+
const queuedStage = getStageByName(workflow, 'queued');
|
|
138
|
+
deliveryStatus = queuedStage?.name ?? 'queued';
|
|
139
|
+
deliveryStageId = queuedStage?.id;
|
|
140
|
+
}
|
|
141
|
+
if (exitReason !== transition.exitReason) {
|
|
142
|
+
// exitReason was modified -- log the warning
|
|
143
|
+
console.warn(`Delivery "${context.delivery.name}": ${exitReason}`);
|
|
144
|
+
}
|
|
145
|
+
// Merge branch if warranted
|
|
146
|
+
let mergeOutcome = { mergeSucceeded: false, exitReason };
|
|
147
|
+
if (shouldMerge) {
|
|
148
|
+
mergeOutcome = await mergeDeliveryBranch({
|
|
149
|
+
config,
|
|
150
|
+
branchName,
|
|
151
|
+
deliveryId,
|
|
152
|
+
deliveryName: context.delivery.name,
|
|
153
|
+
organizationId: context.delivery.organization_id,
|
|
154
|
+
sessionId,
|
|
155
|
+
workflow,
|
|
156
|
+
});
|
|
157
|
+
exitReason = mergeOutcome.exitReason;
|
|
158
|
+
}
|
|
159
|
+
if (mergeOutcome.overrideDeliveryStatus) {
|
|
160
|
+
deliveryStatus = mergeOutcome.overrideDeliveryStatus;
|
|
161
|
+
deliveryStageId = mergeOutcome.overrideDeliveryStageId;
|
|
162
|
+
}
|
|
163
|
+
// Update delivery status with workflow stage
|
|
164
|
+
try {
|
|
165
|
+
await updateDeliveryStatus(deliveryId, deliveryStatus, deliveryStageId);
|
|
166
|
+
console.log(`Delivery "${context.delivery.name}" set to ${deliveryStatus}`);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
console.warn(`Failed to set delivery "${context.delivery.name}" to ${deliveryStatus}:`, err.message);
|
|
170
|
+
}
|
|
171
|
+
// Clean up worktree (branch is preserved for PR/review)
|
|
172
|
+
// Safety guards will refuse to delete if uncommitted changes or unmerged commits exist
|
|
173
|
+
removeWorktree(config.repoPath, runningAgent.worktreePath, {
|
|
174
|
+
branchName,
|
|
175
|
+
integrationBranch: config.integrationBranch,
|
|
176
|
+
deliveryName: context.delivery.name,
|
|
177
|
+
mergeSucceeded: mergeOutcome.mergeSucceeded,
|
|
178
|
+
});
|
|
179
|
+
// Report worktree_cleaned if merge succeeded (worktree was actually removed)
|
|
180
|
+
if (mergeOutcome.mergeSucceeded) {
|
|
181
|
+
reportGitState(deliveryId, 'worktree_cleaned').catch(err => console.warn(`[reportGitState] worktree_cleaned failed:`, err.message));
|
|
182
|
+
}
|
|
183
|
+
await updateSession(sessionId, {
|
|
184
|
+
status: sessionStatus,
|
|
185
|
+
exit_reason: exitReason,
|
|
186
|
+
ended_at: new Date().toISOString(),
|
|
187
|
+
});
|
|
188
|
+
// Record session completion for heartbeat counters
|
|
189
|
+
recordSessionCompleted(0, 0); // Token/cost tracking can be enriched later
|
|
190
|
+
// Trigger re-poll to pick up next delivery in the strategy's priority queue
|
|
191
|
+
if (shouldTriggerRepoll) {
|
|
192
|
+
console.log(`Delivery "${context.delivery.name}" completed, checking for next delivery in strategy...`);
|
|
193
|
+
triggerCheck();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Note: MergeOutcome type and merge functions are now in delivery-lifecycle.ts.
|
|
197
|
+
// The handleMergeIfNeeded and handleCiMerge functions have been extracted to
|
|
198
|
+
// mergeDeliveryBranch() in delivery-lifecycle.ts for reuse by both the
|
|
199
|
+
// legacy per-delivery handler and the strategy team lead.
|
|
200
|
+
//# sourceMappingURL=completion-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-handler.js","sourceRoot":"","sources":["../src/completion-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Individual condition type evaluators for the guard engine.
|
|
3
|
+
*
|
|
4
|
+
* Each condition type (open_issues_count, all_issues_done, agent_exit_code,
|
|
5
|
+
* gate_result, token_budget, work_unit_state, all_work_units_completed,
|
|
6
|
+
* cycle_count, wall_clock) is a separate function. A dispatch map routes
|
|
7
|
+
* condition_type strings to the appropriate evaluator.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from guard-engine.ts to improve maintainability.
|
|
10
|
+
*/
|
|
11
|
+
import type { GuardConditionNode, ConditionEvalResult } from './types.js';
|
|
12
|
+
import type { EvaluationContext } from './evaluation-context.js';
|
|
13
|
+
/**
|
|
14
|
+
* Safely coerce a JSONB value to a number.
|
|
15
|
+
* Returns null if the value is not a valid finite number.
|
|
16
|
+
*/
|
|
17
|
+
export declare function toSafeNumber(value: unknown): number | null;
|
|
18
|
+
/**
|
|
19
|
+
* Compare two numeric values with the given operator.
|
|
20
|
+
*/
|
|
21
|
+
export declare function compareValues(observed: number, operator: string, expected: number): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Signature for a leaf condition evaluator function.
|
|
24
|
+
*/
|
|
25
|
+
export type ConditionEvaluatorFn = (node: GuardConditionNode, nodeId: string, ctx: EvaluationContext) => ConditionEvalResult;
|
|
26
|
+
/**
|
|
27
|
+
* Evaluate a single leaf condition against the evaluation context.
|
|
28
|
+
* Dispatches to the appropriate evaluator based on condition_type.
|
|
29
|
+
*/
|
|
30
|
+
export declare function evaluateLeafCondition(node: GuardConditionNode, nodeId: string, ctx: EvaluationContext): ConditionEvalResult;
|
|
31
|
+
//# sourceMappingURL=condition-evaluators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"condition-evaluators.d.ts","sourceRoot":"","sources":["../src/condition-evaluators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAMjE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAU3F;AAMD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,iBAAiB,KACnB,mBAAmB,CAAC;AAmczB;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,iBAAiB,GACrB,mBAAmB,CASrB"}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Individual condition type evaluators for the guard engine.
|
|
3
|
+
*
|
|
4
|
+
* Each condition type (open_issues_count, all_issues_done, agent_exit_code,
|
|
5
|
+
* gate_result, token_budget, work_unit_state, all_work_units_completed,
|
|
6
|
+
* cycle_count, wall_clock) is a separate function. A dispatch map routes
|
|
7
|
+
* condition_type strings to the appropriate evaluator.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from guard-engine.ts to improve maintainability.
|
|
10
|
+
*/
|
|
11
|
+
// ============================================
|
|
12
|
+
// Shared Utilities
|
|
13
|
+
// ============================================
|
|
14
|
+
/**
|
|
15
|
+
* Safely coerce a JSONB value to a number.
|
|
16
|
+
* Returns null if the value is not a valid finite number.
|
|
17
|
+
*/
|
|
18
|
+
export function toSafeNumber(value) {
|
|
19
|
+
if (value === null || value === undefined)
|
|
20
|
+
return null;
|
|
21
|
+
const num = typeof value === 'number' ? value : Number(value);
|
|
22
|
+
return Number.isFinite(num) ? num : null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Compare two numeric values with the given operator.
|
|
26
|
+
*/
|
|
27
|
+
export function compareValues(observed, operator, expected) {
|
|
28
|
+
switch (operator) {
|
|
29
|
+
case 'eq': return observed === expected;
|
|
30
|
+
case 'neq': return observed !== expected;
|
|
31
|
+
case 'lt': return observed < expected;
|
|
32
|
+
case 'lte': return observed <= expected;
|
|
33
|
+
case 'gt': return observed > expected;
|
|
34
|
+
case 'gte': return observed >= expected;
|
|
35
|
+
default: return observed === expected;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// ============================================
|
|
39
|
+
// Individual Condition Evaluators
|
|
40
|
+
// ============================================
|
|
41
|
+
function evaluateOpenIssuesCount(node, nodeId, ctx) {
|
|
42
|
+
const expr = node.expression ?? {};
|
|
43
|
+
const conditionType = 'open_issues_count';
|
|
44
|
+
const statuses = expr.statuses ?? ['To Do', 'In Progress', 'Blocked'];
|
|
45
|
+
const operator = expr.operator ?? 'eq';
|
|
46
|
+
const expected = toSafeNumber(expr.value) ?? 0;
|
|
47
|
+
let observed = 0;
|
|
48
|
+
for (const status of statuses) {
|
|
49
|
+
observed += ctx.issuesByStatus[status] ?? 0;
|
|
50
|
+
}
|
|
51
|
+
const passed = compareValues(observed, operator, expected);
|
|
52
|
+
return {
|
|
53
|
+
condition_id: nodeId,
|
|
54
|
+
condition_type: conditionType,
|
|
55
|
+
passed,
|
|
56
|
+
observed_value: observed,
|
|
57
|
+
expected_value: `${operator} ${expected}`,
|
|
58
|
+
message: passed
|
|
59
|
+
? `Open issues count (${observed}) satisfies ${operator} ${expected}`
|
|
60
|
+
: `Open issues count (${observed}) does not satisfy ${operator} ${expected}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function evaluateAllIssuesDone(node, nodeId, ctx) {
|
|
64
|
+
const conditionType = 'all_issues_done';
|
|
65
|
+
const passed = ctx.openIssueCount === 0 && ctx.totalIssueCount > 0;
|
|
66
|
+
return {
|
|
67
|
+
condition_id: nodeId,
|
|
68
|
+
condition_type: conditionType,
|
|
69
|
+
passed,
|
|
70
|
+
observed_value: ctx.openIssueCount,
|
|
71
|
+
expected_value: 0,
|
|
72
|
+
message: passed
|
|
73
|
+
? 'All issues are Done'
|
|
74
|
+
: ctx.totalIssueCount === 0
|
|
75
|
+
? 'No issues exist on this delivery'
|
|
76
|
+
: `${ctx.openIssueCount} issue(s) are not Done`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function evaluateAgentExitCode(node, nodeId, ctx) {
|
|
80
|
+
const expr = node.expression ?? {};
|
|
81
|
+
const conditionType = 'agent_exit_code';
|
|
82
|
+
const operator = expr.operator ?? 'eq';
|
|
83
|
+
const expected = toSafeNumber(expr.value) ?? 0;
|
|
84
|
+
const passed = compareValues(ctx.lastExitCode, operator, expected);
|
|
85
|
+
return {
|
|
86
|
+
condition_id: nodeId,
|
|
87
|
+
condition_type: conditionType,
|
|
88
|
+
passed,
|
|
89
|
+
observed_value: ctx.lastExitCode,
|
|
90
|
+
expected_value: `${operator} ${expected}`,
|
|
91
|
+
message: passed
|
|
92
|
+
? `Agent exit code (${ctx.lastExitCode}) satisfies ${operator} ${expected}`
|
|
93
|
+
: `Agent exit code (${ctx.lastExitCode}) does not satisfy ${operator} ${expected}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function evaluateGateResult(node, nodeId, ctx) {
|
|
97
|
+
const expr = node.expression ?? {};
|
|
98
|
+
const conditionType = 'gate_result';
|
|
99
|
+
const gateType = expr.gate_type;
|
|
100
|
+
if (!gateType) {
|
|
101
|
+
return {
|
|
102
|
+
condition_id: nodeId,
|
|
103
|
+
condition_type: conditionType,
|
|
104
|
+
passed: false,
|
|
105
|
+
observed_value: null,
|
|
106
|
+
expected_value: 'gate_type required',
|
|
107
|
+
message: 'gate_result condition missing required gate_type in expression',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const scope = expr.scope ?? 'strategy';
|
|
111
|
+
const operator = expr.operator ?? 'eq';
|
|
112
|
+
const expectedValue = expr.value ?? 'passed';
|
|
113
|
+
const strategyId = expr.strategy_id;
|
|
114
|
+
const results = ctx.gateResults ?? [];
|
|
115
|
+
let filtered = results.filter(r => r.gateType === gateType);
|
|
116
|
+
if (scope === 'strategy' && strategyId) {
|
|
117
|
+
filtered = filtered.filter(r => r.strategyId === strategyId);
|
|
118
|
+
}
|
|
119
|
+
if (filtered.length === 0) {
|
|
120
|
+
return {
|
|
121
|
+
condition_id: nodeId,
|
|
122
|
+
condition_type: conditionType,
|
|
123
|
+
passed: false,
|
|
124
|
+
observed_value: 'no_results',
|
|
125
|
+
expected_value: `${operator} ${expectedValue}`,
|
|
126
|
+
message: `No gate results found for gate_type "${gateType}" (gate hasn't run yet)`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Use the most recent result (last in array)
|
|
130
|
+
const latest = filtered[filtered.length - 1];
|
|
131
|
+
const observedState = latest.passed ? 'passed' : 'failed';
|
|
132
|
+
const passed = operator === 'neq'
|
|
133
|
+
? observedState !== expectedValue
|
|
134
|
+
: observedState === expectedValue;
|
|
135
|
+
return {
|
|
136
|
+
condition_id: nodeId,
|
|
137
|
+
condition_type: conditionType,
|
|
138
|
+
passed,
|
|
139
|
+
observed_value: observedState,
|
|
140
|
+
expected_value: `${operator} ${expectedValue}`,
|
|
141
|
+
message: passed
|
|
142
|
+
? `Gate ${gateType} result (${observedState}) satisfies ${operator} ${expectedValue}`
|
|
143
|
+
: `Gate ${gateType} result (${observedState}) does not satisfy ${operator} ${expectedValue}`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function evaluateTokenBudget(node, nodeId, ctx) {
|
|
147
|
+
const expr = node.expression ?? {};
|
|
148
|
+
const conditionType = 'token_budget';
|
|
149
|
+
if (ctx.tokensUsed === undefined) {
|
|
150
|
+
return {
|
|
151
|
+
condition_id: nodeId,
|
|
152
|
+
condition_type: conditionType,
|
|
153
|
+
passed: true,
|
|
154
|
+
observed_value: null,
|
|
155
|
+
expected_value: null,
|
|
156
|
+
message: 'No factory context -- token_budget skipped',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const mode = expr.mode ?? 'percentage';
|
|
160
|
+
const operator = expr.operator ?? 'lt';
|
|
161
|
+
const expected = toSafeNumber(expr.value);
|
|
162
|
+
if (expected === null) {
|
|
163
|
+
return {
|
|
164
|
+
condition_id: nodeId,
|
|
165
|
+
condition_type: conditionType,
|
|
166
|
+
passed: false,
|
|
167
|
+
observed_value: ctx.tokensUsed,
|
|
168
|
+
expected_value: 'value required',
|
|
169
|
+
message: 'token_budget condition missing or invalid value in expression',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
let observed;
|
|
173
|
+
if (mode === 'percentage') {
|
|
174
|
+
if (ctx.tokenBudget == null) {
|
|
175
|
+
// Unlimited budget -- percentage mode always passes
|
|
176
|
+
return {
|
|
177
|
+
condition_id: nodeId,
|
|
178
|
+
condition_type: conditionType,
|
|
179
|
+
passed: true,
|
|
180
|
+
observed_value: 0,
|
|
181
|
+
expected_value: `${operator} ${expected}%`,
|
|
182
|
+
message: 'Token budget is unlimited -- percentage check passes',
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (ctx.tokenBudget === 0) {
|
|
186
|
+
// Zero budget means no tokens allowed -- usage is always 100%
|
|
187
|
+
observed = ctx.tokensUsed > 0 ? 100 : 0;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
observed = (ctx.tokensUsed / ctx.tokenBudget) * 100;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
observed = ctx.tokensUsed;
|
|
195
|
+
}
|
|
196
|
+
const passed = compareValues(observed, operator, expected);
|
|
197
|
+
const unit = mode === 'percentage' ? '%' : ' tokens';
|
|
198
|
+
return {
|
|
199
|
+
condition_id: nodeId,
|
|
200
|
+
condition_type: conditionType,
|
|
201
|
+
passed,
|
|
202
|
+
observed_value: Math.round(observed * 100) / 100,
|
|
203
|
+
expected_value: `${operator} ${expected}${unit}`,
|
|
204
|
+
message: passed
|
|
205
|
+
? `Token usage (${Math.round(observed)}${unit}) satisfies ${operator} ${expected}${unit}`
|
|
206
|
+
: `Token usage (${Math.round(observed)}${unit}) does not satisfy ${operator} ${expected}${unit}`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function evaluateWorkUnitState(node, nodeId, ctx) {
|
|
210
|
+
const expr = node.expression ?? {};
|
|
211
|
+
const conditionType = 'work_unit_state';
|
|
212
|
+
const statuses = expr.statuses;
|
|
213
|
+
if (!statuses || statuses.length === 0) {
|
|
214
|
+
return {
|
|
215
|
+
condition_id: nodeId,
|
|
216
|
+
condition_type: conditionType,
|
|
217
|
+
passed: false,
|
|
218
|
+
observed_value: null,
|
|
219
|
+
expected_value: 'statuses required',
|
|
220
|
+
message: 'work_unit_state condition missing required statuses in expression',
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
const operator = expr.operator ?? 'eq';
|
|
224
|
+
const expected = toSafeNumber(expr.value);
|
|
225
|
+
if (expected === null) {
|
|
226
|
+
return {
|
|
227
|
+
condition_id: nodeId,
|
|
228
|
+
condition_type: conditionType,
|
|
229
|
+
passed: false,
|
|
230
|
+
observed_value: null,
|
|
231
|
+
expected_value: 'value required',
|
|
232
|
+
message: 'work_unit_state condition missing or invalid value in expression',
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
const wuByStatus = ctx.workUnitsByStatus ?? {};
|
|
236
|
+
let observed = 0;
|
|
237
|
+
for (const status of statuses) {
|
|
238
|
+
observed += wuByStatus[status] ?? 0;
|
|
239
|
+
}
|
|
240
|
+
const passed = compareValues(observed, operator, expected);
|
|
241
|
+
return {
|
|
242
|
+
condition_id: nodeId,
|
|
243
|
+
condition_type: conditionType,
|
|
244
|
+
passed,
|
|
245
|
+
observed_value: observed,
|
|
246
|
+
expected_value: `${operator} ${expected}`,
|
|
247
|
+
message: passed
|
|
248
|
+
? `Work units in [${statuses.join(', ')}] (${observed}) satisfies ${operator} ${expected}`
|
|
249
|
+
: `Work units in [${statuses.join(', ')}] (${observed}) does not satisfy ${operator} ${expected}`,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function evaluateAllWorkUnitsCompleted(node, nodeId, ctx) {
|
|
253
|
+
const conditionType = 'all_work_units_completed';
|
|
254
|
+
const wuByStatus = ctx.workUnitsByStatus ?? {};
|
|
255
|
+
const total = ctx.totalWorkUnitCount ?? 0;
|
|
256
|
+
const completed = wuByStatus['completed'] ?? 0;
|
|
257
|
+
const passed = completed === total && total > 0;
|
|
258
|
+
return {
|
|
259
|
+
condition_id: nodeId,
|
|
260
|
+
condition_type: conditionType,
|
|
261
|
+
passed,
|
|
262
|
+
observed_value: completed,
|
|
263
|
+
expected_value: total,
|
|
264
|
+
message: passed
|
|
265
|
+
? `All ${total} work units are completed`
|
|
266
|
+
: total === 0
|
|
267
|
+
? 'No work units exist'
|
|
268
|
+
: `${completed} of ${total} work units are completed`,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function evaluateCycleCount(node, nodeId, ctx) {
|
|
272
|
+
const expr = node.expression ?? {};
|
|
273
|
+
const conditionType = 'cycle_count';
|
|
274
|
+
if (ctx.cycleCount === undefined) {
|
|
275
|
+
return {
|
|
276
|
+
condition_id: nodeId,
|
|
277
|
+
condition_type: conditionType,
|
|
278
|
+
passed: true,
|
|
279
|
+
observed_value: null,
|
|
280
|
+
expected_value: null,
|
|
281
|
+
message: 'No factory context -- cycle_count skipped',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
const operator = expr.operator ?? 'lt';
|
|
285
|
+
// Support dynamic values via value_from (reads from ctx.configValues)
|
|
286
|
+
const rawExpected = expr.value_from
|
|
287
|
+
? (ctx.configValues?.[expr.value_from] ?? toSafeNumber(expr.value))
|
|
288
|
+
: toSafeNumber(expr.value);
|
|
289
|
+
if (rawExpected === null || rawExpected === undefined) {
|
|
290
|
+
return {
|
|
291
|
+
condition_id: nodeId,
|
|
292
|
+
condition_type: conditionType,
|
|
293
|
+
passed: false,
|
|
294
|
+
observed_value: ctx.cycleCount,
|
|
295
|
+
expected_value: 'value required',
|
|
296
|
+
message: 'cycle_count condition missing or invalid value in expression',
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const expected = rawExpected;
|
|
300
|
+
const passed = compareValues(ctx.cycleCount, operator, expected);
|
|
301
|
+
return {
|
|
302
|
+
condition_id: nodeId,
|
|
303
|
+
condition_type: conditionType,
|
|
304
|
+
passed,
|
|
305
|
+
observed_value: ctx.cycleCount,
|
|
306
|
+
expected_value: `${operator} ${expected}`,
|
|
307
|
+
message: passed
|
|
308
|
+
? `Cycle count (${ctx.cycleCount}) satisfies ${operator} ${expected}`
|
|
309
|
+
: `Cycle count (${ctx.cycleCount}) does not satisfy ${operator} ${expected}`,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function evaluateWallClock(node, nodeId, ctx) {
|
|
313
|
+
const expr = node.expression ?? {};
|
|
314
|
+
const conditionType = 'wall_clock';
|
|
315
|
+
if (ctx.wallClockSeconds === undefined) {
|
|
316
|
+
return {
|
|
317
|
+
condition_id: nodeId,
|
|
318
|
+
condition_type: conditionType,
|
|
319
|
+
passed: true,
|
|
320
|
+
observed_value: null,
|
|
321
|
+
expected_value: null,
|
|
322
|
+
message: 'No factory context -- wall_clock skipped',
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
const mode = expr.mode ?? 'percentage';
|
|
326
|
+
const operator = expr.operator ?? 'lt';
|
|
327
|
+
const expected = toSafeNumber(expr.value);
|
|
328
|
+
if (expected === null) {
|
|
329
|
+
return {
|
|
330
|
+
condition_id: nodeId,
|
|
331
|
+
condition_type: conditionType,
|
|
332
|
+
passed: false,
|
|
333
|
+
observed_value: ctx.wallClockSeconds,
|
|
334
|
+
expected_value: 'value required',
|
|
335
|
+
message: 'wall_clock condition missing or invalid value in expression',
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
let observed;
|
|
339
|
+
if (mode === 'percentage') {
|
|
340
|
+
if (ctx.wallClockLimitSeconds == null) {
|
|
341
|
+
return {
|
|
342
|
+
condition_id: nodeId,
|
|
343
|
+
condition_type: conditionType,
|
|
344
|
+
passed: true,
|
|
345
|
+
observed_value: 0,
|
|
346
|
+
expected_value: `${operator} ${expected}%`,
|
|
347
|
+
message: 'Wall clock limit is unlimited -- percentage check passes',
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
if (ctx.wallClockLimitSeconds === 0) {
|
|
351
|
+
// Zero time limit means no time allowed -- elapsed is always 100%
|
|
352
|
+
observed = ctx.wallClockSeconds > 0 ? 100 : 0;
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
observed = (ctx.wallClockSeconds / ctx.wallClockLimitSeconds) * 100;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
observed = ctx.wallClockSeconds;
|
|
360
|
+
}
|
|
361
|
+
const passed = compareValues(observed, operator, expected);
|
|
362
|
+
const unit = mode === 'percentage' ? '%' : 's';
|
|
363
|
+
return {
|
|
364
|
+
condition_id: nodeId,
|
|
365
|
+
condition_type: conditionType,
|
|
366
|
+
passed,
|
|
367
|
+
observed_value: Math.round(observed * 100) / 100,
|
|
368
|
+
expected_value: `${operator} ${expected}${unit}`,
|
|
369
|
+
message: passed
|
|
370
|
+
? `Wall clock (${Math.round(observed)}${unit}) satisfies ${operator} ${expected}${unit}`
|
|
371
|
+
: `Wall clock (${Math.round(observed)}${unit}) does not satisfy ${operator} ${expected}${unit}`,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
function evaluateUnknown(node, nodeId, _ctx) {
|
|
375
|
+
const conditionType = node.condition_type ?? 'unknown';
|
|
376
|
+
console.warn(`[guard] Unknown condition type "${conditionType}" -- blocking (possible misconfiguration)`);
|
|
377
|
+
return {
|
|
378
|
+
condition_id: nodeId,
|
|
379
|
+
condition_type: conditionType,
|
|
380
|
+
passed: false,
|
|
381
|
+
observed_value: null,
|
|
382
|
+
expected_value: null,
|
|
383
|
+
message: `Unknown condition type "${conditionType}" -- blocked (unrecognized type)`,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
// ============================================
|
|
387
|
+
// Dispatch Map
|
|
388
|
+
// ============================================
|
|
389
|
+
/**
|
|
390
|
+
* Map of condition type strings to their evaluator functions.
|
|
391
|
+
* Add new condition types here.
|
|
392
|
+
*/
|
|
393
|
+
const conditionEvaluators = {
|
|
394
|
+
open_issues_count: evaluateOpenIssuesCount,
|
|
395
|
+
all_issues_done: evaluateAllIssuesDone,
|
|
396
|
+
agent_exit_code: evaluateAgentExitCode,
|
|
397
|
+
gate_result: evaluateGateResult,
|
|
398
|
+
token_budget: evaluateTokenBudget,
|
|
399
|
+
work_unit_state: evaluateWorkUnitState,
|
|
400
|
+
all_work_units_completed: evaluateAllWorkUnitsCompleted,
|
|
401
|
+
cycle_count: evaluateCycleCount,
|
|
402
|
+
wall_clock: evaluateWallClock,
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* Evaluate a single leaf condition against the evaluation context.
|
|
406
|
+
* Dispatches to the appropriate evaluator based on condition_type.
|
|
407
|
+
*/
|
|
408
|
+
export function evaluateLeafCondition(node, nodeId, ctx) {
|
|
409
|
+
const conditionType = node.condition_type ?? 'unknown';
|
|
410
|
+
const evaluator = conditionEvaluators[conditionType];
|
|
411
|
+
if (evaluator) {
|
|
412
|
+
return evaluator(node, nodeId, ctx);
|
|
413
|
+
}
|
|
414
|
+
return evaluateUnknown(node, nodeId, ctx);
|
|
415
|
+
}
|
|
416
|
+
//# sourceMappingURL=condition-evaluators.js.map
|