@telora/daemon 0.24.25 → 0.24.26
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/audit/audit-prompt.d.ts.map +1 -1
- package/dist/audit/audit-prompt.js +15 -0
- package/dist/audit/audit-prompt.js.map +1 -1
- package/dist/completion/completion-event/event.d.ts +4 -3
- package/dist/completion/completion-event/event.d.ts.map +1 -1
- package/dist/completion/completion-event/event.js.map +1 -1
- package/dist/completion/review-cycle-budget/review-cycle-cap.d.ts +19 -11
- package/dist/completion/review-cycle-budget/review-cycle-cap.d.ts.map +1 -1
- package/dist/completion/review-cycle-budget/review-cycle-cap.js +36 -36
- package/dist/completion/review-cycle-budget/review-cycle-cap.js.map +1 -1
- package/dist/completion/review-cycle-budget/review-loop-detection.d.ts +101 -0
- package/dist/completion/review-cycle-budget/review-loop-detection.d.ts.map +1 -0
- package/dist/completion/review-cycle-budget/review-loop-detection.js +105 -0
- package/dist/completion/review-cycle-budget/review-loop-detection.js.map +1 -0
- package/dist/completion/review-cycle-budget/spent-budget-release.d.ts +70 -0
- package/dist/completion/review-cycle-budget/spent-budget-release.d.ts.map +1 -0
- package/dist/completion/review-cycle-budget/spent-budget-release.js +98 -0
- package/dist/completion/review-cycle-budget/spent-budget-release.js.map +1 -0
- package/dist/completion/review-exit/review-defect-detector.d.ts +71 -49
- package/dist/completion/review-exit/review-defect-detector.d.ts.map +1 -1
- package/dist/completion/review-exit/review-defect-detector.js +75 -69
- package/dist/completion/review-exit/review-defect-detector.js.map +1 -1
- package/dist/completion/review-exit/review-exit-attribution.d.ts +1 -1
- package/dist/completion/review-exit/review-exit-attribution.js +1 -1
- package/dist/completion/review-exit/review-exit-deps.d.ts +5 -2
- package/dist/completion/review-exit/review-exit-deps.d.ts.map +1 -1
- package/dist/completion/review-exit/review-exit-deps.js +1 -1
- package/dist/completion/review-exit/review-exit-evidence.d.ts +10 -1
- package/dist/completion/review-exit/review-exit-evidence.d.ts.map +1 -1
- package/dist/completion/review-exit/review-exit-evidence.js +17 -14
- package/dist/completion/review-exit/review-exit-evidence.js.map +1 -1
- package/dist/completion/review-exit/review-exit-foreign-findings.d.ts +1 -1
- package/dist/completion/review-exit/review-exit-foreign-findings.d.ts.map +1 -1
- package/dist/completion/review-exit/review-exit-phase.d.ts.map +1 -1
- package/dist/completion/review-exit/review-exit-phase.js +12 -8
- package/dist/completion/review-exit/review-exit-phase.js.map +1 -1
- package/dist/completion/state-cascade/review-next-step.d.ts +12 -3
- package/dist/completion/state-cascade/review-next-step.d.ts.map +1 -1
- package/dist/completion/state-cascade/review-next-step.js +10 -1
- package/dist/completion/state-cascade/review-next-step.js.map +1 -1
- package/dist/completion/state-cascade/standing-approval-convergence.d.ts +1 -1
- package/dist/completion/state-cascade/standing-approval-convergence.d.ts.map +1 -1
- package/dist/completion/state-cascade/standing-approval-convergence.js +10 -4
- package/dist/completion/state-cascade/standing-approval-convergence.js.map +1 -1
- package/dist/completion/state-cascade/state-cascade.d.ts +3 -0
- package/dist/completion/state-cascade/state-cascade.d.ts.map +1 -1
- package/dist/completion/state-cascade/state-cascade.js +16 -1
- package/dist/completion/state-cascade/state-cascade.js.map +1 -1
- package/dist/completion/team-exit/status-advance-phase.d.ts +1 -1
- package/dist/completion/team-exit/status-advance-phase.d.ts.map +1 -1
- package/dist/completion/team-exit/status-advance-phase.js +6 -4
- package/dist/completion/team-exit/status-advance-phase.js.map +1 -1
- package/dist/completion/team-outcome/apply-turn.d.ts.map +1 -1
- package/dist/completion/team-outcome/apply-turn.js +9 -4
- package/dist/completion/team-outcome/apply-turn.js.map +1 -1
- package/dist/completion/team-outcome/decide-turn-entry-rows.d.ts.map +1 -1
- package/dist/completion/team-outcome/decide-turn-entry-rows.js +28 -3
- package/dist/completion/team-outcome/decide-turn-entry-rows.js.map +1 -1
- package/dist/completion/team-outcome/decide.d.ts.map +1 -1
- package/dist/completion/team-outcome/decide.js +1 -0
- package/dist/completion/team-outcome/decide.js.map +1 -1
- package/dist/completion/team-outcome/exit-limits.d.ts +6 -0
- package/dist/completion/team-outcome/exit-limits.d.ts.map +1 -1
- package/dist/completion/team-outcome/exit-limits.js +6 -0
- package/dist/completion/team-outcome/exit-limits.js.map +1 -1
- package/dist/completion/team-outcome/exit-pipeline-state.d.ts +5 -0
- package/dist/completion/team-outcome/exit-pipeline-state.d.ts.map +1 -1
- package/dist/completion/team-outcome/exit-pipeline-state.js.map +1 -1
- package/dist/completion/team-teardown/session-hold-bounds.d.ts +10 -1
- package/dist/completion/team-teardown/session-hold-bounds.d.ts.map +1 -1
- package/dist/completion/team-teardown/session-hold-bounds.js +11 -0
- package/dist/completion/team-teardown/session-hold-bounds.js.map +1 -1
- package/dist/completion/team-teardown/session-hold.d.ts.map +1 -1
- package/dist/completion/team-teardown/session-hold.js +2 -0
- package/dist/completion/team-teardown/session-hold.js.map +1 -1
- package/dist/composition/engine-start-context.d.ts.map +1 -1
- package/dist/composition/engine-start-context.js +9 -1
- package/dist/composition/engine-start-context.js.map +1 -1
- package/dist/composition/execution-spawn-context.d.ts.map +1 -1
- package/dist/composition/execution-spawn-context.js +2 -0
- package/dist/composition/execution-spawn-context.js.map +1 -1
- package/dist/composition/judgement-contexts.d.ts.map +1 -1
- package/dist/composition/judgement-contexts.js +8 -2
- package/dist/composition/judgement-contexts.js.map +1 -1
- package/dist/composition/review-exit-context.d.ts.map +1 -1
- package/dist/composition/review-exit-context.js +2 -0
- package/dist/composition/review-exit-context.js.map +1 -1
- package/dist/composition/review-loop-context.d.ts +28 -0
- package/dist/composition/review-loop-context.d.ts.map +1 -0
- package/dist/composition/review-loop-context.js +147 -0
- package/dist/composition/review-loop-context.js.map +1 -0
- package/dist/composition/runtime-heartbeat-context.d.ts.map +1 -1
- package/dist/composition/runtime-heartbeat-context.js +8 -2
- package/dist/composition/runtime-heartbeat-context.js.map +1 -1
- package/dist/composition/spawn-pass-deps.d.ts.map +1 -1
- package/dist/composition/spawn-pass-deps.js +3 -0
- package/dist/composition/spawn-pass-deps.js.map +1 -1
- package/dist/composition/state-cascade-context.d.ts.map +1 -1
- package/dist/composition/state-cascade-context.js +3 -1
- package/dist/composition/state-cascade-context.js.map +1 -1
- package/dist/composition/tower-escalation-context.d.ts +12 -0
- package/dist/composition/tower-escalation-context.d.ts.map +1 -0
- package/dist/composition/tower-escalation-context.js +109 -0
- package/dist/composition/tower-escalation-context.js.map +1 -0
- package/dist/composition/workstation-intervals-context.d.ts +3 -0
- package/dist/composition/workstation-intervals-context.d.ts.map +1 -0
- package/dist/composition/workstation-intervals-context.js +33 -0
- package/dist/composition/workstation-intervals-context.js.map +1 -0
- package/dist/daemon-state/awaiting-slot.d.ts +18 -1
- package/dist/daemon-state/awaiting-slot.d.ts.map +1 -1
- package/dist/daemon-state/awaiting-slot.js +7 -0
- package/dist/daemon-state/awaiting-slot.js.map +1 -1
- package/dist/delivery/delivery-reconciler.d.ts +7 -7
- package/dist/delivery/recorded-concerns.d.ts +63 -28
- package/dist/delivery/recorded-concerns.d.ts.map +1 -1
- package/dist/delivery/recorded-concerns.js +72 -28
- package/dist/delivery/recorded-concerns.js.map +1 -1
- package/dist/directive/directive-queue.d.ts +8 -0
- package/dist/directive/directive-queue.d.ts.map +1 -1
- package/dist/directive/directive-queue.js +1 -1
- package/dist/directive/directive-queue.js.map +1 -1
- package/dist/focus/control-state.d.ts +6 -4
- package/dist/focus/control-state.d.ts.map +1 -1
- package/dist/focus/control-state.js +6 -4
- package/dist/focus/control-state.js.map +1 -1
- package/dist/focus/daemon-contexts-judgement.d.ts +6 -0
- package/dist/focus/daemon-contexts-judgement.d.ts.map +1 -1
- package/dist/focus/daemon-contexts.d.ts +6 -0
- package/dist/focus/daemon-contexts.d.ts.map +1 -1
- package/dist/focus/daemon-contexts.js.map +1 -1
- package/dist/focus/focus-engine.d.ts.map +1 -1
- package/dist/focus/focus-engine.js +3 -1
- package/dist/focus/focus-engine.js.map +1 -1
- package/dist/focus/focus-executor.d.ts.map +1 -1
- package/dist/focus/focus-executor.js +3 -2
- package/dist/focus/focus-executor.js.map +1 -1
- package/dist/focus/focus-loop-registry.d.ts.map +1 -1
- package/dist/focus/focus-loop-registry.js +42 -0
- package/dist/focus/focus-loop-registry.js.map +1 -1
- package/dist/focus/focus-poller-auto-advance.d.ts +4 -2
- package/dist/focus/focus-poller-auto-advance.d.ts.map +1 -1
- package/dist/focus/focus-poller-auto-advance.js +24 -18
- package/dist/focus/focus-poller-auto-advance.js.map +1 -1
- package/dist/focus/focus-poller-spawn.d.ts.map +1 -1
- package/dist/focus/focus-poller-spawn.js +8 -6
- package/dist/focus/focus-poller-spawn.js.map +1 -1
- package/dist/focus/heartbeat.d.ts +9 -2
- package/dist/focus/heartbeat.d.ts.map +1 -1
- package/dist/focus/heartbeat.js +9 -1
- package/dist/focus/heartbeat.js.map +1 -1
- package/dist/focus/pending-directive-gates.d.ts +14 -0
- package/dist/focus/pending-directive-gates.d.ts.map +1 -1
- package/dist/focus/pending-directive-gates.js +25 -1
- package/dist/focus/pending-directive-gates.js.map +1 -1
- package/dist/focus/pending-spawn-pass-deps.d.ts +7 -0
- package/dist/focus/pending-spawn-pass-deps.d.ts.map +1 -1
- package/dist/focus/pending-spawn-review-next-step.d.ts +1 -1
- package/dist/focus/pending-spawn-review-next-step.d.ts.map +1 -1
- package/dist/focus/pending-spawn-review-next-step.js +2 -0
- package/dist/focus/pending-spawn-review-next-step.js.map +1 -1
- package/dist/focus/ready-focus-team-work.d.ts +9 -4
- package/dist/focus/ready-focus-team-work.d.ts.map +1 -1
- package/dist/focus/ready-focus-team-work.js +14 -3
- package/dist/focus/ready-focus-team-work.js.map +1 -1
- package/dist/focus/verify-open-issues.d.ts +3 -2
- package/dist/focus/verify-open-issues.d.ts.map +1 -1
- package/dist/focus/verify-open-issues.js +6 -4
- package/dist/focus/verify-open-issues.js.map +1 -1
- package/dist/focus/workstation-intervals.d.ts +83 -0
- package/dist/focus/workstation-intervals.d.ts.map +1 -0
- package/dist/focus/workstation-intervals.js +81 -0
- package/dist/focus/workstation-intervals.js.map +1 -0
- package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts +5 -2
- package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts.map +1 -1
- package/dist/focus-stage-lifecycle/wedge-watchdog.js +2 -2
- package/dist/focus-stage-lifecycle/wedge-watchdog.js.map +1 -1
- package/dist/prompt-sections/persona-sections.d.ts.map +1 -1
- package/dist/prompt-sections/persona-sections.js +4 -1
- package/dist/prompt-sections/persona-sections.js.map +1 -1
- package/dist/prompt-sections/qa-author-section.d.ts.map +1 -1
- package/dist/prompt-sections/qa-author-section.js +18 -1
- package/dist/prompt-sections/qa-author-section.js.map +1 -1
- package/dist/prompt-sections/scoping-sections.d.ts +0 -12
- package/dist/prompt-sections/scoping-sections.d.ts.map +1 -1
- package/dist/prompt-sections/scoping-sections.js +16 -2
- package/dist/prompt-sections/scoping-sections.js.map +1 -1
- package/dist/prompts/bounded-universals.d.ts +13 -0
- package/dist/prompts/bounded-universals.d.ts.map +1 -0
- package/dist/prompts/bounded-universals.js +32 -0
- package/dist/prompts/bounded-universals.js.map +1 -0
- package/dist/queries/api-client/shared.d.ts +2 -1
- package/dist/queries/api-client/shared.d.ts.map +1 -1
- package/dist/queries/api-client/shared.js +31 -1
- package/dist/queries/api-client/shared.js.map +1 -1
- package/dist/queries/deliveries/issues.d.ts.map +1 -1
- package/dist/queries/deliveries/issues.js +1 -0
- package/dist/queries/deliveries/issues.js.map +1 -1
- package/dist/queries/escalations/escalation-consumption.d.ts +13 -0
- package/dist/queries/escalations/escalation-consumption.d.ts.map +1 -1
- package/dist/queries/escalations/escalation-consumption.js +12 -2
- package/dist/queries/escalations/escalation-consumption.js.map +1 -1
- package/dist/queries/escalations/tower-escalations.d.ts +82 -0
- package/dist/queries/escalations/tower-escalations.d.ts.map +1 -0
- package/dist/queries/escalations/tower-escalations.js +97 -0
- package/dist/queries/escalations/tower-escalations.js.map +1 -0
- package/dist/queries/focus-review/recorded-concern-ids.d.ts +48 -11
- package/dist/queries/focus-review/recorded-concern-ids.d.ts.map +1 -1
- package/dist/queries/focus-review/recorded-concern-ids.js +42 -12
- package/dist/queries/focus-review/recorded-concern-ids.js.map +1 -1
- package/dist/queries/focus-review/review-criterion-verdicts.d.ts +37 -0
- package/dist/queries/focus-review/review-criterion-verdicts.d.ts.map +1 -0
- package/dist/queries/focus-review/review-criterion-verdicts.js +64 -0
- package/dist/queries/focus-review/review-criterion-verdicts.js.map +1 -0
- package/dist/queries/focus-review/review-finding-facts.d.ts +18 -6
- package/dist/queries/focus-review/review-finding-facts.d.ts.map +1 -1
- package/dist/queries/focus-review/review-finding-facts.js +21 -8
- package/dist/queries/focus-review/review-finding-facts.js.map +1 -1
- package/dist/queries/focuses/ended-arm.d.ts +56 -13
- package/dist/queries/focuses/ended-arm.d.ts.map +1 -1
- package/dist/queries/focuses/ended-arm.js +40 -14
- package/dist/queries/focuses/ended-arm.js.map +1 -1
- package/dist/queries/focuses/focus-criteria-standing.d.ts +12 -0
- package/dist/queries/focuses/focus-criteria-standing.d.ts.map +1 -1
- package/dist/queries/focuses/focus-criteria-standing.js +13 -0
- package/dist/queries/focuses/focus-criteria-standing.js.map +1 -1
- package/dist/queries/focuses/focus-discovery.d.ts +14 -3
- package/dist/queries/focuses/focus-discovery.d.ts.map +1 -1
- package/dist/queries/focuses/focus-discovery.js +2 -19
- package/dist/queries/focuses/focus-discovery.js.map +1 -1
- package/dist/queries/focuses/focuses.d.ts +15 -12
- package/dist/queries/focuses/focuses.d.ts.map +1 -1
- package/dist/queries/focuses/focuses.js +15 -13
- package/dist/queries/focuses/focuses.js.map +1 -1
- package/dist/queries/sessions/sessions.d.ts.map +1 -1
- package/dist/queries/sessions/sessions.js +2 -1
- package/dist/queries/sessions/sessions.js.map +1 -1
- package/dist/queries/tower-decisions/tower-decisions.d.ts +103 -0
- package/dist/queries/tower-decisions/tower-decisions.d.ts.map +1 -0
- package/dist/queries/tower-decisions/tower-decisions.js +138 -0
- package/dist/queries/tower-decisions/tower-decisions.js.map +1 -0
- package/dist/queries/wire-schemas/schemas.d.ts +2 -0
- package/dist/queries/wire-schemas/schemas.d.ts.map +1 -1
- package/dist/queries/wire-schemas/schemas.js +8 -2
- package/dist/queries/wire-schemas/schemas.js.map +1 -1
- package/dist/queries/workstation-intervals/workstation-intervals.d.ts +52 -0
- package/dist/queries/workstation-intervals/workstation-intervals.d.ts.map +1 -0
- package/dist/queries/workstation-intervals/workstation-intervals.js +49 -0
- package/dist/queries/workstation-intervals/workstation-intervals.js.map +1 -0
- package/dist/resolvers/escalation-answers.d.ts +31 -0
- package/dist/resolvers/escalation-answers.d.ts.map +1 -1
- package/dist/resolvers/escalation-answers.js +31 -17
- package/dist/resolvers/escalation-answers.js.map +1 -1
- package/dist/resolvers/focus-criteria-standing.d.ts.map +1 -1
- package/dist/resolvers/focus-criteria-standing.js +20 -0
- package/dist/resolvers/focus-criteria-standing.js.map +1 -1
- package/dist/shell/unified-engine-lifecycle.d.ts +11 -1
- package/dist/shell/unified-engine-lifecycle.d.ts.map +1 -1
- package/dist/shell/unified-engine-lifecycle.js +10 -1
- package/dist/shell/unified-engine-lifecycle.js.map +1 -1
- package/dist/spawn/directive-dispatch.d.ts.map +1 -1
- package/dist/spawn/directive-dispatch.js +1 -0
- package/dist/spawn/directive-dispatch.js.map +1 -1
- package/dist/spawn/lead-continuation.d.ts +4 -3
- package/dist/spawn/lead-continuation.d.ts.map +1 -1
- package/dist/spawn/lead-continuation.js.map +1 -1
- package/dist/spawn/live-answer-delivery.d.ts +53 -0
- package/dist/spawn/live-answer-delivery.d.ts.map +1 -0
- package/dist/spawn/live-answer-delivery.js +26 -0
- package/dist/spawn/live-answer-delivery.js.map +1 -0
- package/dist/spawn/routing-decider-spawn.d.ts +64 -2
- package/dist/spawn/routing-decider-spawn.d.ts.map +1 -1
- package/dist/spawn/routing-decider-spawn.js +65 -20
- package/dist/spawn/routing-decider-spawn.js.map +1 -1
- package/dist/spawn/worktree-session.d.ts +7 -5
- package/dist/spawn/worktree-session.d.ts.map +1 -1
- package/dist/spawn/worktree-session.js +11 -7
- package/dist/spawn/worktree-session.js.map +1 -1
- package/dist/supervision/review-cycle-cap-hold.d.ts +11 -5
- package/dist/supervision/review-cycle-cap-hold.d.ts.map +1 -1
- package/dist/supervision/review-cycle-cap-hold.js +29 -11
- package/dist/supervision/review-cycle-cap-hold.js.map +1 -1
- package/dist/supervision/review-loop-detector.d.ts +48 -0
- package/dist/supervision/review-loop-detector.d.ts.map +1 -0
- package/dist/supervision/review-loop-detector.js +13 -0
- package/dist/supervision/review-loop-detector.js.map +1 -0
- package/dist/supervision/review-loop-hold.d.ts +29 -0
- package/dist/supervision/review-loop-hold.d.ts.map +1 -0
- package/dist/supervision/review-loop-hold.js +99 -0
- package/dist/supervision/review-loop-hold.js.map +1 -0
- package/dist/supervision/stall-detector-config.d.ts +8 -0
- package/dist/supervision/stall-detector-config.d.ts.map +1 -1
- package/dist/supervision/stall-detector-config.js +14 -3
- package/dist/supervision/stall-detector-config.js.map +1 -1
- package/dist/supervision/stop-registry.d.ts +3 -0
- package/dist/supervision/stop-registry.d.ts.map +1 -1
- package/dist/supervision/stop-registry.js +3 -1
- package/dist/supervision/stop-registry.js.map +1 -1
- package/dist/supervision/stop-rows-review-loop.d.ts +35 -0
- package/dist/supervision/stop-rows-review-loop.d.ts.map +1 -0
- package/dist/supervision/stop-rows-review-loop.js +150 -0
- package/dist/supervision/stop-rows-review-loop.js.map +1 -0
- package/dist/supervision/stop-rows-team-session.d.ts +1 -1
- package/dist/supervision/stop-rows-team-session.d.ts.map +1 -1
- package/dist/supervision/stop-rows-team-session.js.map +1 -1
- package/dist/supervision/unreviewed-settle-detector.d.ts +7 -2
- package/dist/supervision/unreviewed-settle-detector.d.ts.map +1 -1
- package/dist/supervision/unreviewed-settle-detector.js +15 -2
- package/dist/supervision/unreviewed-settle-detector.js.map +1 -1
- package/dist/templates/agents-md.d.ts.map +1 -1
- package/dist/templates/agents-md.js +1 -0
- package/dist/templates/agents-md.js.map +1 -1
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.d.ts.map +1 -1
- package/dist/templates/claude-md.js +12 -0
- package/dist/templates/claude-md.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/pending-spawn-world.d.ts +4 -0
- package/dist/testing/fixtures/pending-spawn-world.d.ts.map +1 -1
- package/dist/testing/fixtures/pending-spawn-world.js +15 -2
- 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/review-exit-deps.d.ts.map +1 -1
- package/dist/testing/fixtures/review-exit-deps.js +3 -1
- package/dist/testing/fixtures/review-exit-deps.js.map +1 -1
- package/dist/testing/fixtures/review-loop.d.ts +19 -0
- package/dist/testing/fixtures/review-loop.d.ts.map +1 -0
- package/dist/testing/fixtures/review-loop.js +30 -0
- package/dist/testing/fixtures/review-loop.js.map +1 -0
- package/dist/testing/fixtures/shortfall-rework-hold-deps.d.ts.map +1 -1
- package/dist/testing/fixtures/shortfall-rework-hold-deps.js +1 -0
- package/dist/testing/fixtures/shortfall-rework-hold-deps.js.map +1 -1
- package/dist/testing/fixtures/tower-loop.d.ts +28 -0
- package/dist/testing/fixtures/tower-loop.d.ts.map +1 -0
- package/dist/testing/fixtures/tower-loop.js +83 -0
- package/dist/testing/fixtures/tower-loop.js.map +1 -0
- package/dist/tower/tower-escalation-gather.d.ts +33 -0
- package/dist/tower/tower-escalation-gather.d.ts.map +1 -0
- package/dist/tower/tower-escalation-gather.js +38 -0
- package/dist/tower/tower-escalation-gather.js.map +1 -0
- package/dist/tower/tower-escalation-prompt.d.ts +62 -0
- package/dist/tower/tower-escalation-prompt.d.ts.map +1 -0
- package/dist/tower/tower-escalation-prompt.js +130 -0
- package/dist/tower/tower-escalation-prompt.js.map +1 -0
- package/dist/tower/tower-escalation-routing.d.ts +49 -0
- package/dist/tower/tower-escalation-routing.d.ts.map +1 -0
- package/dist/tower/tower-escalation-routing.js +53 -0
- package/dist/tower/tower-escalation-routing.js.map +1 -0
- package/dist/tower/tower-escalation-session.d.ts +149 -0
- package/dist/tower/tower-escalation-session.d.ts.map +1 -0
- package/dist/tower/tower-escalation-session.js +238 -0
- package/dist/tower/tower-escalation-session.js.map +1 -0
- package/dist/tower/tower-supervisor-history.d.ts +129 -0
- package/dist/tower/tower-supervisor-history.d.ts.map +1 -0
- package/dist/tower/tower-supervisor-history.js +217 -0
- package/dist/tower/tower-supervisor-history.js.map +1 -0
- package/dist/tower/tower-supervisor-prompt.d.ts +21 -0
- package/dist/tower/tower-supervisor-prompt.d.ts.map +1 -0
- package/dist/tower/tower-supervisor-prompt.js +205 -0
- package/dist/tower/tower-supervisor-prompt.js.map +1 -0
- package/dist/tower/tower-supervisor-session.d.ts +220 -0
- package/dist/tower/tower-supervisor-session.d.ts.map +1 -0
- package/dist/tower/tower-supervisor-session.js +307 -0
- package/dist/tower/tower-supervisor-session.js.map +1 -0
- package/dist/tower/tower-supervisor.d.ts +86 -0
- package/dist/tower/tower-supervisor.d.ts.map +1 -0
- package/dist/tower/tower-supervisor.js +8 -0
- package/dist/tower/tower-supervisor.js.map +1 -0
- package/dist/types/index.js +1 -1
- package/dist/verify/outcome-routing/verification-rework-issue.d.ts +4 -4
- package/dist/verify/outcome-routing/verification-rework-issue.d.ts.map +1 -1
- package/dist/verify/outcome-routing/verification-rework-issue.js +16 -6
- package/dist/verify/outcome-routing/verification-rework-issue.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TOWER SUPERVISOR SESSION: the TowerSupervisor (tower/tower-supervisor.ts)
|
|
3
|
+
* the composition root binds. One held loop -> one one-shot `claude --print`
|
|
4
|
+
* judgement session (the routing decider's process, spawn/routing-decider-spawn.ts
|
|
5
|
+
* spawnOneShotJudgementSession, under the supervisor's identity), started in
|
|
6
|
+
* the background so the review exit never waits on it; the hold covers the wait.
|
|
7
|
+
*
|
|
8
|
+
* BOUNDED.
|
|
9
|
+
* - One session per open loop_detected: an in-flight map keyed by the loop
|
|
10
|
+
* decision; no second session starts while one runs.
|
|
11
|
+
* - A governor slot (engine TOWER_SUPERVISOR_GOVERNOR_ENGINE, bounded by the
|
|
12
|
+
* global session cap). None free, the provider window open, the model
|
|
13
|
+
* unavailable: nothing ran, nothing is counted, the next sweep retries.
|
|
14
|
+
* - A session that RAN and left no terminal decision on the record (crashed,
|
|
15
|
+
* timed out, exited without recording) is an attempt. After
|
|
16
|
+
* TOWER_SUPERVISOR_MAX_ATTEMPTS the daemon stops trying: it files one
|
|
17
|
+
* agent_resolvable observation (the daemon has no human-facing route --
|
|
18
|
+
* supervision/filing-route.ts; a routing decider makes it the operator's)
|
|
19
|
+
* and records `escalated_to_operator` naming it, so the loop never stands
|
|
20
|
+
* held SILENTLY. Attempts are counted in memory: a restart grants at most
|
|
21
|
+
* that many more.
|
|
22
|
+
*
|
|
23
|
+
* ONCE PER CRITERION PER ARM. Before any session starts for an undecided
|
|
24
|
+
* loop, the record is asked whether the loop's criterion was already bounded
|
|
25
|
+
* under the current arm (escalateRepeatReviewLoop -> product-api
|
|
26
|
+
* handlers/tower-repeat-loop-escalation.ts, where the rule lives). A repeat --
|
|
27
|
+
* the supervisor's bound did not hold -- is never handed to a second
|
|
28
|
+
* supervisor: the edge files it to the operator (the one path by which a
|
|
29
|
+
* review loop reaches the operator) and records `escalated_to_operator`, so
|
|
30
|
+
* the loop stays held and every later sweep reads it as awaiting the operator.
|
|
31
|
+
* A failed check starts nothing (the next sweep asks again). A new arm resets
|
|
32
|
+
* the allowance: the rule counts bounds of the current arm only.
|
|
33
|
+
*
|
|
34
|
+
* WHO RELEASES THE HOLD: the daemon, never the session. After a session exits
|
|
35
|
+
* (and on every sweep) the daemon reads the focus record: a `criterion_bounded`
|
|
36
|
+
* decision naming the loop (evidence.loopDecisionId) WHOSE BOUND WAS APPLIED --
|
|
37
|
+
* the edge reports an amendment of the loop's criterion recorded since the
|
|
38
|
+
* loop was detected (appliedBounds; handlers/tower-loop-amendments.ts, which
|
|
39
|
+
* also refuses a loop_resolved without one) -> the daemon records
|
|
40
|
+
* `loop_resolved` naming the loop and drops any review directive queued before
|
|
41
|
+
* the amendment, so the next review is a fresh session on the new wording. A
|
|
42
|
+
* criterion_bounded whose amendment never landed releases nothing: the
|
|
43
|
+
* decision is the session's account, the amendment the act, and a release on
|
|
44
|
+
* the account would resume the team on the unbounded wording. That session is
|
|
45
|
+
* an attempt like one that decided nothing. An
|
|
46
|
+
* `escalated_to_operator` naming it -> the loop STAYS held while the operator
|
|
47
|
+
* answers (the safe reading of "the escalation goes to the human"); a new arm
|
|
48
|
+
* is the operator's release, as it always was. A session cannot hold or
|
|
49
|
+
* release a loop by writing a row (product-api tower_decision_record refuses
|
|
50
|
+
* both kinds).
|
|
51
|
+
*
|
|
52
|
+
* MODEL PIN: 'opus' (TOWER_SUPERVISOR_MODEL), the routing decider's pin and for
|
|
53
|
+
* its reason: bounding a criterion moves the bar a whole armed run is judged
|
|
54
|
+
* against, without a human, so the stronger model is worth its cost, and the
|
|
55
|
+
* volume is one session per held loop. A constant, not an EnginePass: the
|
|
56
|
+
* one-shot is a `claude --print` session (an engine pass would let a per-pass
|
|
57
|
+
* org default name a model this path cannot run), and adding a pass widens
|
|
58
|
+
* every engine-override surface for a session that is not a team pass.
|
|
59
|
+
* Reversible: a 'supervisor' pass can replace the constant later.
|
|
60
|
+
*
|
|
61
|
+
* NO BUDGET LEVER, ENFORCED AT THE TOOL. The session runs its Telora MCP server
|
|
62
|
+
* under the scoped profile TOWER_SUPERVISOR_MCP_PROFILE (`tower_supervisor`,
|
|
63
|
+
* mcp/telora-products src/profile-scope.ts), handed to it as its ONLY MCP config
|
|
64
|
+
* (composition/review-loop-context.ts TOWER_SUPERVISOR_IDENTITY.mcpProfile ->
|
|
65
|
+
* spawn/routing-decider-spawn.ts inline --mcp-config + --strict-mcp-config).
|
|
66
|
+
* Under that profile telora_product_focus offers the reads plus amend_criterion
|
|
67
|
+
* and nothing else -- no update, so no arm or re-arm (a new arm resets
|
|
68
|
+
* review_cycle_count: a fresh budget), no unarm, no review-request clear, no
|
|
69
|
+
* pipelineConfig -- and refuses any other action at dispatch; no other tool it
|
|
70
|
+
* registers can arm, unarm, grant cycles or write review_cycle_count. The
|
|
71
|
+
* allowlist (TOWER_SUPERVISOR_MCP_TOOLS) and the prompt
|
|
72
|
+
* (tower/tower-supervisor-prompt.ts) say the same; neither is the bound. Pinned
|
|
73
|
+
* by tower-supervisor-session.test.ts, the prompt test, routing-decider-spawn
|
|
74
|
+
* .test.ts and mcp/telora-products tower-supervisor-profile.test.ts.
|
|
75
|
+
*
|
|
76
|
+
* @module tower/tower-supervisor-session
|
|
77
|
+
*/
|
|
78
|
+
import type { ResourceGovernor } from '@telora/daemon-core';
|
|
79
|
+
import type { DaemonConfig } from '../types/index.js';
|
|
80
|
+
import type { FocusDecisionRecord, OpenReviewLoop, RepeatReviewLoopAnswer, TowerDecision, TowerDecisionInput } from '../queries/tower-decisions/tower-decisions.js';
|
|
81
|
+
import { type GatherLoopHistoryArgs, type HeldLoop, type LoopHistory } from './tower-supervisor-history.js';
|
|
82
|
+
import { type TowerSupervisor } from './tower-supervisor.js';
|
|
83
|
+
export declare const TOWER_SUPERVISOR_MODEL = "opus";
|
|
84
|
+
/** Kill a supervisor that has not exited within this window (30 minutes: it may run the disputed tests). */
|
|
85
|
+
export declare const TOWER_SUPERVISOR_TIMEOUT_MS: number;
|
|
86
|
+
/** Sessions that ran without deciding, per loop, before the daemon stops trying and files it. */
|
|
87
|
+
export declare const TOWER_SUPERVISOR_MAX_ATTEMPTS = 2;
|
|
88
|
+
/** Governor engine name for supervisor slots (no per-engine limit: bounded by the global session cap). */
|
|
89
|
+
export declare const TOWER_SUPERVISOR_GOVERNOR_ENGINE = "tower-supervisor";
|
|
90
|
+
/**
|
|
91
|
+
* The scoped MCP profile the supervisor's Telora server runs under
|
|
92
|
+
* (mcp/telora-products profile-scope.ts TOWER_SUPERVISOR_PROFILE): the tool-level
|
|
93
|
+
* bound on "it never grants review budget".
|
|
94
|
+
*/
|
|
95
|
+
export declare const TOWER_SUPERVISOR_MCP_PROFILE = "tower_supervisor";
|
|
96
|
+
/** escalation_kind of the observation filed when every attempt ran without deciding. */
|
|
97
|
+
export declare const TOWER_SUPERVISOR_UNDECIDED_KIND = "tower_supervisor_undecided";
|
|
98
|
+
/**
|
|
99
|
+
* The tools a supervisor session is pre-approved for: reading and running the
|
|
100
|
+
* disputed check in the worktree, and the Telora acts it decides through --
|
|
101
|
+
* the amendment (telora_product_focus amend_criterion), the findings and Tasks
|
|
102
|
+
* (telora_product_issue), the decision record (telora_product_tower), the one
|
|
103
|
+
* escalation (telora_agent) -- plus the context it reads. This list only
|
|
104
|
+
* PRE-APPROVES; what the Telora tools can DO is bounded by the scoped MCP
|
|
105
|
+
* profile (TOWER_SUPERVISOR_MCP_PROFILE), under which none can arm, unarm or
|
|
106
|
+
* grant review cycles: the budget is the daemon's.
|
|
107
|
+
*/
|
|
108
|
+
export declare const TOWER_SUPERVISOR_MCP_TOOLS: readonly string[];
|
|
109
|
+
/** What one supervisor process is spawned with. */
|
|
110
|
+
export interface TowerSupervisorSpawnOptions {
|
|
111
|
+
config: DaemonConfig;
|
|
112
|
+
prompt: string;
|
|
113
|
+
cwd: string;
|
|
114
|
+
focusId: string;
|
|
115
|
+
/** The loop being decided (telemetry + worker label). */
|
|
116
|
+
loopDecisionId: string;
|
|
117
|
+
model: string;
|
|
118
|
+
timeoutMs: number;
|
|
119
|
+
allowedTools: readonly string[];
|
|
120
|
+
}
|
|
121
|
+
/** How a supervisor process ended. */
|
|
122
|
+
export interface TowerSupervisorSpawnResult {
|
|
123
|
+
started: boolean;
|
|
124
|
+
exitCode: number | null;
|
|
125
|
+
timedOut: boolean;
|
|
126
|
+
stdout: string;
|
|
127
|
+
errorMessage?: string;
|
|
128
|
+
/** The model never ran (rate limit, auth, the provider window): not an attempt. */
|
|
129
|
+
modelUnavailable?: {
|
|
130
|
+
kind: string;
|
|
131
|
+
resetAtMs: number | null;
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/** The focus a held loop belongs to, as the daemon runs it. */
|
|
135
|
+
export interface SupervisedFocus {
|
|
136
|
+
focusId: string;
|
|
137
|
+
focusName: string;
|
|
138
|
+
focusDescription: string | null;
|
|
139
|
+
productId: string;
|
|
140
|
+
}
|
|
141
|
+
/** The one observation filed when every attempt ran without deciding. */
|
|
142
|
+
export interface UndecidedLoopFiling {
|
|
143
|
+
organizationId: string;
|
|
144
|
+
productId: string;
|
|
145
|
+
focusId: string;
|
|
146
|
+
escalationKind: string;
|
|
147
|
+
description: string;
|
|
148
|
+
whatWasTried: string;
|
|
149
|
+
helpNeeded: string;
|
|
150
|
+
metadata: Record<string, unknown>;
|
|
151
|
+
}
|
|
152
|
+
/** The supervisor's collaborators, all required, bound at the composition root. */
|
|
153
|
+
export interface TowerSupervisorDeps {
|
|
154
|
+
/** The running daemon's config (null before the poller starts). */
|
|
155
|
+
readConfig: () => DaemonConfig | null;
|
|
156
|
+
/** The product-scoped config for a product this daemon runs, or null. */
|
|
157
|
+
productConfig: (config: DaemonConfig, productId: string) => DaemonConfig | null;
|
|
158
|
+
/** Read at use time: the engine receives the governor after composition. */
|
|
159
|
+
readGovernor: () => Pick<ResourceGovernor, 'tryAcquireSlot' | 'releaseSlot'> | null;
|
|
160
|
+
listOpenReviewLoops: (scope: {
|
|
161
|
+
productId: string | null;
|
|
162
|
+
}) => Promise<OpenReviewLoop[]>;
|
|
163
|
+
listTowerDecisions: (focusId: string) => Promise<FocusDecisionRecord>;
|
|
164
|
+
recordTowerDecision: (input: TowerDecisionInput) => Promise<{
|
|
165
|
+
decision: TowerDecision;
|
|
166
|
+
created: boolean;
|
|
167
|
+
}>;
|
|
168
|
+
/** The once-per-criterion-per-arm rule: a repeat is filed to the operator by the edge. Throws on failure. */
|
|
169
|
+
escalateRepeatReviewLoop: (args: {
|
|
170
|
+
focusId: string;
|
|
171
|
+
loopDecisionId: string;
|
|
172
|
+
}) => Promise<RepeatReviewLoopAnswer>;
|
|
173
|
+
findFocus: (focusId: string, productId: string | null) => Promise<SupervisedFocus | null>;
|
|
174
|
+
focusWorktreePath: (focusId: string) => string | null;
|
|
175
|
+
gatherHistory: (args: GatherLoopHistoryArgs) => Promise<LoopHistory>;
|
|
176
|
+
spawn: (opts: TowerSupervisorSpawnOptions) => Promise<TowerSupervisorSpawnResult>;
|
|
177
|
+
fileUndecidedLoop: (filing: UndecidedLoopFiling) => Promise<{
|
|
178
|
+
escalationId: string | null;
|
|
179
|
+
}>;
|
|
180
|
+
/** Drop a review directive queued for the focus (directive-queue clearPendingReviewDirective). */
|
|
181
|
+
dropPendingReviewDirective: (focusId: string) => boolean;
|
|
182
|
+
newSessionId: () => string;
|
|
183
|
+
}
|
|
184
|
+
/** Where the record stands for one held loop. */
|
|
185
|
+
export type LoopSettlement = {
|
|
186
|
+
kind: 'bounded';
|
|
187
|
+
bounded: TowerDecision[];
|
|
188
|
+
amendmentIds: string[];
|
|
189
|
+
} | {
|
|
190
|
+
kind: 'bound_unapplied';
|
|
191
|
+
bounded: TowerDecision[];
|
|
192
|
+
} | {
|
|
193
|
+
kind: 'awaiting_operator';
|
|
194
|
+
escalations: TowerDecision[];
|
|
195
|
+
} | {
|
|
196
|
+
kind: 'undecided';
|
|
197
|
+
};
|
|
198
|
+
/** Pure: the decisions on the record that are ABOUT a loop (evidence.loopDecisionId). */
|
|
199
|
+
export declare function decisionsAboutLoop(decisions: readonly TowerDecision[], loopDecisionId: string): TowerDecision[];
|
|
200
|
+
/**
|
|
201
|
+
* Pure: where a held loop stands on the record. An escalation to the operator
|
|
202
|
+
* wins over a bound (a supervisor that escalated did not settle it); a
|
|
203
|
+
* criterion_bounded decision naming the loop settles it only when the edge
|
|
204
|
+
* reports its bound APPLIED (an amendment of the criterion since detection);
|
|
205
|
+
* a bound on the record without one is `bound_unapplied`, which releases
|
|
206
|
+
* nothing; anything else is undecided.
|
|
207
|
+
*/
|
|
208
|
+
export declare function settlementOf(record: Pick<FocusDecisionRecord, 'decisions' | 'appliedBounds'>, loopDecisionId: string): LoopSettlement;
|
|
209
|
+
/** Pure: the loop_resolved the daemon records once the criterion was bounded. */
|
|
210
|
+
export declare function loopResolvedDecision(loop: HeldLoop, bounded: readonly TowerDecision[], amendmentIds: readonly string[]): TowerDecisionInput;
|
|
211
|
+
/** Pure: what a finished spawn was -- not run at all (retry, uncounted), or ran. */
|
|
212
|
+
export declare function spawnRan(result: TowerSupervisorSpawnResult): boolean;
|
|
213
|
+
/** Pure: a one-line account of a spawn's end. */
|
|
214
|
+
export declare function describeSpawnEnd(result: TowerSupervisorSpawnResult): string;
|
|
215
|
+
/** Build the TowerSupervisor the composition root binds (one per process). */
|
|
216
|
+
export declare function createTowerSupervisor(deps: TowerSupervisorDeps): TowerSupervisor & {
|
|
217
|
+
/** Test seam: resolves once every session started so far has finished. */
|
|
218
|
+
settled(): Promise<void>;
|
|
219
|
+
};
|
|
220
|
+
//# sourceMappingURL=tower-supervisor-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-supervisor-session.d.ts","sourceRoot":"","sources":["../../src/tower/tower-supervisor-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/composition/tower-escalation-context.test.ts,
|
|
3
|
+
// packages/daemon/src/tower/tower-escalation-session.test.ts,
|
|
4
|
+
// packages/daemon/src/tower/tower-supervisor-session.test.ts,
|
|
5
|
+
// packages/daemon/src/tower/tower-supervisor.test.ts
|
|
6
|
+
// PINNED-BY-END
|
|
7
|
+
import { createLogger } from '../log/daemon-log.js';
|
|
8
|
+
import { heldLoopOf } from './tower-supervisor-history.js';
|
|
9
|
+
import { buildTowerSupervisorPrompt, parseTowerDecisionLine } from './tower-supervisor-prompt.js';
|
|
10
|
+
import { emptySweepCounts, } from './tower-supervisor.js';
|
|
11
|
+
const log = createLogger({ module: 'tower' });
|
|
12
|
+
export const TOWER_SUPERVISOR_MODEL = 'opus';
|
|
13
|
+
/** Kill a supervisor that has not exited within this window (30 minutes: it may run the disputed tests). */
|
|
14
|
+
export const TOWER_SUPERVISOR_TIMEOUT_MS = 30 * 60 * 1000;
|
|
15
|
+
/** Sessions that ran without deciding, per loop, before the daemon stops trying and files it. */
|
|
16
|
+
export const TOWER_SUPERVISOR_MAX_ATTEMPTS = 2;
|
|
17
|
+
/** Governor engine name for supervisor slots (no per-engine limit: bounded by the global session cap). */
|
|
18
|
+
export const TOWER_SUPERVISOR_GOVERNOR_ENGINE = 'tower-supervisor';
|
|
19
|
+
/**
|
|
20
|
+
* The scoped MCP profile the supervisor's Telora server runs under
|
|
21
|
+
* (mcp/telora-products profile-scope.ts TOWER_SUPERVISOR_PROFILE): the tool-level
|
|
22
|
+
* bound on "it never grants review budget".
|
|
23
|
+
*/
|
|
24
|
+
export const TOWER_SUPERVISOR_MCP_PROFILE = 'tower_supervisor';
|
|
25
|
+
/** escalation_kind of the observation filed when every attempt ran without deciding. */
|
|
26
|
+
export const TOWER_SUPERVISOR_UNDECIDED_KIND = 'tower_supervisor_undecided';
|
|
27
|
+
/**
|
|
28
|
+
* The tools a supervisor session is pre-approved for: reading and running the
|
|
29
|
+
* disputed check in the worktree, and the Telora acts it decides through --
|
|
30
|
+
* the amendment (telora_product_focus amend_criterion), the findings and Tasks
|
|
31
|
+
* (telora_product_issue), the decision record (telora_product_tower), the one
|
|
32
|
+
* escalation (telora_agent) -- plus the context it reads. This list only
|
|
33
|
+
* PRE-APPROVES; what the Telora tools can DO is bounded by the scoped MCP
|
|
34
|
+
* profile (TOWER_SUPERVISOR_MCP_PROFILE), under which none can arm, unarm or
|
|
35
|
+
* grant review cycles: the budget is the daemon's.
|
|
36
|
+
*/
|
|
37
|
+
export const TOWER_SUPERVISOR_MCP_TOOLS = [
|
|
38
|
+
'Read', 'Grep', 'Glob', 'Bash',
|
|
39
|
+
'mcp__telora-products__telora_product_focus',
|
|
40
|
+
'mcp__telora-products__telora_product_issue',
|
|
41
|
+
'mcp__telora-products__telora_product_delivery',
|
|
42
|
+
'mcp__telora-products__telora_product_tower',
|
|
43
|
+
'mcp__telora-products__telora_agent',
|
|
44
|
+
'mcp__telora-products__telora_reality_tree_traverse',
|
|
45
|
+
'mcp__telora-products__telora_wiki_search',
|
|
46
|
+
];
|
|
47
|
+
/** Pure: the decisions on the record that are ABOUT a loop (evidence.loopDecisionId). */
|
|
48
|
+
export function decisionsAboutLoop(decisions, loopDecisionId) {
|
|
49
|
+
return decisions.filter((d) => {
|
|
50
|
+
const ev = d.evidence;
|
|
51
|
+
return ev !== null && typeof ev === 'object' && ev.loopDecisionId === loopDecisionId;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Pure: where a held loop stands on the record. An escalation to the operator
|
|
56
|
+
* wins over a bound (a supervisor that escalated did not settle it); a
|
|
57
|
+
* criterion_bounded decision naming the loop settles it only when the edge
|
|
58
|
+
* reports its bound APPLIED (an amendment of the criterion since detection);
|
|
59
|
+
* a bound on the record without one is `bound_unapplied`, which releases
|
|
60
|
+
* nothing; anything else is undecided.
|
|
61
|
+
*/
|
|
62
|
+
export function settlementOf(record, loopDecisionId) {
|
|
63
|
+
const about = decisionsAboutLoop(record.decisions, loopDecisionId);
|
|
64
|
+
const escalations = about.filter((d) => d.kind === 'escalated_to_operator');
|
|
65
|
+
if (escalations.length > 0)
|
|
66
|
+
return { kind: 'awaiting_operator', escalations };
|
|
67
|
+
const bounded = about.filter((d) => d.kind === 'criterion_bounded');
|
|
68
|
+
if (bounded.length === 0)
|
|
69
|
+
return { kind: 'undecided' };
|
|
70
|
+
const applied = (record.appliedBounds ?? []).find((b) => b.loopDecisionId === loopDecisionId);
|
|
71
|
+
return applied && applied.amendmentIds.length > 0
|
|
72
|
+
? { kind: 'bounded', bounded, amendmentIds: applied.amendmentIds }
|
|
73
|
+
: { kind: 'bound_unapplied', bounded };
|
|
74
|
+
}
|
|
75
|
+
/** Pure: the loop_resolved the daemon records once the criterion was bounded. */
|
|
76
|
+
export function loopResolvedDecision(loop, bounded, amendmentIds) {
|
|
77
|
+
return {
|
|
78
|
+
focusId: loop.focusId,
|
|
79
|
+
kind: 'loop_resolved',
|
|
80
|
+
decidedByKind: 'daemon',
|
|
81
|
+
summary: `Released the held review loop on criterion "${loop.criterion}": the Tower supervisor bounded it.`,
|
|
82
|
+
rationale: `The supervisor recorded ${bounded.length} criterion_bounded decision(s) naming this loop and applied the ` +
|
|
83
|
+
`bound (${amendmentIds.length} amendment(s) of the criterion since the loop was detected), so the criterion ` +
|
|
84
|
+
'the loop could not converge on now reads as a closed list plus a named judge. The next review is a fresh ' +
|
|
85
|
+
'session that judges the amended wording.',
|
|
86
|
+
evidence: {
|
|
87
|
+
loopDecisionId: loop.towerDecisionId,
|
|
88
|
+
boundDecisionIds: bounded.map((d) => d.towerDecisionId),
|
|
89
|
+
amendmentIds: [...amendmentIds],
|
|
90
|
+
supervisorSessionIds: [...new Set(bounded.map((d) => d.agentSessionId).filter((s) => s !== null))],
|
|
91
|
+
},
|
|
92
|
+
criterionKey: loop.criterionKey,
|
|
93
|
+
nodeId: loop.nodeId,
|
|
94
|
+
resolvesDecisionId: loop.towerDecisionId,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** Pure: what a finished spawn was -- not run at all (retry, uncounted), or ran. */
|
|
98
|
+
export function spawnRan(result) {
|
|
99
|
+
return result.started && result.modelUnavailable === undefined;
|
|
100
|
+
}
|
|
101
|
+
/** Pure: a one-line account of a spawn's end. */
|
|
102
|
+
export function describeSpawnEnd(result) {
|
|
103
|
+
if (result.modelUnavailable)
|
|
104
|
+
return `model unavailable (${result.modelUnavailable.kind})`;
|
|
105
|
+
if (!result.started)
|
|
106
|
+
return result.errorMessage ?? 'did not start';
|
|
107
|
+
if (result.timedOut)
|
|
108
|
+
return 'timed out (killed)';
|
|
109
|
+
const said = parseTowerDecisionLine(result.stdout);
|
|
110
|
+
return `exited ${result.exitCode ?? 'null'}${result.errorMessage ? ` (${result.errorMessage})` : ''}${said ? `; said "${said}"` : ''}`;
|
|
111
|
+
}
|
|
112
|
+
/** Record loop_resolved for a bounded loop and drop the review directive queued on the old wording. */
|
|
113
|
+
async function release(st, loop, bounded, amendmentIds) {
|
|
114
|
+
await st.deps.recordTowerDecision(loopResolvedDecision(loop, bounded, amendmentIds));
|
|
115
|
+
const dropped = st.deps.dropPendingReviewDirective(loop.focusId);
|
|
116
|
+
log.info(`[tower-supervisor] released the held loop ${loop.towerDecisionId.slice(0, 8)} on "${loop.criterion}": the ` +
|
|
117
|
+
`criterion was bounded${dropped ? '; dropped the review directive queued on the old wording' : ''}.`);
|
|
118
|
+
st.attempts.delete(loop.towerDecisionId);
|
|
119
|
+
return 'resolved';
|
|
120
|
+
}
|
|
121
|
+
/** Every attempt ran without deciding: file the loop for a routing decider and record escalated_to_operator. */
|
|
122
|
+
async function giveUp(st, loop, focus, config, detail) {
|
|
123
|
+
const tried = st.attempts.get(loop.towerDecisionId) ?? 0;
|
|
124
|
+
const filed = await st.deps.fileUndecidedLoop({
|
|
125
|
+
organizationId: config.organizationId, productId: focus.productId, focusId: focus.focusId,
|
|
126
|
+
escalationKind: TOWER_SUPERVISOR_UNDECIDED_KIND,
|
|
127
|
+
description: `The review loop of focus "${focus.focusName}" on criterion "${loop.criterion}" is held, and the Tower ` +
|
|
128
|
+
`supervisor ran ${tried} time(s) without deciding it (last: ${detail}). The focus spawns no coding or ` +
|
|
129
|
+
'review pass until the criterion is bounded or the operator rules.',
|
|
130
|
+
whatWasTried: `${tried} one-shot supervisor session(s); none recorded escalated_to_operator, or a criterion_bounded whose ` +
|
|
131
|
+
'amendment of the criterion landed.',
|
|
132
|
+
helpNeeded: 'Decide the loop: bound the criterion (telora_product_focus amend_criterion) and record it ' +
|
|
133
|
+
'(telora_product_tower decision_record criterion_bounded with loopDecisionId), or escalate to the operator.',
|
|
134
|
+
metadata: { loopDecisionId: loop.towerDecisionId, attempts: tried, lastDetail: detail },
|
|
135
|
+
});
|
|
136
|
+
await st.deps.recordTowerDecision({
|
|
137
|
+
focusId: loop.focusId, kind: 'escalated_to_operator', decidedByKind: 'daemon',
|
|
138
|
+
summary: `Handed the held review loop on "${loop.criterion}" on: the Tower supervisor could not decide it.`,
|
|
139
|
+
rationale: `${tried} supervisor session(s) ran and none recorded a decision (last: ${detail}). The daemon stops ` +
|
|
140
|
+
'spawning supervisors for this loop and files it for a routing decider, which makes it the operator\'s ' +
|
|
141
|
+
'when only a human can rule. The loop stays held.',
|
|
142
|
+
evidence: { loopDecisionId: loop.towerDecisionId, attempts: tried, lastDetail: detail },
|
|
143
|
+
criterionKey: loop.criterionKey, nodeId: loop.nodeId, escalationId: filed.escalationId,
|
|
144
|
+
});
|
|
145
|
+
log.warn(`[tower-supervisor] gave up on the held loop ${loop.towerDecisionId.slice(0, 8)} of "${focus.focusName}" after ${tried} attempt(s); filed ${filed.escalationId ?? '(correlated)'}.`);
|
|
146
|
+
}
|
|
147
|
+
/** After a session exits: release a bounded loop, leave an escalated one held, count an undecided run. */
|
|
148
|
+
async function settleAfterRun(st, loop, focus, config, result) {
|
|
149
|
+
const detail = describeSpawnEnd(result);
|
|
150
|
+
const record = await st.deps.listTowerDecisions(loop.focusId);
|
|
151
|
+
const settled = settlementOf(record, loop.towerDecisionId);
|
|
152
|
+
if (settled.kind === 'bounded') {
|
|
153
|
+
await release(st, loop, settled.bounded, settled.amendmentIds);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (settled.kind === 'awaiting_operator') {
|
|
157
|
+
log.info(`[tower-supervisor] the held loop ${loop.towerDecisionId.slice(0, 8)} of "${focus.focusName}" was escalated to the operator; it stays held.`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (!spawnRan(result)) {
|
|
161
|
+
log.info(`[tower-supervisor] supervisor for "${focus.focusName}" did not run (${detail}); the next sweep retries.`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const tried = (st.attempts.get(loop.towerDecisionId) ?? 0) + 1;
|
|
165
|
+
st.attempts.set(loop.towerDecisionId, tried);
|
|
166
|
+
const outcome = settled.kind === 'bound_unapplied'
|
|
167
|
+
? `${detail}, recording criterion_bounded with no amendment of the criterion -- the bound was not applied, so the loop stays held`
|
|
168
|
+
: `${detail} without deciding`;
|
|
169
|
+
log.warn(`[tower-supervisor] supervisor for "${focus.focusName}" ${outcome} (attempt ${tried} of ${TOWER_SUPERVISOR_MAX_ATTEMPTS}).`);
|
|
170
|
+
if (tried >= TOWER_SUPERVISOR_MAX_ATTEMPTS)
|
|
171
|
+
await giveUp(st, loop, focus, config, settled.kind === 'bound_unapplied' ? `${detail}; bound recorded, never applied` : detail);
|
|
172
|
+
}
|
|
173
|
+
/** One supervisor session, inside a governor slot: gather, prompt, spawn, settle. */
|
|
174
|
+
async function runSession(st, loop, focus, config) {
|
|
175
|
+
const governor = st.deps.readGovernor();
|
|
176
|
+
let token = null;
|
|
177
|
+
if (governor) {
|
|
178
|
+
token = governor.tryAcquireSlot(TOWER_SUPERVISOR_GOVERNOR_ENGINE);
|
|
179
|
+
if (!token) {
|
|
180
|
+
log.info(`[tower-supervisor] no governor slot free for "${focus.focusName}"; the next sweep retries.`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const repoRoot = st.deps.focusWorktreePath(focus.focusId) ?? config.repoPath;
|
|
186
|
+
const history = await st.deps.gatherHistory({ loop, productId: focus.productId, config, repoRoot });
|
|
187
|
+
const supervisorSessionId = st.deps.newSessionId();
|
|
188
|
+
const prompt = buildTowerSupervisorPrompt({ focus, loop, supervisorSessionId, history });
|
|
189
|
+
log.info(`[tower-supervisor] deciding the held loop ${loop.towerDecisionId.slice(0, 8)} of "${focus.focusName}" (session ${supervisorSessionId.slice(0, 8)}).`);
|
|
190
|
+
const result = await st.deps.spawn({
|
|
191
|
+
config, prompt, cwd: repoRoot, focusId: focus.focusId, loopDecisionId: loop.towerDecisionId,
|
|
192
|
+
model: TOWER_SUPERVISOR_MODEL, timeoutMs: TOWER_SUPERVISOR_TIMEOUT_MS, allowedTools: TOWER_SUPERVISOR_MCP_TOOLS,
|
|
193
|
+
});
|
|
194
|
+
await settleAfterRun(st, loop, focus, config, result);
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
if (token && governor)
|
|
198
|
+
governor.releaseSlot(token);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/** One supervision step for one held loop; starts a session in the background when one is owed. Never throws. */
|
|
202
|
+
async function supervise(st, loopDecision, productId, known) {
|
|
203
|
+
const loopId = loopDecision.towerDecisionId;
|
|
204
|
+
if (st.inFlight.has(loopId))
|
|
205
|
+
return 'in_flight';
|
|
206
|
+
try {
|
|
207
|
+
const loop = heldLoopOf(loopDecision);
|
|
208
|
+
const config = st.deps.readConfig();
|
|
209
|
+
if (!loop || !config)
|
|
210
|
+
return 'skipped';
|
|
211
|
+
const record = known ?? await st.deps.listTowerDecisions(loop.focusId);
|
|
212
|
+
if (!record.openLoopDecisionIds.includes(loopId))
|
|
213
|
+
return 'not_open';
|
|
214
|
+
const settled = settlementOf(record, loopId);
|
|
215
|
+
if (settled.kind === 'bounded')
|
|
216
|
+
return await release(st, loop, settled.bounded, settled.amendmentIds);
|
|
217
|
+
if (settled.kind === 'awaiting_operator')
|
|
218
|
+
return 'awaiting_operator';
|
|
219
|
+
const repeat = await st.deps.escalateRepeatReviewLoop({ focusId: loop.focusId, loopDecisionId: loopId });
|
|
220
|
+
if (repeat.repeat) {
|
|
221
|
+
log.warn(`[tower-supervisor] the loop ${loopId.slice(0, 8)} on "${loop.criterion}" repeats a criterion the supervisor ` +
|
|
222
|
+
`already bounded under this arm: no second supervisor; filed to the operator (${repeat.escalationId ?? 'escalation unknown'}).`);
|
|
223
|
+
return 'awaiting_operator';
|
|
224
|
+
}
|
|
225
|
+
const focus = await st.deps.findFocus(loop.focusId, productId);
|
|
226
|
+
const scoped = focus ? st.deps.productConfig(config, focus.productId) : null;
|
|
227
|
+
if (!focus || !scoped)
|
|
228
|
+
return 'skipped';
|
|
229
|
+
if ((st.attempts.get(loopId) ?? 0) >= TOWER_SUPERVISOR_MAX_ATTEMPTS) {
|
|
230
|
+
await giveUp(st, loop, focus, scoped, 'the previous hand-off did not land');
|
|
231
|
+
return 'awaiting_operator';
|
|
232
|
+
}
|
|
233
|
+
const run = runSession(st, loop, focus, scoped)
|
|
234
|
+
.catch((err) => log.warn(`[tower-supervisor] supervision of "${focus.focusName}" failed: ${err.message}; the next sweep retries.`))
|
|
235
|
+
.finally(() => st.inFlight.delete(loopId));
|
|
236
|
+
st.inFlight.set(loopId, run);
|
|
237
|
+
return 'started';
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
log.warn(`[tower-supervisor] could not read the held loop ${loopId.slice(0, 8)}: ${err.message}; the next sweep retries.`);
|
|
241
|
+
return 'unreadable';
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** A sweep's step for one open loop: read its focus record, then supervise it. */
|
|
245
|
+
async function superviseOpen(st, open, productId) {
|
|
246
|
+
if (st.inFlight.has(open.towerDecisionId))
|
|
247
|
+
return 'in_flight';
|
|
248
|
+
try {
|
|
249
|
+
const record = await st.deps.listTowerDecisions(open.focusId);
|
|
250
|
+
const decision = record.decisions.find((d) => d.towerDecisionId === open.towerDecisionId);
|
|
251
|
+
return decision ? await supervise(st, decision, productId, record) : 'not_open';
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
log.warn(`[tower-supervisor] focus record read failed for ${open.focusId.slice(0, 8)}: ${err.message}`);
|
|
255
|
+
return 'unreadable';
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function tally(counts, outcome) {
|
|
259
|
+
if (outcome === 'started')
|
|
260
|
+
counts.started += 1;
|
|
261
|
+
else if (outcome === 'in_flight')
|
|
262
|
+
counts.inFlight += 1;
|
|
263
|
+
else if (outcome === 'resolved')
|
|
264
|
+
counts.resolved += 1;
|
|
265
|
+
else if (outcome === 'awaiting_operator')
|
|
266
|
+
counts.awaitingOperator += 1;
|
|
267
|
+
else if (outcome === 'unreadable')
|
|
268
|
+
counts.unreadable += 1;
|
|
269
|
+
else
|
|
270
|
+
counts.skipped += 1;
|
|
271
|
+
}
|
|
272
|
+
/** Sweep the held loops of every configured product. */
|
|
273
|
+
async function sweepHeldLoops(st) {
|
|
274
|
+
const counts = emptySweepCounts();
|
|
275
|
+
const config = st.deps.readConfig();
|
|
276
|
+
if (!config)
|
|
277
|
+
return counts;
|
|
278
|
+
for (const product of config.products) {
|
|
279
|
+
let loops;
|
|
280
|
+
try {
|
|
281
|
+
loops = await st.deps.listOpenReviewLoops({ productId: product.id });
|
|
282
|
+
}
|
|
283
|
+
catch (err) {
|
|
284
|
+
log.warn(`[tower-supervisor] open-loop read failed for product ${product.id.slice(0, 8)}: ${err.message}`);
|
|
285
|
+
counts.unreadable += 1;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
for (const open of loops) {
|
|
289
|
+
counts.openLoops += 1;
|
|
290
|
+
tally(counts, await superviseOpen(st, open, product.id));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return counts;
|
|
294
|
+
}
|
|
295
|
+
/** Build the TowerSupervisor the composition root binds (one per process). */
|
|
296
|
+
export function createTowerSupervisor(deps) {
|
|
297
|
+
const st = { deps, inFlight: new Map(), attempts: new Map() };
|
|
298
|
+
return {
|
|
299
|
+
onLoopDetected: async (notice) => {
|
|
300
|
+
const outcome = await supervise(st, notice.decision, null, null);
|
|
301
|
+
log.info(`[tower-supervisor] "${notice.focusName}" held loop handed to the supervisor: ${outcome}.`);
|
|
302
|
+
},
|
|
303
|
+
sweep: () => sweepHeldLoops(st),
|
|
304
|
+
settled: async () => { await Promise.all([...st.inFlight.values()]); },
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=tower-supervisor-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-supervisor-session.js","sourceRoot":"","sources":["../../src/tower/tower-supervisor-session.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,+EAA+E;AAC/E,gEAAgE;AAChE,gEAAgE;AAChE,uDAAuD;AACvD,gBAAgB;AAyFhB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,UAAU,EAA+D,MAAM,+BAA+B,CAAC;AACxH,OAAO,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAClG,OAAO,EACL,gBAAgB,GAIjB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C,4GAA4G;AAC5G,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1D,iGAAiG;AACjG,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,0GAA0G;AAC1G,MAAM,CAAC,MAAM,gCAAgC,GAAG,kBAAkB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,kBAAkB,CAAC;AAE/D,wFAAwF;AACxF,MAAM,CAAC,MAAM,+BAA+B,GAAG,4BAA4B,CAAC;AAE5E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsB;IAC3D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC9B,4CAA4C;IAC5C,4CAA4C;IAC5C,+CAA+C;IAC/C,4CAA4C;IAC5C,oCAAoC;IACpC,oDAAoD;IACpD,0CAA0C;CAC3C,CAAC;AA4EF,yFAAyF;AACzF,MAAM,UAAU,kBAAkB,CAAC,SAAmC,EAAE,cAAsB;IAC5F,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC;QACtB,OAAO,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAK,EAAmC,CAAC,cAAc,KAAK,cAAc,CAAC;IACzH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,MAAgE,EAAE,cAAsB;IACnH,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,uBAAuB,CAAC,CAAC;IAC5E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAC;IAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACvD,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,cAAc,CAAC,CAAC;IAC9F,OAAO,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAC/C,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE;QAClE,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,IAAc,EAAE,OAAiC,EAAE,YAA+B;IACrH,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,eAAe;QACrB,aAAa,EAAE,QAAQ;QACvB,OAAO,EAAE,+CAA+C,IAAI,CAAC,SAAS,qCAAqC;QAC3G,SAAS,EACP,2BAA2B,OAAO,CAAC,MAAM,kEAAkE;YAC3G,UAAU,YAAY,CAAC,MAAM,gFAAgF;YAC7G,2GAA2G;YAC3G,0CAA0C;QAC5C,QAAQ,EAAE;YACR,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;YACvD,YAAY,EAAE,CAAC,GAAG,YAAY,CAAC;YAC/B,oBAAoB,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;SAChH;QACD,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,kBAAkB,EAAE,IAAI,CAAC,eAAe;KACzC,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,QAAQ,CAAC,MAAkC;IACzD,OAAO,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,CAAC;AACjE,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,gBAAgB,CAAC,MAAkC;IACjE,IAAI,MAAM,CAAC,gBAAgB;QAAE,OAAO,sBAAsB,MAAM,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC;IAC1F,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,YAAY,IAAI,eAAe,CAAC;IACnE,IAAI,MAAM,CAAC,QAAQ;QAAE,OAAO,oBAAoB,CAAC;IACjD,MAAM,IAAI,GAAG,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,OAAO,UAAU,MAAM,CAAC,QAAQ,IAAI,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACzI,CAAC;AASD,uGAAuG;AACvG,KAAK,UAAU,OAAO,CAAC,EAAmB,EAAE,IAAc,EAAE,OAAwB,EAAE,YAAsB;IAC1G,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjE,GAAG,CAAC,IAAI,CACN,6CAA6C,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,SAAS,SAAS;QAC5G,wBAAwB,OAAO,CAAC,CAAC,CAAC,0DAA0D,CAAC,CAAC,CAAC,EAAE,GAAG,CACrG,CAAC;IACF,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzC,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,gHAAgH;AAChH,KAAK,UAAU,MAAM,CAAC,EAAmB,EAAE,IAAc,EAAE,KAAsB,EAAE,MAAoB,EAAE,MAAc;IACrH,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC;QAC5C,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO;QACzF,cAAc,EAAE,+BAA+B;QAC/C,WAAW,EACT,6BAA6B,KAAK,CAAC,SAAS,mBAAmB,IAAI,CAAC,SAAS,2BAA2B;YACxG,kBAAkB,KAAK,uCAAuC,MAAM,mCAAmC;YACvG,mEAAmE;QACrE,YAAY,EACV,GAAG,KAAK,qGAAqG;YAC7G,oCAAoC;QACtC,UAAU,EACR,4FAA4F;YAC5F,4GAA4G;QAC9G,QAAQ,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE;KACxF,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC;QAChC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,uBAAuB,EAAE,aAAa,EAAE,QAAQ;QAC7E,OAAO,EAAE,mCAAmC,IAAI,CAAC,SAAS,iDAAiD;QAC3G,SAAS,EACP,GAAG,KAAK,kEAAkE,MAAM,sBAAsB;YACtG,wGAAwG;YACxG,kDAAkD;QACpD,QAAQ,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE;QACvF,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY;KACvF,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,CAAC,+CAA+C,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,KAAK,CAAC,SAAS,WAAW,KAAK,sBAAsB,KAAK,CAAC,YAAY,IAAI,cAAc,GAAG,CAAC,CAAC;AAChM,CAAC;AAED,0GAA0G;AAC1G,KAAK,UAAU,cAAc,CAC3B,EAAmB,EAAE,IAAc,EAAE,KAAsB,EAAE,MAAoB,EAAE,MAAkC;IAErH,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAAC,MAAM,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC3G,IAAI,OAAO,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,oCAAoC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,KAAK,CAAC,SAAS,iDAAiD,CAAC,CAAC;QACvJ,OAAO;IACT,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,SAAS,kBAAkB,MAAM,4BAA4B,CAAC,CAAC;QACpH,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/D,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,KAAK,iBAAiB;QAChD,CAAC,CAAC,GAAG,MAAM,uHAAuH;QAClI,CAAC,CAAC,GAAG,MAAM,mBAAmB,CAAC;IACjC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,SAAS,KAAK,OAAO,aAAa,KAAK,OAAO,6BAA6B,IAAI,CAAC,CAAC;IACtI,IAAI,KAAK,IAAI,6BAA6B;QAAE,MAAM,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,iCAAiC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9K,CAAC;AAED,qFAAqF;AACrF,KAAK,UAAU,UAAU,CAAC,EAAmB,EAAE,IAAc,EAAE,KAAsB,EAAE,MAAoB;IACzG,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IACxC,IAAI,KAAK,GAAqB,IAAI,CAAC;IACnC,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,gCAAgC,CAAC,CAAC;QAClE,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,iDAAiD,KAAK,CAAC,SAAS,4BAA4B,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;IACjI,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC;QAC7E,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpG,MAAM,mBAAmB,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,0BAA0B,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,CAAC;QACzF,GAAG,CAAC,IAAI,CAAC,6CAA6C,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,KAAK,CAAC,SAAS,cAAc,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAChK,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACjC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe;YAC3F,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,2BAA2B,EAAE,YAAY,EAAE,0BAA0B;SAChH,CAAC,CAAC;QACH,MAAM,cAAc,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;YAAS,CAAC;QACT,IAAI,KAAK,IAAI,QAAQ;YAAE,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAID,iHAAiH;AACjH,KAAK,UAAU,SAAS,CACtB,EAAmB,EAAE,YAA2B,EAAE,SAAwB,EAAE,KAAyB;IAErG,MAAM,MAAM,GAAG,YAAY,CAAC,eAAe,CAAC;IAC5C,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,WAAW,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QACvC,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,UAAU,CAAC;QACpE,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,MAAM,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACtG,IAAI,OAAO,CAAC,IAAI,KAAK,mBAAmB;YAAE,OAAO,mBAAmB,CAAC;QACrE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;QACzG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CACN,+BAA+B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,SAAS,uCAAuC;gBAC9G,gFAAgF,MAAM,CAAC,YAAY,IAAI,oBAAoB,IAAI,CAChI,CAAC;YACF,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7E,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,6BAA6B,EAAE,CAAC;YACpE,MAAM,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,CAAC,CAAC;YAC5E,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC;aAC5C,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,SAAS,aAAc,GAAa,CAAC,OAAO,2BAA2B,CAAC,CAAC;aACtJ,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,mDAAmD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAM,GAAa,CAAC,OAAO,2BAA2B,CAAC,CAAC;QACtI,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,KAAK,UAAU,aAAa,CAAC,EAAmB,EAAE,IAAoB,EAAE,SAAiB;IACvF,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC;QAAE,OAAO,WAAW,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1F,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAClF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,mDAAmD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACnH,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,MAAkC,EAAE,OAA+B;IAChF,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;SAC1C,IAAI,OAAO,KAAK,WAAW;QAAE,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;SAClD,IAAI,OAAO,KAAK,UAAU;QAAE,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;SACjD,IAAI,OAAO,KAAK,mBAAmB;QAAE,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC;SAClE,IAAI,OAAO,KAAK,YAAY;QAAE,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;;QACrD,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,wDAAwD;AACxD,KAAK,UAAU,cAAc,CAAC,EAAmB;IAC/C,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,KAAuB,CAAC;QAC5B,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,wDAAwD,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACtH,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;YACtB,KAAK,CAAC,MAAM,EAAE,MAAM,aAAa,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,qBAAqB,CAAC,IAAyB;IAI7D,MAAM,EAAE,GAAoB,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAC/E,OAAO;QACL,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC/B,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACjE,GAAG,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,SAAS,yCAAyC,OAAO,GAAG,CAAC,CAAC;QACvG,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;KACvE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE TOWER SUPERVISOR: the actor a held review loop is handed to.
|
|
3
|
+
*
|
|
4
|
+
* A review loop that cannot converge (supervision/review-loop-detector.ts) is
|
|
5
|
+
* a judgement call -- is the criterion unbounded, or does the work really fall
|
|
6
|
+
* short? The operator ruled that a Tower supervisor decides it,
|
|
7
|
+
* WITHOUT the operator in the loop, and reports what it decided on the focus
|
|
8
|
+
* (focus_tower_decisions). The review exit holds the loop, records the
|
|
9
|
+
* `loop_detected` decision, and calls `onLoopDetected`
|
|
10
|
+
* (completion/review-cycle-budget/review-loop-detection.ts). The supervisor
|
|
11
|
+
* session bounds the criterion (or, when it cannot, escalates to the
|
|
12
|
+
* operator); the daemon then records the `loop_resolved` that names the loop,
|
|
13
|
+
* which releases the hold (supervision/review-loop-hold.ts). It is called once
|
|
14
|
+
* per criterion per arm: a loop that returns after a bound under the same arm
|
|
15
|
+
* goes to the operator instead (tower/tower-supervisor-session.ts).
|
|
16
|
+
*
|
|
17
|
+
* This module is the contract; the implementation is
|
|
18
|
+
* tower/tower-supervisor-session.ts, bound once at the composition root
|
|
19
|
+
* (composition/review-loop-context.ts) and never defaulted in a consumer.
|
|
20
|
+
*
|
|
21
|
+
* @module tower/tower-supervisor
|
|
22
|
+
*/
|
|
23
|
+
import type { TowerDecision } from '../queries/tower-decisions/tower-decisions.js';
|
|
24
|
+
/** What the supervisor is handed when a loop is held. */
|
|
25
|
+
export interface LoopDetectedNotice {
|
|
26
|
+
focusId: string;
|
|
27
|
+
focusName: string;
|
|
28
|
+
/** The `loop_detected` decision recorded on the focus (its id is what a `loop_resolved` names). */
|
|
29
|
+
decision: TowerDecision;
|
|
30
|
+
criterionKey: string;
|
|
31
|
+
criterion: string;
|
|
32
|
+
nodeId: string | null;
|
|
33
|
+
/** The reviews of the loop, oldest first, with the new blocking findings each named. */
|
|
34
|
+
rounds: ReadonlyArray<{
|
|
35
|
+
reviewId: string;
|
|
36
|
+
newBlockingIssueIds: readonly string[];
|
|
37
|
+
}>;
|
|
38
|
+
/** The review-cycle count after this exit, and the budget it is measured against (logged; never handed to the session). */
|
|
39
|
+
reviewCycleCount: number;
|
|
40
|
+
cap: number;
|
|
41
|
+
}
|
|
42
|
+
/** What one supervision step did for one held loop. */
|
|
43
|
+
export type LoopSupervisionOutcome =
|
|
44
|
+
/** A supervisor session was started for it (it runs in the background). */
|
|
45
|
+
'started'
|
|
46
|
+
/** A session for it is already running in this process. */
|
|
47
|
+
| 'in_flight'
|
|
48
|
+
/** The loop is no longer open (resolved, or from a previous arm). */
|
|
49
|
+
| 'not_open'
|
|
50
|
+
/** The supervisor bounded the criterion; the daemon recorded loop_resolved. */
|
|
51
|
+
| 'resolved'
|
|
52
|
+
/** The supervisor (or the daemon, after its attempts ran out) escalated it to the operator; it stays held. */
|
|
53
|
+
| 'awaiting_operator'
|
|
54
|
+
/** Nothing could run (no daemon config, the focus is not one this daemon runs); retried next sweep. */
|
|
55
|
+
| 'skipped'
|
|
56
|
+
/** A read or write failed; retried next sweep. */
|
|
57
|
+
| 'unreadable';
|
|
58
|
+
/** One sweep over the held loops of the configured products. */
|
|
59
|
+
export interface TowerSupervisorSweepCounts {
|
|
60
|
+
openLoops: number;
|
|
61
|
+
started: number;
|
|
62
|
+
inFlight: number;
|
|
63
|
+
resolved: number;
|
|
64
|
+
awaitingOperator: number;
|
|
65
|
+
skipped: number;
|
|
66
|
+
unreadable: number;
|
|
67
|
+
}
|
|
68
|
+
/** A sweep that found nothing (each sweep starts from a copy). */
|
|
69
|
+
export declare function emptySweepCounts(): TowerSupervisorSweepCounts;
|
|
70
|
+
/** The actor that decides a held review loop. */
|
|
71
|
+
export interface TowerSupervisor {
|
|
72
|
+
/**
|
|
73
|
+
* Called once per newly recorded `loop_detected`. Starts the supervision in
|
|
74
|
+
* the background and returns at once: the review exit is never blocked on a
|
|
75
|
+
* session (the hold covers the wait). Never rejects.
|
|
76
|
+
*/
|
|
77
|
+
onLoopDetected(notice: LoopDetectedNotice): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Settle every held loop of the configured products: start a session for one
|
|
80
|
+
* nobody is deciding (a daemon restart, a failed attempt, no slot free),
|
|
81
|
+
* release one whose criterion was bounded but whose release did not land, and
|
|
82
|
+
* leave one escalated to the operator held. Never rejects.
|
|
83
|
+
*/
|
|
84
|
+
sweep(): Promise<TowerSupervisorSweepCounts>;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=tower-supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-supervisor.d.ts","sourceRoot":"","sources":["../../src/tower/tower-supervisor.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAEnF,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,mGAAmG;IACnG,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACpF,2HAA2H;IAC3H,gBAAgB,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,uDAAuD;AACvD,MAAM,MAAM,sBAAsB;AAChC,2EAA2E;AACzE,SAAS;AACX,2DAA2D;GACzD,WAAW;AACb,qEAAqE;GACnE,UAAU;AACZ,+EAA+E;GAC7E,UAAU;AACZ,8GAA8G;GAC5G,mBAAmB;AACrB,uGAAuG;GACrG,SAAS;AACX,kDAAkD;GAChD,YAAY,CAAC;AAEjB,gEAAgE;AAChE,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,IAAI,0BAA0B,CAE7D;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC9C"}
|