@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,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branch management utilities for the git subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Handles branch existence checks, default branch detection,
|
|
5
|
+
* integration branch creation, and branch deletion.
|
|
6
|
+
*
|
|
7
|
+
* Uses daemon-core's branchExists for the local-only check and layers
|
|
8
|
+
* a remote-branch fallback on top for the daemon's broader needs.
|
|
9
|
+
*/
|
|
10
|
+
import type { DaemonConfig } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Check if a branch exists (locally or remotely).
|
|
13
|
+
*
|
|
14
|
+
* Delegates to daemon-core's branchExists for the local check, then
|
|
15
|
+
* falls back to a remote branch lookup. The daemon needs both because
|
|
16
|
+
* worktree creation and integration-branch setup reference branches
|
|
17
|
+
* that may only exist on the remote.
|
|
18
|
+
*/
|
|
19
|
+
export declare function branchExists(branchName: string, repoPath: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Get the default branch (main or master).
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDefaultBranch(repoPath: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Ensure the integration branch exists.
|
|
26
|
+
* Creates it from the default branch (main/master) if it doesn't exist.
|
|
27
|
+
*/
|
|
28
|
+
export declare function ensureIntegrationBranch(config: DaemonConfig): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Delete a branch after successful merge to integration.
|
|
31
|
+
*/
|
|
32
|
+
export declare function deleteBranch(branchName: string, repoPath: string): void;
|
|
33
|
+
//# sourceMappingURL=git-branch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-branch.d.ts","sourceRoot":"","sources":["../src/git-branch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO/C;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgB1E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBzD;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCjF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAUvE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branch management utilities for the git subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Handles branch existence checks, default branch detection,
|
|
5
|
+
* integration branch creation, and branch deletion.
|
|
6
|
+
*
|
|
7
|
+
* Uses daemon-core's branchExists for the local-only check and layers
|
|
8
|
+
* a remote-branch fallback on top for the daemon's broader needs.
|
|
9
|
+
*/
|
|
10
|
+
import { branchExists as localBranchExists, runGit, } from '@telora/daemon-core';
|
|
11
|
+
import { runGitSync } from './git-types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Check if a branch exists (locally or remotely).
|
|
14
|
+
*
|
|
15
|
+
* Delegates to daemon-core's branchExists for the local check, then
|
|
16
|
+
* falls back to a remote branch lookup. The daemon needs both because
|
|
17
|
+
* worktree creation and integration-branch setup reference branches
|
|
18
|
+
* that may only exist on the remote.
|
|
19
|
+
*/
|
|
20
|
+
export function branchExists(branchName, repoPath) {
|
|
21
|
+
// Check local branches via daemon-core
|
|
22
|
+
if (localBranchExists(branchName, repoPath)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
// Check remote branches
|
|
26
|
+
const remoteResult = runGit(['branch', '-r', '--list', `origin/${branchName}`], repoPath);
|
|
27
|
+
if (remoteResult.success && remoteResult.output.includes(`origin/${branchName}`)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the default branch (main or master).
|
|
34
|
+
*/
|
|
35
|
+
export function getDefaultBranch(repoPath) {
|
|
36
|
+
// Try to get the default branch from remote HEAD
|
|
37
|
+
const result = runGitSync(['symbolic-ref', 'refs/remotes/origin/HEAD', '--short'], repoPath);
|
|
38
|
+
if (result.success) {
|
|
39
|
+
// Result is like "origin/main", extract just the branch name
|
|
40
|
+
const parts = result.output.split('/');
|
|
41
|
+
return parts[parts.length - 1];
|
|
42
|
+
}
|
|
43
|
+
// Fallback: check if main exists, otherwise assume master
|
|
44
|
+
if (branchExists('main', repoPath)) {
|
|
45
|
+
return 'main';
|
|
46
|
+
}
|
|
47
|
+
return 'master';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Ensure the integration branch exists.
|
|
51
|
+
* Creates it from the default branch (main/master) if it doesn't exist.
|
|
52
|
+
*/
|
|
53
|
+
export async function ensureIntegrationBranch(config) {
|
|
54
|
+
const { repoPath, integrationBranch } = config;
|
|
55
|
+
if (branchExists(integrationBranch, repoPath)) {
|
|
56
|
+
console.log(`Integration branch '${integrationBranch}' exists`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const defaultBranch = getDefaultBranch(repoPath);
|
|
60
|
+
console.log(`Creating integration branch '${integrationBranch}' from '${defaultBranch}'...`);
|
|
61
|
+
// Create the integration branch from the default branch
|
|
62
|
+
const result = runGitSync(['branch', integrationBranch, defaultBranch], repoPath);
|
|
63
|
+
if (!result.success) {
|
|
64
|
+
throw new Error(`Failed to create integration branch: ${result.error}`);
|
|
65
|
+
}
|
|
66
|
+
// Push the integration branch to remote if origin exists
|
|
67
|
+
const pushResult = runGitSync(['push', '-u', 'origin', integrationBranch], repoPath);
|
|
68
|
+
if (pushResult.success) {
|
|
69
|
+
console.log(`Pushed integration branch to origin`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(`Note: Could not push integration branch to origin (may not have remote)`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Delete a branch after successful merge to integration.
|
|
77
|
+
*/
|
|
78
|
+
export function deleteBranch(branchName, repoPath) {
|
|
79
|
+
// Delete local branch
|
|
80
|
+
const localResult = runGitSync(['branch', '-d', branchName], repoPath);
|
|
81
|
+
if (!localResult.success) {
|
|
82
|
+
// Try force delete if normal delete fails
|
|
83
|
+
runGitSync(['branch', '-D', branchName], repoPath);
|
|
84
|
+
}
|
|
85
|
+
// Delete remote branch (if exists)
|
|
86
|
+
runGitSync(['push', 'origin', '--delete', branchName], repoPath);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=git-branch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-branch.js","sourceRoot":"","sources":["../src/git-branch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,YAAY,IAAI,iBAAiB,EACjC,MAAM,GACP,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,QAAgB;IAC/D,uCAAuC;IACvC,IAAI,iBAAiB,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wBAAwB;IACxB,MAAM,YAAY,GAAG,MAAM,CACzB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,UAAU,EAAE,CAAC,EAClD,QAAQ,CACT,CAAC;IACF,IAAI,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,UAAU,EAAE,CAAC,EAAE,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,iDAAiD;IACjD,MAAM,MAAM,GAAG,UAAU,CACvB,CAAC,cAAc,EAAE,0BAA0B,EAAE,SAAS,CAAC,EACvD,QAAQ,CACT,CAAC;IACF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,6DAA6D;QAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,0DAA0D;IAC1D,IAAI,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAoB;IAChE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAAC;IAE/C,IAAI,YAAY,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,uBAAuB,iBAAiB,UAAU,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CACT,gCAAgC,iBAAiB,WAAW,aAAa,MAAM,CAChF,CAAC;IAEF,wDAAwD;IACxD,MAAM,MAAM,GAAG,UAAU,CACvB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,aAAa,CAAC,EAC5C,QAAQ,CACT,CAAC;IAEF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,wCAAwC,MAAM,CAAC,KAAK,EAAE,CACvD,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,MAAM,UAAU,GAAG,UAAU,CAC3B,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,CAAC,EAC3C,QAAQ,CACT,CAAC;IAEF,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,QAAgB;IAC/D,sBAAsB;IACtB,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC;IACvE,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,0CAA0C;QAC1C,UAAU,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,mCAAmC;IACnC,UAAU,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration branch management for the git subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Handles syncing integration with main so agents start from the latest code.
|
|
5
|
+
* The daemon never touches main directly — the user merges integration into main.
|
|
6
|
+
*/
|
|
7
|
+
import type { DaemonConfig } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Sync the integration branch with main so agents start from the latest code.
|
|
10
|
+
*
|
|
11
|
+
* Uses a pre-flight check to avoid taking the merge lock when integration
|
|
12
|
+
* is already up-to-date with main. This prevents spawn operations from
|
|
13
|
+
* contending with merge completions in the common case.
|
|
14
|
+
*
|
|
15
|
+
* Steps:
|
|
16
|
+
* 1. Fetch origin to get latest remote state
|
|
17
|
+
* 2. Check if integration already contains main (skip if so)
|
|
18
|
+
* 3. Acquire merge lock only if sync is needed
|
|
19
|
+
* 4. Check out integration, merge main, push, restore
|
|
20
|
+
*
|
|
21
|
+
* Uses merge (not rebase) to preserve in-progress agent branch references.
|
|
22
|
+
*/
|
|
23
|
+
export declare function syncIntegrationWithMain(config: DaemonConfig): Promise<{
|
|
24
|
+
success: boolean;
|
|
25
|
+
error?: string;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=git-integration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-integration.d.ts","sourceRoot":"","sources":["../src/git-integration.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA2E/C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration branch management for the git subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Handles syncing integration with main so agents start from the latest code.
|
|
5
|
+
* The daemon never touches main directly — the user merges integration into main.
|
|
6
|
+
*/
|
|
7
|
+
import { runGitSync } from './git-types.js';
|
|
8
|
+
import { withMergeLock } from './git-merge-lock.js';
|
|
9
|
+
import { getDefaultBranch } from './git-branch.js';
|
|
10
|
+
import { getMergeWorktreePath } from './worktree.js';
|
|
11
|
+
/**
|
|
12
|
+
* Sync the integration branch with main so agents start from the latest code.
|
|
13
|
+
*
|
|
14
|
+
* Uses a pre-flight check to avoid taking the merge lock when integration
|
|
15
|
+
* is already up-to-date with main. This prevents spawn operations from
|
|
16
|
+
* contending with merge completions in the common case.
|
|
17
|
+
*
|
|
18
|
+
* Steps:
|
|
19
|
+
* 1. Fetch origin to get latest remote state
|
|
20
|
+
* 2. Check if integration already contains main (skip if so)
|
|
21
|
+
* 3. Acquire merge lock only if sync is needed
|
|
22
|
+
* 4. Check out integration, merge main, push, restore
|
|
23
|
+
*
|
|
24
|
+
* Uses merge (not rebase) to preserve in-progress agent branch references.
|
|
25
|
+
*/
|
|
26
|
+
export async function syncIntegrationWithMain(config) {
|
|
27
|
+
const { repoPath, integrationBranch } = config;
|
|
28
|
+
const defaultBranch = getDefaultBranch(repoPath);
|
|
29
|
+
// No remote — nothing to sync from, local integration is the source of truth.
|
|
30
|
+
const hasOrigin = runGitSync(['remote', 'get-url', 'origin'], repoPath, { timeoutMs: 3_000 }).success;
|
|
31
|
+
if (!hasOrigin) {
|
|
32
|
+
return { success: true };
|
|
33
|
+
}
|
|
34
|
+
// Pre-flight: fetch and check if sync is actually needed.
|
|
35
|
+
// This runs outside the merge lock to avoid contention.
|
|
36
|
+
const fetchResult = runGitSync(['fetch', 'origin'], repoPath);
|
|
37
|
+
if (!fetchResult.success) {
|
|
38
|
+
return { success: false, error: `Fetch failed: ${fetchResult.error}` };
|
|
39
|
+
}
|
|
40
|
+
// Check if integration already contains all of origin/main.
|
|
41
|
+
// merge-base --is-ancestor returns 0 if main is ancestor of integration.
|
|
42
|
+
const ancestorCheck = runGitSync(['merge-base', '--is-ancestor', `origin/${defaultBranch}`, integrationBranch], repoPath);
|
|
43
|
+
if (ancestorCheck.success) {
|
|
44
|
+
// Integration already up-to-date with main -- no lock needed
|
|
45
|
+
return { success: true };
|
|
46
|
+
}
|
|
47
|
+
// Sync is needed -- acquire the merge lock
|
|
48
|
+
return withMergeLock(async () => {
|
|
49
|
+
const mwt = getMergeWorktreePath(config);
|
|
50
|
+
// Re-check after acquiring lock (another caller may have synced while we waited)
|
|
51
|
+
const recheck = runGitSync(['merge-base', '--is-ancestor', `origin/${defaultBranch}`, integrationBranch], repoPath);
|
|
52
|
+
if (recheck.success) {
|
|
53
|
+
return { success: true };
|
|
54
|
+
}
|
|
55
|
+
// Checkout integration branch in the merge worktree
|
|
56
|
+
const checkoutResult = runGitSync(['checkout', integrationBranch], mwt);
|
|
57
|
+
if (!checkoutResult.success) {
|
|
58
|
+
return { success: false, error: `Checkout integration failed: ${checkoutResult.error}` };
|
|
59
|
+
}
|
|
60
|
+
// Pull latest integration from remote (in case another daemon pushed)
|
|
61
|
+
runGitSync(['pull', 'origin', integrationBranch], mwt);
|
|
62
|
+
// Merge main into integration
|
|
63
|
+
const mergeResult = runGitSync(['merge', `origin/${defaultBranch}`, '-m', `Sync integration with ${defaultBranch}`], mwt);
|
|
64
|
+
if (!mergeResult.success) {
|
|
65
|
+
// Merge conflict during sync -- abort and report
|
|
66
|
+
runGitSync(['merge', '--abort'], mwt);
|
|
67
|
+
return {
|
|
68
|
+
success: false,
|
|
69
|
+
error: `Sync merge conflict (${defaultBranch} -> ${integrationBranch}): ${mergeResult.error}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Push updated integration to origin
|
|
73
|
+
const pushResult = runGitSync(['push', 'origin', integrationBranch], mwt);
|
|
74
|
+
if (!pushResult.success) {
|
|
75
|
+
console.warn(`Could not push synced integration to origin: ${pushResult.error}`);
|
|
76
|
+
// Non-fatal -- local sync still succeeded
|
|
77
|
+
}
|
|
78
|
+
console.log(`Synced ${integrationBranch} with ${defaultBranch}`);
|
|
79
|
+
return { success: true };
|
|
80
|
+
}, 'syncIntegrationWithMain');
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=git-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-integration.js","sourceRoot":"","sources":["../src/git-integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git merge helper functions.
|
|
3
|
+
*
|
|
4
|
+
* Low-level helpers for merge operations: remote detection, conflict
|
|
5
|
+
* extraction, rollback, untracked file handling, and push failure recovery.
|
|
6
|
+
*/
|
|
7
|
+
import { type MergeResult } from './git-types.js';
|
|
8
|
+
import { type CorruptionDetails } from './git-merge-lock.js';
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if the repo at repoPath has an 'origin' remote configured.
|
|
11
|
+
* Used to gate all network operations so the daemon works in remote-less repos.
|
|
12
|
+
*/
|
|
13
|
+
export declare function hasOriginRemote(repoPath: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Extract the list of conflicted files from git status.
|
|
16
|
+
* Returns an empty array if the command fails or there are no conflicts.
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractConflictedFiles(repoPath: string): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Hard-reset the current branch to a given ref.
|
|
21
|
+
* Returns whether the rollback succeeded.
|
|
22
|
+
*/
|
|
23
|
+
export declare function rollbackToRef(repoPath: string, ref: string): boolean;
|
|
24
|
+
interface PushFailureRollbackParams {
|
|
25
|
+
repoPath: string;
|
|
26
|
+
branch: string;
|
|
27
|
+
preMergeRef: string;
|
|
28
|
+
pushError: string;
|
|
29
|
+
sourceBranch: string;
|
|
30
|
+
targetBranch: string;
|
|
31
|
+
onRollbackFailure?: (details: CorruptionDetails) => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Handle a push failure with rollback. If rollback also fails, marks the
|
|
35
|
+
* branch as corrupt and returns a result indicating the failure.
|
|
36
|
+
*/
|
|
37
|
+
export declare function handlePushFailureWithRollback(params: PushFailureRollbackParams): MergeResult;
|
|
38
|
+
/**
|
|
39
|
+
* Handle untracked files that block a merge.
|
|
40
|
+
*
|
|
41
|
+
* When agents create new files (e.g. migrations) that also exist as
|
|
42
|
+
* untracked files in the main repo working directory, git refuses to
|
|
43
|
+
* merge. This helper parses the error output, removes the blocking
|
|
44
|
+
* files, and returns true if blocking files were cleaned.
|
|
45
|
+
*/
|
|
46
|
+
export declare function handleUntrackedFilesBlockingMerge(repoPath: string, errorOutput: string): boolean;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=git-merge-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-merge-helpers.d.ts","sourceRoot":"","sources":["../src/git-merge-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAErF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAMjE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGpE;AAED,UAAU,yBAAyB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC1D;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,yBAAyB,GAAG,WAAW,CA8C5F;AAED;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CA6BT"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git merge helper functions.
|
|
3
|
+
*
|
|
4
|
+
* Low-level helpers for merge operations: remote detection, conflict
|
|
5
|
+
* extraction, rollback, untracked file handling, and push failure recovery.
|
|
6
|
+
*/
|
|
7
|
+
import { runGitSync } from './git-types.js';
|
|
8
|
+
import { markIntegrationCorrupt } from './git-merge-lock.js';
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if the repo at repoPath has an 'origin' remote configured.
|
|
11
|
+
* Used to gate all network operations so the daemon works in remote-less repos.
|
|
12
|
+
*/
|
|
13
|
+
export function hasOriginRemote(repoPath) {
|
|
14
|
+
return runGitSync(['remote', 'get-url', 'origin'], repoPath, { timeoutMs: 3_000 }).success;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Extract the list of conflicted files from git status.
|
|
18
|
+
* Returns an empty array if the command fails or there are no conflicts.
|
|
19
|
+
*/
|
|
20
|
+
export function extractConflictedFiles(repoPath) {
|
|
21
|
+
const statusResult = runGitSync(['diff', '--name-only', '--diff-filter=U'], repoPath);
|
|
22
|
+
if (!statusResult.success) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
return statusResult.output.split('\n').filter(Boolean);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Hard-reset the current branch to a given ref.
|
|
29
|
+
* Returns whether the rollback succeeded.
|
|
30
|
+
*/
|
|
31
|
+
export function rollbackToRef(repoPath, ref) {
|
|
32
|
+
const result = runGitSync(['reset', '--hard', ref], repoPath);
|
|
33
|
+
return result.success;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Handle a push failure with rollback. If rollback also fails, marks the
|
|
37
|
+
* branch as corrupt and returns a result indicating the failure.
|
|
38
|
+
*/
|
|
39
|
+
export function handlePushFailureWithRollback(params) {
|
|
40
|
+
const { repoPath, branch, preMergeRef, pushError, sourceBranch, targetBranch, onRollbackFailure } = params;
|
|
41
|
+
console.error(`Push to origin failed for ${branch}: ${pushError}`);
|
|
42
|
+
const rollbackSuccess = rollbackToRef(repoPath, preMergeRef);
|
|
43
|
+
if (rollbackSuccess) {
|
|
44
|
+
console.log(`Rolled back local merge to ${preMergeRef.slice(0, 8)}`);
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
error: `Push failed (local merge rolled back): ${pushError}. Branch ${sourceBranch} preserved for retry.`,
|
|
48
|
+
sourceBranch,
|
|
49
|
+
targetBranch,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Rollback also failed -- mark as corrupt
|
|
53
|
+
const currentHeadResult = runGitSync(['rev-parse', 'HEAD'], repoPath);
|
|
54
|
+
const currentHead = currentHeadResult.success ? currentHeadResult.output : 'unknown';
|
|
55
|
+
const details = {
|
|
56
|
+
branch,
|
|
57
|
+
attemptedRollbackRef: preMergeRef,
|
|
58
|
+
currentHead,
|
|
59
|
+
};
|
|
60
|
+
markIntegrationCorrupt(details);
|
|
61
|
+
console.error(`[merge-lock] CRITICAL: Push failed AND rollback failed for "${branch}". ` +
|
|
62
|
+
`Branch is in a corrupt state. Attempted rollback to ${preMergeRef}, ` +
|
|
63
|
+
`current HEAD: ${currentHead}. All further merge operations will be rejected ` +
|
|
64
|
+
`until manual recovery and daemon restart.`);
|
|
65
|
+
if (onRollbackFailure) {
|
|
66
|
+
onRollbackFailure(details);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
success: false,
|
|
70
|
+
error: `Push failed AND rollback failed. Branch "${branch}" is corrupt. ` +
|
|
71
|
+
`Manual recovery required: git reset --hard origin/${branch}`,
|
|
72
|
+
sourceBranch,
|
|
73
|
+
targetBranch,
|
|
74
|
+
rollbackFailed: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Handle untracked files that block a merge.
|
|
79
|
+
*
|
|
80
|
+
* When agents create new files (e.g. migrations) that also exist as
|
|
81
|
+
* untracked files in the main repo working directory, git refuses to
|
|
82
|
+
* merge. This helper parses the error output, removes the blocking
|
|
83
|
+
* files, and returns true if blocking files were cleaned.
|
|
84
|
+
*/
|
|
85
|
+
export function handleUntrackedFilesBlockingMerge(repoPath, errorOutput) {
|
|
86
|
+
const isUntrackedBlock = errorOutput.includes('untracked working tree files would be overwritten') ||
|
|
87
|
+
errorOutput.includes('would be overwritten by merge');
|
|
88
|
+
if (!isUntrackedBlock) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
const lines = errorOutput.split('\n');
|
|
92
|
+
const blockingFiles = lines
|
|
93
|
+
.map((l) => l.trim())
|
|
94
|
+
.filter((l) => l &&
|
|
95
|
+
!l.startsWith('error:') &&
|
|
96
|
+
!l.startsWith('Please') &&
|
|
97
|
+
!l.startsWith('Aborting'));
|
|
98
|
+
if (blockingFiles.length === 0) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
console.log(`Removing ${blockingFiles.length} untracked file(s) blocking merge: ${blockingFiles.join(', ')}`);
|
|
102
|
+
runGitSync(['clean', '-f', '--', ...blockingFiles], repoPath);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=git-merge-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-merge-helpers.js","sourceRoot":"","sources":["../src/git-merge-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAoB,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAA0B,MAAM,qBAAqB,CAAC;AAErF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,UAAU,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;AAC7F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,CAAC,EAAE,QAAQ,CAAC,CAAC;IACtF,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,GAAW;IACzD,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAYD;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAAiC;IAC7E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAAC;IAC3G,OAAO,CAAC,KAAK,CAAC,6BAA6B,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;IAEnE,MAAM,eAAe,GAAG,aAAa,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC7D,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,8BAA8B,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,0CAA0C,SAAS,YAAY,YAAY,uBAAuB;YACzG,YAAY;YACZ,YAAY;SACb,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,MAAM,iBAAiB,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAErF,MAAM,OAAO,GAAsB;QACjC,MAAM;QACN,oBAAoB,EAAE,WAAW;QACjC,WAAW;KACZ,CAAC;IAEF,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CACX,+DAA+D,MAAM,KAAK;QAC1E,uDAAuD,WAAW,IAAI;QACtE,iBAAiB,WAAW,kDAAkD;QAC9E,2CAA2C,CAC5C,CAAC;IAEF,IAAI,iBAAiB,EAAE,CAAC;QACtB,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,4CAA4C,MAAM,gBAAgB;YACvE,qDAAqD,MAAM,EAAE;QAC/D,YAAY;QACZ,YAAY;QACZ,cAAc,EAAE,IAAI;KACrB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iCAAiC,CAC/C,QAAgB,EAChB,WAAmB;IAEnB,MAAM,gBAAgB,GACpB,WAAW,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QACzE,WAAW,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC;IAExD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,KAAK;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC;QACD,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC;QACvB,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC;QACvB,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAC5B,CAAC;IAEJ,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAAG,CACT,YAAY,aAAa,CAAC,MAAM,sCAAsC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjG,CAAC;IACF,UAAU,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge lock and corruption state management for the git subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Provides an in-process mutex to serialize operations that checkout/modify
|
|
5
|
+
* the integration or main branches. Only one such operation can run at a
|
|
6
|
+
* time since the daemon is a single Node.js process sharing one repo.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Error thrown when the merge lock cannot be acquired within the timeout.
|
|
10
|
+
*/
|
|
11
|
+
export declare class MergeLockTimeoutError extends Error {
|
|
12
|
+
constructor(label: string, timeoutMs: number);
|
|
13
|
+
}
|
|
14
|
+
/** Details of the corrupt integration branch, if any. */
|
|
15
|
+
export interface CorruptionDetails {
|
|
16
|
+
branch: string;
|
|
17
|
+
attemptedRollbackRef: string;
|
|
18
|
+
currentHead: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Error thrown when the integration branch is in a corrupt state.
|
|
22
|
+
*/
|
|
23
|
+
export declare class IntegrationCorruptError extends Error {
|
|
24
|
+
constructor(details: CorruptionDetails);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if the integration branch is in a corrupt state.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isIntegrationCorrupt(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get corruption details if the integration branch is corrupt.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getCorruptionDetails(): CorruptionDetails | null;
|
|
34
|
+
/**
|
|
35
|
+
* Reset the corruption flag. Exported for testing and manual recovery.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resetCorruptionFlag(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Mark the integration branch as corrupt. Called by merge operations
|
|
40
|
+
* when push fails and rollback also fails.
|
|
41
|
+
*/
|
|
42
|
+
export declare function markIntegrationCorrupt(details: CorruptionDetails): void;
|
|
43
|
+
/**
|
|
44
|
+
* Configure merge lock timeouts. Called during daemon initialization.
|
|
45
|
+
*/
|
|
46
|
+
export declare function configureMergeLock(config: {
|
|
47
|
+
timeoutMs: number;
|
|
48
|
+
contentionWarningMs: number;
|
|
49
|
+
}): void;
|
|
50
|
+
/**
|
|
51
|
+
* Acquire the merge lock, execute `fn`, then release.
|
|
52
|
+
* Callers are queued in FIFO order.
|
|
53
|
+
*
|
|
54
|
+
* Features:
|
|
55
|
+
* - Configurable acquisition timeout (rejects with MergeLockTimeoutError)
|
|
56
|
+
* - Contention logging with caller labels and wait durations
|
|
57
|
+
* - Rejects if integration branch is in corrupt state
|
|
58
|
+
*
|
|
59
|
+
* @param fn The function to execute while holding the lock
|
|
60
|
+
* @param label Optional caller label for contention logging (e.g. "mergeToIntegration:my-delivery")
|
|
61
|
+
*/
|
|
62
|
+
export declare function withMergeLock<T>(fn: () => Promise<T>, label?: string): Promise<T>;
|
|
63
|
+
/**
|
|
64
|
+
* Reset the merge lock state. Only for testing.
|
|
65
|
+
*/
|
|
66
|
+
export declare function resetMergeLock(): void;
|
|
67
|
+
//# sourceMappingURL=git-merge-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-merge-lock.d.ts","sourceRoot":"","sources":["../src/git-merge-lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAO7C;AASD,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAID;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,iBAAiB;CAUvC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,IAAI,CAE/D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAGvE;AAUD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,IAAI,CAEP;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,SAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAgEpF;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAKrC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge lock and corruption state management for the git subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Provides an in-process mutex to serialize operations that checkout/modify
|
|
5
|
+
* the integration or main branches. Only one such operation can run at a
|
|
6
|
+
* time since the daemon is a single Node.js process sharing one repo.
|
|
7
|
+
*/
|
|
8
|
+
// ── Merge lock ─────────────────────────────────────────────────────
|
|
9
|
+
let mergeLockPromise = Promise.resolve();
|
|
10
|
+
let mergeLockQueueDepth = 0;
|
|
11
|
+
/**
|
|
12
|
+
* Error thrown when the merge lock cannot be acquired within the timeout.
|
|
13
|
+
*/
|
|
14
|
+
export class MergeLockTimeoutError extends Error {
|
|
15
|
+
constructor(label, timeoutMs) {
|
|
16
|
+
super(`Merge lock acquisition timed out after ${timeoutMs}ms for "${label}". ` +
|
|
17
|
+
`Another operation may be holding the lock.`);
|
|
18
|
+
this.name = 'MergeLockTimeoutError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// ── Integration branch corrupt state ─────────────────────────────
|
|
22
|
+
// Set when a push fails AND the rollback also fails, leaving the
|
|
23
|
+
// local branch in a state that doesn't match remote. While set,
|
|
24
|
+
// all merge operations are rejected until daemon restart or manual fix.
|
|
25
|
+
let integrationBranchCorrupt = false;
|
|
26
|
+
let corruptionDetails = null;
|
|
27
|
+
/**
|
|
28
|
+
* Error thrown when the integration branch is in a corrupt state.
|
|
29
|
+
*/
|
|
30
|
+
export class IntegrationCorruptError extends Error {
|
|
31
|
+
constructor(details) {
|
|
32
|
+
super(`Integration branch "${details.branch}" is in a corrupt state. ` +
|
|
33
|
+
`Attempted rollback to ${details.attemptedRollbackRef} failed. ` +
|
|
34
|
+
`Current HEAD: ${details.currentHead}. ` +
|
|
35
|
+
`Manual recovery required (e.g. git reset --hard origin/${details.branch}). ` +
|
|
36
|
+
`Restart daemon after fixing.`);
|
|
37
|
+
this.name = 'IntegrationCorruptError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if the integration branch is in a corrupt state.
|
|
42
|
+
*/
|
|
43
|
+
export function isIntegrationCorrupt() {
|
|
44
|
+
return integrationBranchCorrupt;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get corruption details if the integration branch is corrupt.
|
|
48
|
+
*/
|
|
49
|
+
export function getCorruptionDetails() {
|
|
50
|
+
return corruptionDetails;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reset the corruption flag. Exported for testing and manual recovery.
|
|
54
|
+
*/
|
|
55
|
+
export function resetCorruptionFlag() {
|
|
56
|
+
integrationBranchCorrupt = false;
|
|
57
|
+
corruptionDetails = null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Mark the integration branch as corrupt. Called by merge operations
|
|
61
|
+
* when push fails and rollback also fails.
|
|
62
|
+
*/
|
|
63
|
+
export function markIntegrationCorrupt(details) {
|
|
64
|
+
integrationBranchCorrupt = true;
|
|
65
|
+
corruptionDetails = details;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Merge lock configuration. Must be set before first use via configureMergeLock().
|
|
69
|
+
*/
|
|
70
|
+
let mergeLockConfig = {
|
|
71
|
+
timeoutMs: 300000, // 5 minutes
|
|
72
|
+
contentionWarningMs: 30000, // 30 seconds
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Configure merge lock timeouts. Called during daemon initialization.
|
|
76
|
+
*/
|
|
77
|
+
export function configureMergeLock(config) {
|
|
78
|
+
mergeLockConfig = { ...config };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Acquire the merge lock, execute `fn`, then release.
|
|
82
|
+
* Callers are queued in FIFO order.
|
|
83
|
+
*
|
|
84
|
+
* Features:
|
|
85
|
+
* - Configurable acquisition timeout (rejects with MergeLockTimeoutError)
|
|
86
|
+
* - Contention logging with caller labels and wait durations
|
|
87
|
+
* - Rejects if integration branch is in corrupt state
|
|
88
|
+
*
|
|
89
|
+
* @param fn The function to execute while holding the lock
|
|
90
|
+
* @param label Optional caller label for contention logging (e.g. "mergeToIntegration:my-delivery")
|
|
91
|
+
*/
|
|
92
|
+
export function withMergeLock(fn, label = 'unknown') {
|
|
93
|
+
// Reject immediately if integration branch is corrupt
|
|
94
|
+
if (integrationBranchCorrupt && corruptionDetails) {
|
|
95
|
+
return Promise.reject(new IntegrationCorruptError(corruptionDetails));
|
|
96
|
+
}
|
|
97
|
+
let release;
|
|
98
|
+
const next = new Promise((resolve) => {
|
|
99
|
+
release = resolve;
|
|
100
|
+
});
|
|
101
|
+
const wait = mergeLockPromise;
|
|
102
|
+
mergeLockPromise = next;
|
|
103
|
+
const isContested = mergeLockQueueDepth > 0;
|
|
104
|
+
mergeLockQueueDepth++;
|
|
105
|
+
const enqueueTime = Date.now();
|
|
106
|
+
if (isContested) {
|
|
107
|
+
console.log(`[merge-lock] "${label}" waiting for lock (queue depth: ${mergeLockQueueDepth})`);
|
|
108
|
+
}
|
|
109
|
+
// Race the wait against a timeout
|
|
110
|
+
const timeoutMs = mergeLockConfig.timeoutMs;
|
|
111
|
+
let timedOut = false;
|
|
112
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
113
|
+
const timer = setTimeout(() => {
|
|
114
|
+
timedOut = true;
|
|
115
|
+
reject(new MergeLockTimeoutError(label, timeoutMs));
|
|
116
|
+
}, timeoutMs);
|
|
117
|
+
// Don't let the timeout timer keep the process alive
|
|
118
|
+
if (timer.unref)
|
|
119
|
+
timer.unref();
|
|
120
|
+
});
|
|
121
|
+
return Promise.race([wait, timeoutPromise]).then(async () => {
|
|
122
|
+
// Lock acquired
|
|
123
|
+
mergeLockQueueDepth--;
|
|
124
|
+
const waitMs = Date.now() - enqueueTime;
|
|
125
|
+
if (waitMs > mergeLockConfig.contentionWarningMs) {
|
|
126
|
+
console.warn(`[merge-lock] WARNING: "${label}" waited ${waitMs}ms to acquire lock ` +
|
|
127
|
+
`(threshold: ${mergeLockConfig.contentionWarningMs}ms)`);
|
|
128
|
+
}
|
|
129
|
+
else if (isContested) {
|
|
130
|
+
console.log(`[merge-lock] "${label}" acquired lock after ${waitMs}ms`);
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
return await fn();
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
release();
|
|
137
|
+
}
|
|
138
|
+
}, (err) => {
|
|
139
|
+
// On timeout, release the slot so subsequent callers aren't stuck
|
|
140
|
+
mergeLockQueueDepth--;
|
|
141
|
+
if (timedOut) {
|
|
142
|
+
// Still need to wait for our turn then release, so the chain isn't broken
|
|
143
|
+
wait.then(() => { release(); });
|
|
144
|
+
}
|
|
145
|
+
throw err;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Reset the merge lock state. Only for testing.
|
|
150
|
+
*/
|
|
151
|
+
export function resetMergeLock() {
|
|
152
|
+
mergeLockPromise = Promise.resolve();
|
|
153
|
+
mergeLockQueueDepth = 0;
|
|
154
|
+
integrationBranchCorrupt = false;
|
|
155
|
+
corruptionDetails = null;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=git-merge-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-merge-lock.js","sourceRoot":"","sources":["../src/git-merge-lock.ts"],"names":[],"mappings":"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"}
|