@telora/daemon 0.24.42 → 0.24.55
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/build-info.json +9 -3
- package/dist/completion/completion-event/unfinished-work.d.ts +3 -3
- package/dist/completion/review-cycle-budget/review-loop-detection.d.ts.map +1 -1
- package/dist/completion/review-cycle-budget/review-loop-detection.js +2 -1
- package/dist/completion/review-cycle-budget/review-loop-detection.js.map +1 -1
- package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts +1 -1
- package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts.map +1 -1
- package/dist/completion/review-exit-holds/review-exit-verdict-gate.js +2 -3
- package/dist/completion/review-exit-holds/review-exit-verdict-gate.js.map +1 -1
- package/dist/completion/state-cascade/focus-next-step-read.d.ts +38 -0
- package/dist/completion/state-cascade/focus-next-step-read.d.ts.map +1 -0
- package/dist/completion/state-cascade/focus-next-step-read.js +188 -0
- package/dist/completion/state-cascade/focus-next-step-read.js.map +1 -0
- package/dist/completion/state-cascade/review-request-gate.d.ts.map +1 -1
- package/dist/completion/state-cascade/review-request-gate.js +1 -0
- package/dist/completion/state-cascade/review-request-gate.js.map +1 -1
- package/dist/completion/state-cascade/review-request-next-step.d.ts +56 -0
- package/dist/completion/state-cascade/review-request-next-step.d.ts.map +1 -0
- package/dist/completion/state-cascade/review-request-next-step.js +47 -0
- package/dist/completion/state-cascade/review-request-next-step.js.map +1 -0
- package/dist/completion/state-cascade/review-verify-judgment-gate.d.ts +1 -1
- package/dist/completion/state-cascade/review-verify-judgment-gate.d.ts.map +1 -1
- package/dist/completion/state-cascade/review-verify-judgment-gate.js +1 -0
- package/dist/completion/state-cascade/review-verify-judgment-gate.js.map +1 -1
- package/dist/completion/state-cascade/state-cascade.d.ts +12 -7
- package/dist/completion/state-cascade/state-cascade.d.ts.map +1 -1
- package/dist/completion/state-cascade/state-cascade.js +36 -105
- package/dist/completion/state-cascade/state-cascade.js.map +1 -1
- package/dist/composition/commit-gate-context.d.ts.map +1 -1
- package/dist/composition/commit-gate-context.js +1 -0
- package/dist/composition/commit-gate-context.js.map +1 -1
- package/dist/composition/daemon-contexts.js +1 -1
- package/dist/composition/execution-migrations-context.d.ts.map +1 -1
- package/dist/composition/execution-migrations-context.js +3 -1
- package/dist/composition/execution-migrations-context.js.map +1 -1
- package/dist/composition/execution-process-context.js +1 -1
- package/dist/composition/execution-recovery-context.d.ts +4 -3
- package/dist/composition/execution-recovery-context.d.ts.map +1 -1
- package/dist/composition/execution-recovery-context.js +6 -3
- package/dist/composition/execution-recovery-context.js.map +1 -1
- package/dist/composition/execution-worktree-context.js +1 -1
- package/dist/composition/focus-next-step-context.d.ts +19 -0
- package/dist/composition/focus-next-step-context.d.ts.map +1 -0
- package/dist/composition/focus-next-step-context.js +51 -0
- package/dist/composition/focus-next-step-context.js.map +1 -0
- package/dist/composition/runtime-contexts.d.ts.map +1 -1
- package/dist/composition/runtime-contexts.js +6 -18
- package/dist/composition/runtime-contexts.js.map +1 -1
- package/dist/composition/runtime-poll-context.d.ts +8 -53
- package/dist/composition/runtime-poll-context.d.ts.map +1 -1
- package/dist/composition/runtime-poll-context.js +35 -94
- package/dist/composition/runtime-poll-context.js.map +1 -1
- package/dist/composition/runtime-prd-context.d.ts +8 -0
- package/dist/composition/runtime-prd-context.d.ts.map +1 -1
- package/dist/composition/runtime-prd-context.js +32 -0
- package/dist/composition/runtime-prd-context.js.map +1 -1
- package/dist/composition/runtime-spawn-pass-context.d.ts.map +1 -1
- package/dist/composition/runtime-spawn-pass-context.js +2 -3
- package/dist/composition/runtime-spawn-pass-context.js.map +1 -1
- package/dist/composition/state-cascade-context.d.ts +2 -0
- package/dist/composition/state-cascade-context.d.ts.map +1 -1
- package/dist/composition/state-cascade-context.js +9 -0
- package/dist/composition/state-cascade-context.js.map +1 -1
- package/dist/composition/verification-context.d.ts.map +1 -1
- package/dist/composition/verification-context.js +15 -3
- package/dist/composition/verification-context.js.map +1 -1
- package/dist/config/live-daemon-config.js +1 -1
- package/dist/daemon-state/branch-removal-record.d.ts +30 -0
- package/dist/daemon-state/branch-removal-record.d.ts.map +1 -0
- package/dist/daemon-state/branch-removal-record.js +103 -0
- package/dist/daemon-state/branch-removal-record.js.map +1 -0
- package/dist/delivery/advance-hold.d.ts +8 -19
- package/dist/delivery/advance-hold.d.ts.map +1 -1
- package/dist/delivery/advance-hold.js +11 -36
- package/dist/delivery/advance-hold.js.map +1 -1
- package/dist/delivery/commit-verdict-hold.d.ts +1 -1
- package/dist/delivery/commit-verdict-hold.js +1 -1
- package/dist/delivery/recorded-concerns.d.ts.map +1 -1
- package/dist/delivery/recorded-concerns.js +0 -2
- package/dist/delivery/recorded-concerns.js.map +1 -1
- package/dist/directive/directive-queue.d.ts +4 -16
- package/dist/directive/directive-queue.d.ts.map +1 -1
- package/dist/directive/directive-queue.js +5 -13
- package/dist/directive/directive-queue.js.map +1 -1
- package/dist/directive/phase-sync.d.ts +1 -1
- package/dist/directive/phase-sync.js +1 -1
- package/dist/focus/crash-recovery.d.ts +10 -32
- package/dist/focus/crash-recovery.d.ts.map +1 -1
- package/dist/focus/crash-recovery.js +55 -150
- package/dist/focus/crash-recovery.js.map +1 -1
- package/dist/focus/daemon-contexts-runtime.d.ts +3 -3
- package/dist/focus/daemon-contexts-runtime.d.ts.map +1 -1
- package/dist/focus/daemon-contexts.js +1 -1
- package/dist/focus/directive-executor.d.ts.map +1 -1
- package/dist/focus/directive-executor.js +3 -7
- package/dist/focus/directive-executor.js.map +1 -1
- package/dist/focus/failed-head-rework-start.d.ts +61 -0
- package/dist/focus/failed-head-rework-start.d.ts.map +1 -0
- package/dist/focus/failed-head-rework-start.js +52 -0
- package/dist/focus/failed-head-rework-start.js.map +1 -0
- package/dist/focus/focus-activity-record.d.ts +4 -2
- package/dist/focus/focus-activity-record.d.ts.map +1 -1
- package/dist/focus/focus-activity-record.js +4 -2
- package/dist/focus/focus-activity-record.js.map +1 -1
- package/dist/focus/focus-liveness-pass.d.ts +62 -0
- package/dist/focus/focus-liveness-pass.d.ts.map +1 -0
- package/dist/focus/focus-liveness-pass.js +197 -0
- package/dist/focus/focus-liveness-pass.js.map +1 -0
- package/dist/focus/focus-poller-spawn.js +1 -1
- package/dist/focus/focus-poller-state.js +1 -1
- package/dist/focus/live-branch-preservation.d.ts +123 -0
- package/dist/focus/live-branch-preservation.d.ts.map +1 -0
- package/dist/focus/live-branch-preservation.js +192 -0
- package/dist/focus/live-branch-preservation.js.map +1 -0
- package/dist/focus/migration-claim-pass.d.ts +2 -0
- package/dist/focus/migration-claim-pass.d.ts.map +1 -1
- package/dist/focus/migration-claim-pass.js +57 -22
- package/dist/focus/migration-claim-pass.js.map +1 -1
- package/dist/focus/migration-held-set-publish.d.ts +28 -2
- package/dist/focus/migration-held-set-publish.d.ts.map +1 -1
- package/dist/focus/migration-held-set-publish.js +14 -0
- package/dist/focus/migration-held-set-publish.js.map +1 -1
- package/dist/focus/pending-spawn-review-next-step.d.ts +5 -11
- package/dist/focus/pending-spawn-review-next-step.d.ts.map +1 -1
- package/dist/focus/pending-spawn-review-next-step.js +26 -72
- package/dist/focus/pending-spawn-review-next-step.js.map +1 -1
- package/dist/focus/review-refire-gate.d.ts +25 -0
- package/dist/focus/review-refire-gate.d.ts.map +1 -0
- package/dist/focus/review-refire-gate.js +68 -0
- package/dist/focus/review-refire-gate.js.map +1 -0
- package/dist/focus/verify-routing-passes.d.ts +8 -11
- package/dist/focus/verify-routing-passes.d.ts.map +1 -1
- package/dist/focus/verify-routing-passes.js +1 -2
- package/dist/focus/verify-routing-passes.js.map +1 -1
- package/dist/git/types.js +1 -1
- package/dist/prd/arm-refusal-streak.d.ts +102 -0
- package/dist/prd/arm-refusal-streak.d.ts.map +1 -0
- package/dist/prd/arm-refusal-streak.js +136 -0
- package/dist/prd/arm-refusal-streak.js.map +1 -0
- package/dist/prd/arm-refusal.d.ts.map +1 -1
- package/dist/prd/arm-refusal.js +7 -4
- package/dist/prd/arm-refusal.js.map +1 -1
- package/dist/prd/controller-shared.d.ts +40 -1
- package/dist/prd/controller-shared.d.ts.map +1 -1
- package/dist/prd/controller-shared.js +28 -2
- package/dist/prd/controller-shared.js.map +1 -1
- package/dist/prd/controller.d.ts.map +1 -1
- package/dist/prd/controller.js +3 -1
- package/dist/prd/controller.js.map +1 -1
- package/dist/prd/frontier-arming.d.ts +10 -2
- package/dist/prd/frontier-arming.d.ts.map +1 -1
- package/dist/prd/frontier-arming.js +91 -7
- package/dist/prd/frontier-arming.js.map +1 -1
- package/dist/prd/scoping-prompt.d.ts +8 -0
- package/dist/prd/scoping-prompt.d.ts.map +1 -1
- package/dist/prd/scoping-prompt.js +18 -0
- package/dist/prd/scoping-prompt.js.map +1 -1
- package/dist/prompt-sections/qa-failure-section.d.ts.map +1 -1
- package/dist/prompt-sections/qa-failure-section.js +3 -1
- package/dist/prompt-sections/qa-failure-section.js.map +1 -1
- package/dist/queries/api-client/shared.js +1 -1
- package/dist/queries/deliveries/deliveries.js +1 -1
- package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts +4 -3
- package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts.map +1 -1
- package/dist/queries/delivery-gate-state/delivery-gate-state.js +1 -1
- package/dist/queries/escalations/escalations.d.ts.map +1 -1
- package/dist/queries/escalations/escalations.js +0 -1
- package/dist/queries/escalations/escalations.js.map +1 -1
- package/dist/queries/escalations/incident-record.d.ts.map +1 -1
- package/dist/queries/escalations/incident-record.js +1 -0
- package/dist/queries/escalations/incident-record.js.map +1 -1
- package/dist/queries/focus-review/review-criterion-verdicts.d.ts.map +1 -1
- package/dist/queries/focus-review/review-criterion-verdicts.js +1 -0
- package/dist/queries/focus-review/review-criterion-verdicts.js.map +1 -1
- package/dist/queries/migrations/live-focus-branches.d.ts +23 -0
- package/dist/queries/migrations/live-focus-branches.d.ts.map +1 -1
- package/dist/queries/migrations/live-focus-branches.js +32 -1
- package/dist/queries/migrations/live-focus-branches.js.map +1 -1
- package/dist/queries/prd/prd.d.ts.map +1 -1
- package/dist/queries/prd/prd.js +1 -16
- package/dist/queries/prd/prd.js.map +1 -1
- package/dist/queries/qa-packets/focus-qa-failure.d.ts +18 -0
- package/dist/queries/qa-packets/focus-qa-failure.d.ts.map +1 -1
- package/dist/queries/qa-packets/focus-qa-failure.js +14 -1
- package/dist/queries/qa-packets/focus-qa-failure.js.map +1 -1
- package/dist/queries/tower-decisions/tower-decisions.d.ts.map +1 -1
- package/dist/queries/tower-decisions/tower-decisions.js +1 -0
- package/dist/queries/tower-decisions/tower-decisions.js.map +1 -1
- package/dist/queries/verification/verification.d.ts +10 -0
- package/dist/queries/verification/verification.d.ts.map +1 -1
- package/dist/queries/verification/verification.js +1 -1
- package/dist/queries/verification/verification.js.map +1 -1
- package/dist/supervision/escalation-suppression.js +1 -1
- package/dist/supervision/failed-head-rerun.d.ts +7 -0
- package/dist/supervision/failed-head-rerun.d.ts.map +1 -0
- package/dist/supervision/failed-head-rerun.js +41 -0
- package/dist/supervision/failed-head-rerun.js.map +1 -0
- package/dist/supervision/focus-delivery-aggregate-phase.js +1 -1
- package/dist/supervision/focus-delivery-aggregate-phase.js.map +1 -1
- package/dist/supervision/focus-liveness.d.ts +89 -0
- package/dist/supervision/focus-liveness.d.ts.map +1 -0
- package/dist/supervision/focus-liveness.js +94 -0
- package/dist/supervision/focus-liveness.js.map +1 -0
- package/dist/supervision/focus-next-step.d.ts +175 -0
- package/dist/supervision/focus-next-step.d.ts.map +1 -0
- package/dist/supervision/focus-next-step.js +129 -0
- package/dist/supervision/focus-next-step.js.map +1 -0
- package/dist/supervision/prd-frontier-rule.d.ts +52 -0
- package/dist/supervision/prd-frontier-rule.d.ts.map +1 -0
- package/dist/supervision/prd-frontier-rule.js +51 -0
- package/dist/supervision/prd-frontier-rule.js.map +1 -0
- package/dist/supervision/prt-frontier.d.ts +22 -7
- package/dist/supervision/prt-frontier.d.ts.map +1 -1
- package/dist/supervision/prt-frontier.js +17 -7
- package/dist/supervision/prt-frontier.js.map +1 -1
- package/dist/supervision/review-loop-detector.d.ts.map +1 -1
- package/dist/supervision/review-loop-detector.js +2 -1
- package/dist/supervision/review-loop-detector.js.map +1 -1
- package/dist/supervision/spawn-cooldown.js +1 -1
- package/dist/supervision/stop-registry.d.ts +1 -0
- package/dist/supervision/stop-registry.d.ts.map +1 -1
- package/dist/supervision/stop-rows-focus-health.d.ts +14 -0
- package/dist/supervision/stop-rows-focus-health.d.ts.map +1 -1
- package/dist/supervision/stop-rows-focus-health.js +32 -0
- package/dist/supervision/stop-rows-focus-health.js.map +1 -1
- package/dist/supervision/stop-rows-spawn.d.ts +3 -2
- package/dist/supervision/stop-rows-spawn.d.ts.map +1 -1
- package/dist/supervision/stop-rows-spawn.js +9 -6
- package/dist/supervision/stop-rows-spawn.js.map +1 -1
- package/dist/supervision/team-work.js +1 -1
- package/dist/supervision/team-work.js.map +1 -1
- package/dist/testing/fixtures/api-client.js +1 -1
- package/dist/testing/fixtures/index.js +1 -1
- package/dist/testing/fixtures/migration-namespace-repo.d.ts.map +1 -1
- package/dist/testing/fixtures/migration-namespace-repo.js +1 -0
- package/dist/testing/fixtures/migration-namespace-repo.js.map +1 -1
- package/dist/testing/fixtures/pending-spawn-world.d.ts +24 -0
- package/dist/testing/fixtures/pending-spawn-world.d.ts.map +1 -1
- package/dist/testing/fixtures/pending-spawn-world.js +46 -19
- package/dist/testing/fixtures/pending-spawn-world.js.map +1 -1
- package/dist/testing/fixtures/recording-api-client.js +1 -1
- package/dist/testing/fixtures/verification-deps.d.ts +27 -0
- package/dist/testing/fixtures/verification-deps.d.ts.map +1 -1
- package/dist/testing/fixtures/verification-deps.js +77 -1
- package/dist/testing/fixtures/verification-deps.js.map +1 -1
- package/dist/testing/fixtures/vitest-failure-log.d.ts.map +1 -1
- package/dist/testing/fixtures/vitest-failure-log.js +1 -0
- package/dist/testing/fixtures/vitest-failure-log.js.map +1 -1
- package/dist/tower/tower-supervisor-history.d.ts.map +1 -1
- package/dist/tower/tower-supervisor-history.js +2 -1
- package/dist/tower/tower-supervisor-history.js.map +1 -1
- package/dist/tower/tower-supervisor-prompt.d.ts.map +1 -1
- package/dist/tower/tower-supervisor-prompt.js +40 -8
- package/dist/tower/tower-supervisor-prompt.js.map +1 -1
- package/dist/tower/tower-supervisor-session.d.ts.map +1 -1
- package/dist/tower/tower-supervisor-session.js +1 -0
- package/dist/tower/tower-supervisor-session.js.map +1 -1
- package/dist/types/issue-status.d.ts.map +1 -1
- package/dist/types/issue-status.js +6 -1
- package/dist/types/issue-status.js.map +1 -1
- package/dist/verify/attribution/code-failure-evidence.d.ts +77 -0
- package/dist/verify/attribution/code-failure-evidence.d.ts.map +1 -0
- package/dist/verify/attribution/code-failure-evidence.js +92 -0
- package/dist/verify/attribution/code-failure-evidence.js.map +1 -0
- package/dist/verify/attribution/verification-attribution.d.ts +18 -0
- package/dist/verify/attribution/verification-attribution.d.ts.map +1 -1
- package/dist/verify/attribution/verification-attribution.js +49 -2
- package/dist/verify/attribution/verification-attribution.js.map +1 -1
- package/dist/verify/attribution/verification-baseline.d.ts.map +1 -1
- package/dist/verify/attribution/verification-baseline.js +1 -0
- package/dist/verify/attribution/verification-baseline.js.map +1 -1
- package/dist/verify/attribution/verification-diagnostics.d.ts +10 -0
- package/dist/verify/attribution/verification-diagnostics.d.ts.map +1 -1
- package/dist/verify/attribution/verification-diagnostics.js +39 -10
- package/dist/verify/attribution/verification-diagnostics.js.map +1 -1
- package/dist/verify/deterministic-gate/verification-deterministic.d.ts +19 -0
- package/dist/verify/deterministic-gate/verification-deterministic.d.ts.map +1 -1
- package/dist/verify/deterministic-gate/verification-deterministic.js +1 -1
- package/dist/verify/deterministic-gate/verification-deterministic.js.map +1 -1
- package/dist/verify/engine/verification-commit-sharing.d.ts.map +1 -1
- package/dist/verify/engine/verification-commit-sharing.js +36 -4
- package/dist/verify/engine/verification-commit-sharing.js.map +1 -1
- package/dist/verify/engine/verification-deps.d.ts +7 -0
- package/dist/verify/engine/verification-deps.d.ts.map +1 -1
- package/dist/verify/engine/verification-engine.d.ts.map +1 -1
- package/dist/verify/engine/verification-engine.js +6 -3
- package/dist/verify/engine/verification-engine.js.map +1 -1
- package/dist/verify/escaped-tests/escaped-test-run.d.ts +5 -1
- package/dist/verify/escaped-tests/escaped-test-run.d.ts.map +1 -1
- package/dist/verify/escaped-tests/escaped-test-run.js +24 -2
- package/dist/verify/escaped-tests/escaped-test-run.js.map +1 -1
- package/dist/verify/failing-test-rerun/failing-test-retry.d.ts +4 -1
- package/dist/verify/failing-test-rerun/failing-test-retry.d.ts.map +1 -1
- package/dist/verify/failing-test-rerun/failing-test-retry.js.map +1 -1
- package/dist/verify/gate-verdicts/commit-verdict-record.js +1 -1
- package/dist/verify/gate-verdicts/commit-verdict-record.js.map +1 -1
- package/dist/verify/gate-verdicts/no-verdict-record.d.ts +27 -3
- package/dist/verify/gate-verdicts/no-verdict-record.d.ts.map +1 -1
- package/dist/verify/gate-verdicts/no-verdict-record.js +36 -6
- package/dist/verify/gate-verdicts/no-verdict-record.js.map +1 -1
- package/dist/verify/outcome-routing/verification-rework-issue.d.ts.map +1 -1
- package/dist/verify/outcome-routing/verification-rework-issue.js +5 -4
- package/dist/verify/outcome-routing/verification-rework-issue.js.map +1 -1
- package/dist/verify/run-selection/default-on-guards.d.ts +15 -4
- package/dist/verify/run-selection/default-on-guards.d.ts.map +1 -1
- package/dist/verify/run-selection/default-on-guards.js +14 -4
- package/dist/verify/run-selection/default-on-guards.js.map +1 -1
- package/dist/verify/run-selection/explicit-next-step-gate.d.ts +39 -0
- package/dist/verify/run-selection/explicit-next-step-gate.d.ts.map +1 -0
- package/dist/verify/run-selection/explicit-next-step-gate.js +70 -0
- package/dist/verify/run-selection/explicit-next-step-gate.js.map +1 -0
- package/dist/verify/run-selection/pre-review-gate-dispatch.d.ts +0 -9
- package/dist/verify/run-selection/pre-review-gate-dispatch.d.ts.map +1 -1
- package/dist/verify/run-selection/pre-review-gate-dispatch.js +21 -62
- package/dist/verify/run-selection/pre-review-gate-dispatch.js.map +1 -1
- package/dist/verify/run-selection/reselection-log-line.d.ts +1 -1
- package/dist/verify/run-selection/reselection-log-line.d.ts.map +1 -1
- package/dist/verify/run-selection/reselection-log-line.js +2 -0
- package/dist/verify/run-selection/reselection-log-line.js.map +1 -1
- package/dist/verify/run-selection/verification-default-on.d.ts +32 -4
- package/dist/verify/run-selection/verification-default-on.d.ts.map +1 -1
- package/dist/verify/run-selection/verification-default-on.js +83 -19
- package/dist/verify/run-selection/verification-default-on.js.map +1 -1
- package/dist/verify/shortfalls/shortfall-park.js +1 -1
- package/dist/worktree/focus-worktree-state.js +1 -1
- package/dist/worktree/focus-worktree-state.js.map +1 -1
- package/package.json +3 -3
- package/dist/completion/state-cascade/review-next-step.d.ts +0 -107
- package/dist/completion/state-cascade/review-next-step.d.ts.map +0 -1
- package/dist/completion/state-cascade/review-next-step.js +0 -90
- package/dist/completion/state-cascade/review-next-step.js.map +0 -1
- package/dist/focus/failed-head-wedge.d.ts +0 -124
- package/dist/focus/failed-head-wedge.d.ts.map +0 -1
- package/dist/focus/failed-head-wedge.js +0 -120
- package/dist/focus/failed-head-wedge.js.map +0 -1
- package/dist/focus/stranded-review-reroute.d.ts +0 -70
- package/dist/focus/stranded-review-reroute.d.ts.map +0 -1
- package/dist/focus/stranded-review-reroute.js +0 -193
- package/dist/focus/stranded-review-reroute.js.map +0 -1
- package/dist/focus/uncommitted-work-backstop.d.ts +0 -115
- package/dist/focus/uncommitted-work-backstop.d.ts.map +0 -1
- package/dist/focus/uncommitted-work-backstop.js +0 -259
- package/dist/focus/uncommitted-work-backstop.js.map +0 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/focus/focus-liveness-pass.test.ts,
|
|
3
|
+
// packages/daemon/src/integration/failed-verdict-review-exit-respawn-regression.test.ts,
|
|
4
|
+
// packages/daemon/src/integration/failed-verdict-review-loop-regression.test.ts
|
|
5
|
+
// PINNED-BY-END
|
|
6
|
+
/**
|
|
7
|
+
* The liveness pass: each poll, every ARMED focus of one product (role set, not
|
|
8
|
+
* operator-stopped, not read-only) has its one next step read
|
|
9
|
+
* (supervision/focus-next-step.ts) and counted by the liveness detector
|
|
10
|
+
* (supervision/focus-liveness.ts), and the pass does what the detector says:
|
|
11
|
+
* - start_coding: start the coding team the step names -- for a failed HEAD's
|
|
12
|
+
* rework, first make it startable: file the HEAD's rework Bug, or re-open the
|
|
13
|
+
* done or paused delivery carrying it (focus/failed-head-rework-start.ts), and
|
|
14
|
+
* close a review window still open over that HEAD (the decision says no review
|
|
15
|
+
* serves it, and the open-work pass routes nothing while it stays open) --
|
|
16
|
+
* and queue ONE daemon coding respawn of the focus's own lineage, naming the
|
|
17
|
+
* decided reason (and the uncommitted paths, when that is the reason), never
|
|
18
|
+
* over a spawn directive already queued. A rework that could not be made
|
|
19
|
+
* startable queues nothing and is asked for again next poll, until its Bug is
|
|
20
|
+
* filed or re-opened (the retired failed-head wedge retried the same way);
|
|
21
|
+
* - report: file ONE agent-resolvable observation for the stalled key, carrying
|
|
22
|
+
* a deterministic cause_key so incident correlation records it once; a filing
|
|
23
|
+
* that fails is reported again next poll.
|
|
24
|
+
* It replaces the per-shape backstops it was built over -- the failed-head wedge,
|
|
25
|
+
* the uncommitted-work backstop and the stranded-review reroute: each of their
|
|
26
|
+
* stalls is a decided actor that did not move the focus.
|
|
27
|
+
*
|
|
28
|
+
* A stranded-work record the retired uncommitted-work backstop left on a delivery
|
|
29
|
+
* (delivery/advance-hold.ts STRANDED_WORK_REASON) is cleared here once the
|
|
30
|
+
* worktree reads clean, so the dashboard's Waiting-on line does not keep it.
|
|
31
|
+
*
|
|
32
|
+
* Best-effort: every failure is logged and the next poll retries.
|
|
33
|
+
*
|
|
34
|
+
* @module focus/focus-liveness-pass
|
|
35
|
+
*/
|
|
36
|
+
import { createHash } from 'node:crypto';
|
|
37
|
+
import { ESCALATION_REASONS } from '@telora/daemon-core';
|
|
38
|
+
import { focusPipelineModelForPass } from '../config/model-resolution.js';
|
|
39
|
+
import { DISPOSITION_AGENT_RESOLVABLE } from '../queries/escalations/escalation-dispositions.js';
|
|
40
|
+
import { computeCauseKey } from '../queries/escalations/cause-key.js';
|
|
41
|
+
import { describeFocusNextStep } from '../supervision/focus-next-step.js';
|
|
42
|
+
import { forgetFocusLiveness, observeFocusLiveness, unmarkFocusLivenessCodingStarted, unmarkFocusLivenessReported, LIVENESS_MERGE_STALL_POLLS, LIVENESS_STALL_POLLS, LIVENESS_STALL_STARTS, } from '../supervision/focus-liveness.js';
|
|
43
|
+
import { hasStrandedWorkRecord } from '../delivery/advance-hold.js';
|
|
44
|
+
import { createLogger } from '../log/daemon-log.js';
|
|
45
|
+
const log = createLogger({ module: 'focus-poller' });
|
|
46
|
+
/** metadata.cause on the stall observation. */
|
|
47
|
+
export const FOCUS_NEXT_ACTOR_STALLED_CAUSE = 'focus_next_actor_stalled';
|
|
48
|
+
/** At most this many uncommitted paths are named in a respawn; the count carries the rest. */
|
|
49
|
+
export const LIVENESS_PATH_CAP = 20;
|
|
50
|
+
const isArmed = (f) => !!f.assigned_agent_role_id && !f.operator_stopped_at && f.read_only !== true;
|
|
51
|
+
/** The respawn message: the decided step, and the paths when the reason is uncommitted work. */
|
|
52
|
+
export function buildLivenessRespawnMessage(focusName, next, paths) {
|
|
53
|
+
const lines = [
|
|
54
|
+
`The focus "${focusName}" has a coding team as its next step (${describeFocusNextStep(next)}), and none has started.`,
|
|
55
|
+
];
|
|
56
|
+
if (next.step === 'coding' && next.reason === 'uncommitted_work' && paths.length > 0) {
|
|
57
|
+
const named = paths.slice(0, LIVENESS_PATH_CAP).map((p) => `- ${p}`);
|
|
58
|
+
const more = paths.length > LIVENESS_PATH_CAP ? [`- ... and ${paths.length - LIVENESS_PATH_CAP} more`] : [];
|
|
59
|
+
lines.push('', 'Its worktree holds uncommitted work -- the gate and the review judge commits, so nothing else can see it:', ...named, ...more, '', 'Finish it and commit it (with the Telora-Delivery trailer of the delivery it belongs to), or discard what is not wanted.');
|
|
60
|
+
}
|
|
61
|
+
else if (next.step === 'coding' && next.reason.startsWith('gate_rework')) {
|
|
62
|
+
lines.push('', 'The gate FAILED at the focus HEAD. Read the failure on the HEAD\'s rework Bug (title "Verify gate failed at <sha>:"), '
|
|
63
|
+
+ 're-open it if it was closed with no commit, fix the failure and commit.');
|
|
64
|
+
}
|
|
65
|
+
return lines.join('\n');
|
|
66
|
+
}
|
|
67
|
+
/** The ONE observation a stalled key owes (agent-resolvable; its cause_key keys the stalled step and HEAD). */
|
|
68
|
+
export function buildFocusStallObservation(organizationId, focus, stall, next, head) {
|
|
69
|
+
const at = head ? head.slice(0, 12) : '<unreadable HEAD>';
|
|
70
|
+
return {
|
|
71
|
+
organizationId,
|
|
72
|
+
issueId: null,
|
|
73
|
+
reasonType: ESCALATION_REASONS.ERROR_ENCOUNTERED,
|
|
74
|
+
disposition: DISPOSITION_AGENT_RESOLVABLE,
|
|
75
|
+
anchor: { focusId: focus.focus_id },
|
|
76
|
+
metadata: {
|
|
77
|
+
cause: FOCUS_NEXT_ACTOR_STALLED_CAUSE,
|
|
78
|
+
cause_key: computeCauseKey(FOCUS_NEXT_ACTOR_STALLED_CAUSE, { focusId: focus.focus_id, step: stall.step, head: head ?? 'unreadable' }),
|
|
79
|
+
step: stall.step,
|
|
80
|
+
next_step: describeFocusNextStep(next),
|
|
81
|
+
head,
|
|
82
|
+
not_started_polls: stall.notStartedPolls,
|
|
83
|
+
starts: stall.starts,
|
|
84
|
+
},
|
|
85
|
+
description: `Armed focus "${focus.focus_name}" is not moving: its next step is ${describeFocusNextStep(next)} at HEAD ${at}, and ` +
|
|
86
|
+
(stall.starts >= LIVENESS_STALL_STARTS
|
|
87
|
+
? `that actor started ${stall.starts} times without the focus moving (no new commit, no new step).`
|
|
88
|
+
: `that actor has not started for ${stall.notStartedPolls} polls (bound ${stall.step === 'merge' ? LIVENESS_MERGE_STALL_POLLS : LIVENESS_STALL_POLLS}).`),
|
|
89
|
+
whatWasTried: 'The liveness detector read the focus\'s one next step every poll (supervision/focus-next-step.ts); a coding step ' +
|
|
90
|
+
'that did not start was given one daemon coding respawn.',
|
|
91
|
+
helpNeeded: 'Find what keeps that actor from starting or from moving the focus (daemon log: [focus-poller], [state-cascade], ' +
|
|
92
|
+
'[verification] lines for this focus) and clear it -- e.g. re-open or file the HEAD\'s rework Bug, commit or discard ' +
|
|
93
|
+
'uncommitted work, or close a review window that cannot route (telora_product_focus update clearReviewRequest).',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function fileStall(organizationId, focus, stall, next, head, deps) {
|
|
97
|
+
try {
|
|
98
|
+
await deps.createEscalation(buildFocusStallObservation(organizationId, focus, stall, next, head));
|
|
99
|
+
log.warn(`[focus-poller] "${focus.focus_name}" is not moving: ${describeFocusNextStep(next)} at ${head?.slice(0, 12) ?? '?'} -- observation filed`);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
unmarkFocusLivenessReported(focus.focus_id, stall.key);
|
|
103
|
+
log.warn(`[focus-poller] "${focus.focus_name}": liveness observation not recorded (retried next poll): ${err.message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A failed HEAD's rework needs its Bug on a routable delivery, and no review window holding its delivery in verify,
|
|
108
|
+
* before a coding team has it to work. False when that could not be made so.
|
|
109
|
+
*/
|
|
110
|
+
async function prepareRework(focus, next, head, deps) {
|
|
111
|
+
if (next.step !== 'coding' || !next.reason.startsWith('gate_rework'))
|
|
112
|
+
return true;
|
|
113
|
+
try {
|
|
114
|
+
if (focus.review_requested_at) {
|
|
115
|
+
await deps.closeReviewWindow(focus.focus_id);
|
|
116
|
+
log.info(`[focus-poller] "${focus.focus_name}": closed the review window over its failed HEAD -- its rework, not a review, is next`);
|
|
117
|
+
}
|
|
118
|
+
if (next.reason === 'gate_rework_unanswered' || !head || !focus.product_id)
|
|
119
|
+
return true;
|
|
120
|
+
const start = await deps.startFailedHeadRework({ focusId: focus.focus_id, productId: focus.product_id, head });
|
|
121
|
+
if (!start.ready) {
|
|
122
|
+
log.warn(`[focus-poller] "${focus.focus_name}": failed HEAD ${head.slice(0, 12)} -- ${start.did}; no coding team queued, retried next poll`);
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
log.info(`[focus-poller] "${focus.focus_name}": failed HEAD ${head.slice(0, 12)} -- ${start.did}`);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
log.warn(`[focus-poller] "${focus.focus_name}": failed HEAD rework not made startable -- no coding team queued; retried next poll: ${err.message}`);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function startCoding(focus, next, head, key, deps) {
|
|
134
|
+
if (!(await prepareRework(focus, next, head, deps))) {
|
|
135
|
+
unmarkFocusLivenessCodingStarted(focus.focus_id, key);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const paths = next.step === 'coding' && next.reason === 'uncommitted_work' ? deps.listUncommittedPaths(focus.focus_id) : [];
|
|
139
|
+
const message = buildLivenessRespawnMessage(focus.focus_name, next, paths);
|
|
140
|
+
const queued = deps.queueCodingRespawn({
|
|
141
|
+
focusId: focus.focus_id,
|
|
142
|
+
message,
|
|
143
|
+
contentHash: createHash('sha256').update(message).digest('hex'),
|
|
144
|
+
focusOverrideModel: focusPipelineModelForPass(focus.pipeline_config, 'coding'),
|
|
145
|
+
});
|
|
146
|
+
log.info(`[focus-poller] "${focus.focus_name}": ${describeFocusNextStep(next)} has not started -- ` +
|
|
147
|
+
(queued ? 'queued a coding respawn' : 'a spawn directive is already queued'));
|
|
148
|
+
}
|
|
149
|
+
/** Clear a stranded-work record left on a delivery once the worktree reads clean (module header). */
|
|
150
|
+
async function clearStaleStrandedWork(focus, deliveries, deps) {
|
|
151
|
+
for (const d of deliveries.filter((x) => hasStrandedWorkRecord(x.gateState))) {
|
|
152
|
+
await deps.clearStrandedWorkRecord(d.id).catch((err) => log.warn(`[focus-poller] "${focus.focus_name}": stranded-work record on ${d.id} not cleared (retried next poll): ${err.message}`));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async function observeFocus(organizationId, focus, deps) {
|
|
156
|
+
const read = await deps.readNextStep(focus);
|
|
157
|
+
if (!read.readable) {
|
|
158
|
+
forgetFocusLiveness(focus.focus_id);
|
|
159
|
+
return { act: 'none' };
|
|
160
|
+
}
|
|
161
|
+
if (!read.facts.uncommittedWork)
|
|
162
|
+
await clearStaleStrandedWork(focus, read.deliveries, deps);
|
|
163
|
+
const act = observeFocusLiveness({ focusId: focus.focus_id, next: read.next, head: read.head, reviewWindow: focus.review_requested_at });
|
|
164
|
+
if (act.act === 'start_coding')
|
|
165
|
+
await startCoding(focus, read.next, read.head, act.key, deps);
|
|
166
|
+
if (act.act === 'report')
|
|
167
|
+
await fileStall(organizationId, focus, act, read.next, read.head, deps);
|
|
168
|
+
return act;
|
|
169
|
+
}
|
|
170
|
+
/** The liveness pass over one product's active focuses (module header). Never throws. */
|
|
171
|
+
export async function detectFocusLivenessStalls(config, deps) {
|
|
172
|
+
let focuses;
|
|
173
|
+
try {
|
|
174
|
+
focuses = await deps.getActiveFocuses(config.organizationId, config.productId);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
log.warn(`[focus-poller] liveness pass: active focuses unreadable (retried next poll): ${err.message}`);
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
const acts = [];
|
|
181
|
+
for (const focus of focuses) {
|
|
182
|
+
if (!isArmed(focus)) {
|
|
183
|
+
forgetFocusLiveness(focus.focus_id);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const act = await observeFocus(config.organizationId, focus, deps);
|
|
188
|
+
if (act.act !== 'none')
|
|
189
|
+
acts.push({ focusId: focus.focus_id, act });
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
log.warn(`[focus-poller] liveness pass failed for "${focus.focus_name}" (retried next poll): ${err.message}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return acts;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=focus-liveness-pass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus-liveness-pass.js","sourceRoot":"","sources":["../../src/focus/focus-liveness-pass.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
-
// Pinned by:
|
|
2
|
+
// Pinned by: 28 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/focus/focus-poller-spawn.ts
|
|
3
3
|
// PINNED-BY-END
|
|
4
4
|
import { resolveReadyFocusSpawnAction } from './ready-focus-spawn-action.js';
|
|
5
5
|
import { roles, pollState, idleLoggedFocuses, nullRoleSkipWarnedFocuses, lastRolesRefreshAt, healthCheckConsecutiveFailures, POLL_INTERVAL_MS, ROLES_REFRESH_INTERVAL_MS, setPollState, setLastRolesRefreshAt, setLastReadyFocusCount, } from './focus-poller-state.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
-
// Pinned by:
|
|
2
|
+
// Pinned by: 26 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/focus/focus-poller-state.ts
|
|
3
3
|
// PINNED-BY-END
|
|
4
4
|
/** Polling interval in milliseconds (default: 30 seconds). */
|
|
5
5
|
export const POLL_INTERVAL_MS = 30000;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What crash recovery must NOT remove, and the stale-branch pruner that obeys it.
|
|
3
|
+
*
|
|
4
|
+
* ONE RULE FOR WHICH FOCUS BRANCHES ARE LIVE. The migration allocator (the
|
|
5
|
+
* held-set publisher and the grant handler's coverage check) treats every focus
|
|
6
|
+
* with a branch and a status other than complete or cancelled as live -- armed
|
|
7
|
+
* or not -- and requires that branch in every held set. A merged branch is not
|
|
8
|
+
* a dead one: a finished focus still active (awaiting QA, its arm cleared at
|
|
9
|
+
* run end) has a branch fully contained in integration that the allocator still
|
|
10
|
+
* requires. Deleting it refuses every migration claim on the product.
|
|
11
|
+
*
|
|
12
|
+
* So recovery reads the SAME population (queries/migrations/live-focus-branches.ts,
|
|
13
|
+
* canonical src/lib/vocabulary/migration-branch-population.ts) plus every
|
|
14
|
+
* pending completion merge, once per pass, and both the classifier
|
|
15
|
+
* (focus/crash-recovery.ts) and the pruner here keep what it names. An
|
|
16
|
+
* unreadable population removes nothing.
|
|
17
|
+
*
|
|
18
|
+
* History: docs/daemon/history-platform.md (focus/live-branch-preservation.ts).
|
|
19
|
+
*
|
|
20
|
+
* @module focus/live-branch-preservation
|
|
21
|
+
*/
|
|
22
|
+
import type { DaemonConfig } from '../types/index.js';
|
|
23
|
+
import type { LiveFocusBranch } from '../queries/migrations/live-focus-branches.js';
|
|
24
|
+
/** What the live population is read through (a subset of RecoveryDeps). */
|
|
25
|
+
export interface LiveBranchPreservationDeps {
|
|
26
|
+
/**
|
|
27
|
+
* The product's LIVE focus branches with their owning focuses: every focus
|
|
28
|
+
* with a branch whose status is not complete or cancelled, armed or not
|
|
29
|
+
* (queries/migrations/live-focus-branches.ts -- the rule the migration
|
|
30
|
+
* allocator and the grant handler read). Deliberately NOT getActiveFocuses,
|
|
31
|
+
* the spawn set. A rejection means the population is unknown, and nothing is
|
|
32
|
+
* removed.
|
|
33
|
+
*/
|
|
34
|
+
listLiveFocusBranches: (productId: string) => Promise<LiveFocusBranch[]>;
|
|
35
|
+
/**
|
|
36
|
+
* The focus ids this host holds a pending completion merge for
|
|
37
|
+
* (merge/completion-hold-record.ts). Their worktrees are NOT orphans even when
|
|
38
|
+
* the focus has left the live set: the completed work still has to reach
|
|
39
|
+
* integration, and the merge-back loop drives it from that worktree.
|
|
40
|
+
*/
|
|
41
|
+
listPendingCompletionFocusIds: (productId: string) => string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract the focus ID prefix (last 8 hex chars) from a worktree directory name.
|
|
45
|
+
* Focus worktree directories follow: agent-{role}-{name}-{8-char-id}
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractFocusIdPrefix(dirName: string): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Extract the 8-char focus-key suffix from an agent BRANCH name.
|
|
50
|
+
* Branch format: agent/<role>/<slug>-<8hexfocuskey>. The final path segment
|
|
51
|
+
* carries the same -<8hex> suffix that extractFocusIdPrefix parses off the
|
|
52
|
+
* worktree DIRECTORY name, so this is the branch-name analogue used to anchor a
|
|
53
|
+
* residual signal back to the owning focus.
|
|
54
|
+
*/
|
|
55
|
+
export declare function extractFocusKeyFromBranch(branchName: string): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Parse `git worktree list --porcelain` to build a map of
|
|
58
|
+
* worktree path -> branch name for all registered worktrees.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseWorktreeList(repoPath: string): Map<string, string>;
|
|
61
|
+
/**
|
|
62
|
+
* What crash recovery must not remove: the shared migration branch population
|
|
63
|
+
* (every focus with a branch and a status other than complete or cancelled,
|
|
64
|
+
* armed or not), plus every focus this host holds a pending completion merge
|
|
65
|
+
* for (RecoveryDeps.listPendingCompletionFocusIds) -- its completed work still
|
|
66
|
+
* has to reach integration from that worktree.
|
|
67
|
+
*/
|
|
68
|
+
export interface LiveFocusPopulation {
|
|
69
|
+
/** 8-char focus-id prefixes whose worktrees are persistent. */
|
|
70
|
+
focusIdPrefixes: Set<string>;
|
|
71
|
+
/** Branch names live focuses name: never pruned, never removed as a merged orphan. */
|
|
72
|
+
branches: Set<string>;
|
|
73
|
+
/** The live focuses themselves, with the status that makes each live -- what the keep log names. */
|
|
74
|
+
liveFocuses: LiveFocusBranch[];
|
|
75
|
+
/**
|
|
76
|
+
* False when the live focus read failed (or the config names no product).
|
|
77
|
+
* Recovery then removes NOTHING a focus could own: a merged branch can be
|
|
78
|
+
* recreated by nobody once it is gone, and keeping one an extra restart costs
|
|
79
|
+
* a directory.
|
|
80
|
+
*/
|
|
81
|
+
known: boolean;
|
|
82
|
+
}
|
|
83
|
+
/** Read the population recovery preserves. Never throws: a failed read is `known: false`. */
|
|
84
|
+
export declare function readLiveFocusPopulation(config: DaemonConfig, deps: LiveBranchPreservationDeps): Promise<LiveFocusPopulation>;
|
|
85
|
+
/**
|
|
86
|
+
* Why the population keeps a branch (or the worktree carrying `idPrefix`), or
|
|
87
|
+
* null when it does not. A LIVE focus is named with the status that makes it
|
|
88
|
+
* live, so a log reader sees the rule -- not complete or cancelled, armed or
|
|
89
|
+
* not -- rather than having to infer it; a pending completion merge is a
|
|
90
|
+
* different reason and says so.
|
|
91
|
+
*/
|
|
92
|
+
export declare function keepReason(population: LiveFocusPopulation, idPrefix: string | null, branchName: string): string | null;
|
|
93
|
+
/**
|
|
94
|
+
* Whether the live population keeps a REGISTERED worktree: its directory
|
|
95
|
+
* carries a live (or pending-completion) focus's id prefix, or its branch is
|
|
96
|
+
* one a live focus names -- merged or not, since its focus can still commit and
|
|
97
|
+
* the allocator requires the branch in every held set. When the population
|
|
98
|
+
* could not be read every worktree is kept: whether it is live is unknown, and
|
|
99
|
+
* it is not removed on a guess.
|
|
100
|
+
*/
|
|
101
|
+
export declare function populationKeepsWorktree(population: LiveFocusPopulation, dirName: string, worktreePath: string, branchName: string): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Prune stale agent branches that have no worktree, no unmerged commits, and
|
|
104
|
+
* that NO LIVE FOCUS NAMES.
|
|
105
|
+
*
|
|
106
|
+
* A merged branch is not a dead one: a finished focus that is still active
|
|
107
|
+
* (awaiting QA, its arm cleared at run end) has a branch fully contained in
|
|
108
|
+
* integration, and the migration allocator still requires it in every held
|
|
109
|
+
* set. So the live population (`LiveFocusPopulation`, the same rule the
|
|
110
|
+
* allocator reads) is consulted before anything is deleted, and an unknown
|
|
111
|
+
* population prunes nothing.
|
|
112
|
+
*
|
|
113
|
+
* Same housekeeping policy as the orphaned-worktree path: a branch with
|
|
114
|
+
* unmerged commits is PRESERVED and LOGGED (the commits are recoverable from
|
|
115
|
+
* the ref), never escalated. A merged branch with no worktree is safe to delete.
|
|
116
|
+
* No path here files a needs_operator escalation -- branch-only orphans are
|
|
117
|
+
* reality-side housekeeping the daemon owns.
|
|
118
|
+
*/
|
|
119
|
+
export declare function pruneStaleAgentBranches(config: DaemonConfig, livePopulation: LiveFocusPopulation): {
|
|
120
|
+
pruned: string[];
|
|
121
|
+
preserved: string[];
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=live-branch-preservation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-branch-preservation.d.ts","sourceRoot":"","sources":["../../src/focus/live-branch-preservation.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAKpF,2EAA2E;AAC3E,MAAM,WAAW,0BAA0B;IACzC;;;;;;;OAOG;IACH,qBAAqB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACzE;;;;;OAKG;IACH,6BAA6B,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAChE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG3E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBvE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,sFAAsF;IACtF,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,oGAAoG;IACpG,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B;;;;;OAKG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,6FAA6F;AAC7F,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuBlI;AAcD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtH;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAWT;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,cAAc,EAAE,mBAAmB,GAClC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAyD3C"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/focus/crash-recovery.test.ts,
|
|
3
|
+
// packages/daemon/src/integration/finished-merged-active-focus-restart-regression.test.ts
|
|
4
|
+
// PINNED-BY-END
|
|
5
|
+
import { runGitSync } from '../git/types.js';
|
|
6
|
+
import { branchHasUnmergedCommits } from '../worktree/safety.js';
|
|
7
|
+
import { createLogger } from '../log/daemon-log.js';
|
|
8
|
+
const log = createLogger({ module: 'crash-recovery' });
|
|
9
|
+
/**
|
|
10
|
+
* Extract the focus ID prefix (last 8 hex chars) from a worktree directory name.
|
|
11
|
+
* Focus worktree directories follow: agent-{role}-{name}-{8-char-id}
|
|
12
|
+
*/
|
|
13
|
+
export function extractFocusIdPrefix(dirName) {
|
|
14
|
+
const match = dirName.match(/-([0-9a-f]{8})$/);
|
|
15
|
+
return match ? match[1] : null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extract the 8-char focus-key suffix from an agent BRANCH name.
|
|
19
|
+
* Branch format: agent/<role>/<slug>-<8hexfocuskey>. The final path segment
|
|
20
|
+
* carries the same -<8hex> suffix that extractFocusIdPrefix parses off the
|
|
21
|
+
* worktree DIRECTORY name, so this is the branch-name analogue used to anchor a
|
|
22
|
+
* residual signal back to the owning focus.
|
|
23
|
+
*/
|
|
24
|
+
export function extractFocusKeyFromBranch(branchName) {
|
|
25
|
+
const lastSegment = branchName.split('/').pop() ?? branchName;
|
|
26
|
+
return extractFocusIdPrefix(lastSegment);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse `git worktree list --porcelain` to build a map of
|
|
30
|
+
* worktree path -> branch name for all registered worktrees.
|
|
31
|
+
*/
|
|
32
|
+
export function parseWorktreeList(repoPath) {
|
|
33
|
+
const result = runGitSync(['worktree', 'list', '--porcelain'], repoPath);
|
|
34
|
+
const map = new Map();
|
|
35
|
+
if (!result.success)
|
|
36
|
+
return map;
|
|
37
|
+
let currentPath = null;
|
|
38
|
+
for (const line of result.output.split('\n')) {
|
|
39
|
+
if (line.startsWith('worktree ')) {
|
|
40
|
+
currentPath = line.slice('worktree '.length);
|
|
41
|
+
}
|
|
42
|
+
else if (line.startsWith('branch refs/heads/') && currentPath) {
|
|
43
|
+
map.set(currentPath, line.slice('branch refs/heads/'.length));
|
|
44
|
+
currentPath = null;
|
|
45
|
+
}
|
|
46
|
+
else if (line === '') {
|
|
47
|
+
currentPath = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return map;
|
|
51
|
+
}
|
|
52
|
+
/** Read the population recovery preserves. Never throws: a failed read is `known: false`. */
|
|
53
|
+
export async function readLiveFocusPopulation(config, deps) {
|
|
54
|
+
const population = { focusIdPrefixes: new Set(), branches: new Set(), liveFocuses: [], known: false };
|
|
55
|
+
if (config.productId) {
|
|
56
|
+
try {
|
|
57
|
+
for (const live of await deps.listLiveFocusBranches(config.productId)) {
|
|
58
|
+
population.focusIdPrefixes.add(live.focusId.slice(0, 8));
|
|
59
|
+
population.branches.add(live.branchName);
|
|
60
|
+
population.liveFocuses.push(live);
|
|
61
|
+
}
|
|
62
|
+
population.known = true;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
log.warn(`[crash-recovery] Failed to read the live focus branches: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
66
|
+
`No focus worktree or agent branch will be removed this pass.`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
log.warn('[crash-recovery] No product in config: the live focus branches cannot be read, so nothing a focus owns is removed.');
|
|
71
|
+
}
|
|
72
|
+
for (const focusId of deps.listPendingCompletionFocusIds(config.productId)) {
|
|
73
|
+
population.focusIdPrefixes.add(focusId.slice(0, 8));
|
|
74
|
+
}
|
|
75
|
+
return population;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* List all local branches matching the agent/* pattern.
|
|
79
|
+
*/
|
|
80
|
+
function listAgentBranches(repoPath) {
|
|
81
|
+
const result = runGitSync(['branch', '--list', 'agent/*'], repoPath);
|
|
82
|
+
if (!result.success)
|
|
83
|
+
return [];
|
|
84
|
+
return result.output
|
|
85
|
+
.split('\n')
|
|
86
|
+
.map((line) => line.replace(/^[*+]?\s+/, '').trim())
|
|
87
|
+
.filter(Boolean);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Why the population keeps a branch (or the worktree carrying `idPrefix`), or
|
|
91
|
+
* null when it does not. A LIVE focus is named with the status that makes it
|
|
92
|
+
* live, so a log reader sees the rule -- not complete or cancelled, armed or
|
|
93
|
+
* not -- rather than having to infer it; a pending completion merge is a
|
|
94
|
+
* different reason and says so.
|
|
95
|
+
*/
|
|
96
|
+
export function keepReason(population, idPrefix, branchName) {
|
|
97
|
+
const live = population.liveFocuses.find((f) => f.branchName === branchName || (idPrefix !== null && f.focusId.startsWith(idPrefix)));
|
|
98
|
+
if (live) {
|
|
99
|
+
return `focus ${live.focusId} is live (status '${live.status}', not complete or cancelled), so its branch ` +
|
|
100
|
+
'is kept merged or not -- the migration allocator requires it in every held set';
|
|
101
|
+
}
|
|
102
|
+
if (idPrefix !== null && population.focusIdPrefixes.has(idPrefix)) {
|
|
103
|
+
return `focus-key ${idPrefix} has a pending completion merge on this host`;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Whether the live population keeps a REGISTERED worktree: its directory
|
|
109
|
+
* carries a live (or pending-completion) focus's id prefix, or its branch is
|
|
110
|
+
* one a live focus names -- merged or not, since its focus can still commit and
|
|
111
|
+
* the allocator requires the branch in every held set. When the population
|
|
112
|
+
* could not be read every worktree is kept: whether it is live is unknown, and
|
|
113
|
+
* it is not removed on a guess.
|
|
114
|
+
*/
|
|
115
|
+
export function populationKeepsWorktree(population, dirName, worktreePath, branchName) {
|
|
116
|
+
const reason = keepReason(population, extractFocusIdPrefix(dirName), branchName);
|
|
117
|
+
if (reason) {
|
|
118
|
+
log.info(`[crash-recovery] Keeping worktree and branch: ${reason}: ${worktreePath} [${branchName}]`);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
if (!population.known) {
|
|
122
|
+
log.warn(`[crash-recovery] Keeping worktree (live focus branches unknown this pass): ${worktreePath} [${branchName}]`);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Prune stale agent branches that have no worktree, no unmerged commits, and
|
|
129
|
+
* that NO LIVE FOCUS NAMES.
|
|
130
|
+
*
|
|
131
|
+
* A merged branch is not a dead one: a finished focus that is still active
|
|
132
|
+
* (awaiting QA, its arm cleared at run end) has a branch fully contained in
|
|
133
|
+
* integration, and the migration allocator still requires it in every held
|
|
134
|
+
* set. So the live population (`LiveFocusPopulation`, the same rule the
|
|
135
|
+
* allocator reads) is consulted before anything is deleted, and an unknown
|
|
136
|
+
* population prunes nothing.
|
|
137
|
+
*
|
|
138
|
+
* Same housekeeping policy as the orphaned-worktree path: a branch with
|
|
139
|
+
* unmerged commits is PRESERVED and LOGGED (the commits are recoverable from
|
|
140
|
+
* the ref), never escalated. A merged branch with no worktree is safe to delete.
|
|
141
|
+
* No path here files a needs_operator escalation -- branch-only orphans are
|
|
142
|
+
* reality-side housekeeping the daemon owns.
|
|
143
|
+
*/
|
|
144
|
+
export function pruneStaleAgentBranches(config, livePopulation) {
|
|
145
|
+
const { repoPath, integrationBranch } = config;
|
|
146
|
+
const branches = listAgentBranches(repoPath);
|
|
147
|
+
const pruned = [];
|
|
148
|
+
const preserved = [];
|
|
149
|
+
if (branches.length === 0) {
|
|
150
|
+
log.info('No stale agent branches found');
|
|
151
|
+
return { pruned, preserved };
|
|
152
|
+
}
|
|
153
|
+
if (!livePopulation.known) {
|
|
154
|
+
log.warn(`[crash-recovery] Branch pruning skipped: the live focus branches are unknown this pass (${branches.length} agent branch(es) kept)`);
|
|
155
|
+
return { pruned, preserved };
|
|
156
|
+
}
|
|
157
|
+
// Get set of branches that have active worktrees
|
|
158
|
+
const worktreeMap = parseWorktreeList(repoPath);
|
|
159
|
+
const worktreeBranches = new Set(worktreeMap.values());
|
|
160
|
+
for (const branch of branches) {
|
|
161
|
+
// Skip branches with active worktrees
|
|
162
|
+
if (worktreeBranches.has(branch))
|
|
163
|
+
continue;
|
|
164
|
+
// A branch a live focus names is never pruned, merged or not; nor is the
|
|
165
|
+
// branch of a pending completion merge.
|
|
166
|
+
const focusKey = extractFocusKeyFromBranch(branch);
|
|
167
|
+
const keep = keepReason(livePopulation, focusKey, branch);
|
|
168
|
+
if (keep) {
|
|
169
|
+
log.info(`[crash-recovery] Keeping branch: ${keep}: ${branch}`);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// Check for unmerged commits
|
|
173
|
+
if (branchHasUnmergedCommits(branch, integrationBranch, repoPath)) {
|
|
174
|
+
log.info(`[crash-recovery] Housekeeping: preserving stale branch with unmerged commits: ${branch}` +
|
|
175
|
+
(focusKey ? ` (focus-key ${focusKey})` : ''));
|
|
176
|
+
preserved.push(branch);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
// Safe to delete
|
|
180
|
+
const deleteResult = runGitSync(['branch', '-D', branch], repoPath);
|
|
181
|
+
if (deleteResult.success) {
|
|
182
|
+
log.info(`Pruned stale branch: ${branch}`);
|
|
183
|
+
pruned.push(branch);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
log.warn(`Failed to prune branch ${branch}: ${deleteResult.error}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
log.info(`[crash-recovery] Branch pruning: ${pruned.length} pruned, ${preserved.length} preserved with unmerged work`);
|
|
190
|
+
return { pruned, preserved };
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=live-branch-preservation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-branch-preservation.js","sourceRoot":"","sources":["../../src/focus/live-branch-preservation.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,8 @@ export interface MigrationClaimPassResult {
|
|
|
30
30
|
skippedUnchanged: number;
|
|
31
31
|
/** Focuses whose branch could not be read: nothing was applied for them. */
|
|
32
32
|
unreadable: number;
|
|
33
|
+
/** Focuses whose unclaimed-file record or clear write failed: retried next tick. */
|
|
34
|
+
recordFailed: number;
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Run the confirm / release / unclaimed-file passes for one product.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-claim-pass.d.ts","sourceRoot":"","sources":["../../src/focus/migration-claim-pass.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migration-claim-pass.d.ts","sourceRoot":"","sources":["../../src/focus/migration-claim-pass.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAMrF,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EAEzB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAIlF,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9D,UAAU,EAAE,OAAO,uBAAuB,CAAC;IAC3C,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,eAAe,EAAE,OAAO,yBAAyB,CAAC;IAClD,cAAc,EAAE,OAAO,wBAAwB,CAAC;IAChD,uEAAuE;IACvE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,wBAAwB,CAAC;IAC3E,sEAAsE;IACtE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC7D,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAWD,sFAAsF;AACtF,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,6DAA6D;AAC7D,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAC;CACtB;AA+MD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,wBAAwB,CAAC,CAsCnC"}
|