@telora/daemon 0.22.189 → 0.22.226
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 +6 -3
- package/dist/backends/index.d.ts.map +1 -1
- package/dist/backends/index.js +5 -1
- package/dist/backends/index.js.map +1 -1
- package/dist/completion/advancement-stall-watchdog.d.ts.map +1 -1
- package/dist/completion/advancement-stall-watchdog.js +6 -2
- package/dist/completion/advancement-stall-watchdog.js.map +1 -1
- package/dist/completion/completion-decision.d.ts +10 -1
- package/dist/completion/completion-decision.d.ts.map +1 -1
- package/dist/completion/completion-decision.js +1 -1
- package/dist/completion/completion-decision.js.map +1 -1
- package/dist/completion/completion-fact-readers.d.ts +35 -0
- package/dist/completion/completion-fact-readers.d.ts.map +1 -0
- package/dist/completion/completion-fact-readers.js +70 -0
- package/dist/completion/completion-fact-readers.js.map +1 -0
- package/dist/completion/delivery-advancement-guard.d.ts +31 -16
- package/dist/completion/delivery-advancement-guard.d.ts.map +1 -1
- package/dist/completion/delivery-advancement-guard.js +22 -37
- package/dist/completion/delivery-advancement-guard.js.map +1 -1
- package/dist/completion/detector.d.ts.map +1 -1
- package/dist/completion/detector.js +3 -1
- package/dist/completion/detector.js.map +1 -1
- package/dist/completion/event-dep-defaults.d.ts +27 -0
- package/dist/completion/event-dep-defaults.d.ts.map +1 -0
- package/dist/completion/event-dep-defaults.js +30 -0
- package/dist/completion/event-dep-defaults.js.map +1 -0
- package/dist/completion/event-phases.d.ts +19 -8
- package/dist/completion/event-phases.d.ts.map +1 -1
- package/dist/completion/event-phases.js +72 -101
- package/dist/completion/event-phases.js.map +1 -1
- package/dist/completion/event.d.ts +44 -9
- package/dist/completion/event.d.ts.map +1 -1
- package/dist/completion/event.js +36 -27
- package/dist/completion/event.js.map +1 -1
- package/dist/completion/index.js +1 -1
- package/dist/completion/progress-snapshot.d.ts +13 -9
- package/dist/completion/progress-snapshot.d.ts.map +1 -1
- package/dist/completion/progress-snapshot.js +16 -13
- package/dist/completion/progress-snapshot.js.map +1 -1
- package/dist/completion/reengagement-redrive.d.ts +8 -1
- package/dist/completion/reengagement-redrive.d.ts.map +1 -1
- package/dist/completion/reengagement-redrive.js +16 -2
- package/dist/completion/reengagement-redrive.js.map +1 -1
- package/dist/completion/session-hold.d.ts +13 -1
- package/dist/completion/session-hold.d.ts.map +1 -1
- package/dist/completion/session-hold.js +18 -0
- package/dist/completion/session-hold.js.map +1 -1
- package/dist/completion/state-cascade.d.ts.map +1 -1
- package/dist/completion/state-cascade.js +11 -19
- package/dist/completion/state-cascade.js.map +1 -1
- package/dist/completion/team-phase.d.ts.map +1 -1
- package/dist/completion/team-phase.js +1 -0
- package/dist/completion/team-phase.js.map +1 -1
- package/dist/completion/team-progress-measure.d.ts +70 -0
- package/dist/completion/team-progress-measure.d.ts.map +1 -0
- package/dist/completion/team-progress-measure.js +285 -0
- package/dist/completion/team-progress-measure.js.map +1 -0
- package/dist/completion/team-stillness.d.ts +76 -0
- package/dist/completion/team-stillness.d.ts.map +1 -0
- package/dist/completion/team-stillness.js +96 -0
- package/dist/completion/team-stillness.js.map +1 -0
- package/dist/completion/unclaimed-migration-notice-phase.d.ts +97 -0
- package/dist/completion/unclaimed-migration-notice-phase.d.ts.map +1 -0
- package/dist/completion/unclaimed-migration-notice-phase.js +270 -0
- package/dist/completion/unclaimed-migration-notice-phase.js.map +1 -0
- package/dist/completion/worker-wait.d.ts +84 -0
- package/dist/completion/worker-wait.d.ts.map +1 -0
- package/dist/completion/worker-wait.js +89 -0
- package/dist/completion/worker-wait.js.map +1 -0
- package/dist/delivery/delivery-advance-block.d.ts.map +1 -1
- package/dist/delivery/delivery-advance-block.js +1 -2
- package/dist/delivery/delivery-advance-block.js.map +1 -1
- package/dist/directive/directive-executor.d.ts.map +1 -1
- package/dist/directive/directive-executor.js +1 -20
- package/dist/directive/directive-executor.js.map +1 -1
- package/dist/focus/focus-executor.d.ts +1 -0
- package/dist/focus/focus-executor.d.ts.map +1 -1
- package/dist/focus/focus-executor.js +18 -17
- package/dist/focus/focus-executor.js.map +1 -1
- package/dist/focus/focus-lifecycle.d.ts.map +1 -1
- package/dist/focus/focus-lifecycle.js +7 -1
- package/dist/focus/focus-lifecycle.js.map +1 -1
- package/dist/focus/focus-team-state.js +1 -1
- package/dist/focus/focus-worktree-state.d.ts.map +1 -1
- package/dist/focus/focus-worktree-state.js +2 -1
- package/dist/focus/focus-worktree-state.js.map +1 -1
- package/dist/focus/listener-spawn.d.ts.map +1 -1
- package/dist/focus/listener-spawn.js +5 -20
- package/dist/focus/listener-spawn.js.map +1 -1
- package/dist/focus/listener-state.d.ts.map +1 -1
- package/dist/focus/listener-state.js +1 -0
- package/dist/focus/listener-state.js.map +1 -1
- package/dist/focus/listener.d.ts +1 -0
- package/dist/focus/listener.d.ts.map +1 -1
- package/dist/focus/listener.js +9 -0
- package/dist/focus/listener.js.map +1 -1
- package/dist/focus/migration-claim-pass.d.ts +50 -0
- package/dist/focus/migration-claim-pass.d.ts.map +1 -0
- package/dist/focus/migration-claim-pass.js +234 -0
- package/dist/focus/migration-claim-pass.js.map +1 -0
- package/dist/focus/pending-spawn-pass-deps.d.ts.map +1 -1
- package/dist/focus/pending-spawn-pass-deps.js +2 -1
- package/dist/focus/pending-spawn-pass-deps.js.map +1 -1
- package/dist/focus/team-actionable-work.d.ts +21 -0
- package/dist/focus/team-actionable-work.d.ts.map +1 -1
- package/dist/focus/team-actionable-work.js +3 -0
- package/dist/focus/team-actionable-work.js.map +1 -1
- package/dist/git/focus-integration-sync.d.ts +42 -4
- package/dist/git/focus-integration-sync.d.ts.map +1 -1
- package/dist/git/focus-integration-sync.js +53 -9
- package/dist/git/focus-integration-sync.js.map +1 -1
- package/dist/git/types.d.ts.map +1 -1
- package/dist/git/types.js +4 -1
- package/dist/git/types.js.map +1 -1
- package/dist/loops/llm-client.d.ts.map +1 -1
- package/dist/loops/llm-client.js +11 -1
- package/dist/loops/llm-client.js.map +1 -1
- package/dist/merge/merge-back-loop.d.ts.map +1 -1
- package/dist/merge/merge-back-loop.js +0 -1
- package/dist/merge/merge-back-loop.js.map +1 -1
- package/dist/migrations/migration-claim-lifecycle.d.ts +166 -0
- package/dist/migrations/migration-claim-lifecycle.d.ts.map +1 -0
- package/dist/migrations/migration-claim-lifecycle.js +198 -0
- package/dist/migrations/migration-claim-lifecycle.js.map +1 -0
- package/dist/migrations/migration-held-set.d.ts +171 -0
- package/dist/migrations/migration-held-set.d.ts.map +1 -0
- package/dist/migrations/migration-held-set.js +295 -0
- package/dist/migrations/migration-held-set.js.map +1 -0
- package/dist/migrations/migration-inventory.d.ts +187 -0
- package/dist/migrations/migration-inventory.d.ts.map +1 -0
- package/dist/migrations/migration-inventory.js +253 -0
- package/dist/migrations/migration-inventory.js.map +1 -0
- package/dist/migrations/migration-manifest.d.ts +114 -0
- package/dist/migrations/migration-manifest.d.ts.map +1 -0
- package/dist/migrations/migration-manifest.js +295 -0
- package/dist/migrations/migration-manifest.js.map +1 -0
- package/dist/prompt/team-prompt-base.js +1 -1
- package/dist/prompt-sections/migration-numbering-section.d.ts +58 -0
- package/dist/prompt-sections/migration-numbering-section.d.ts.map +1 -0
- package/dist/prompt-sections/migration-numbering-section.js +70 -0
- package/dist/prompt-sections/migration-numbering-section.js.map +1 -0
- package/dist/prompt-sections/migration-numbering-state.d.ts +30 -0
- package/dist/prompt-sections/migration-numbering-state.d.ts.map +1 -0
- package/dist/prompt-sections/migration-numbering-state.js +24 -0
- package/dist/prompt-sections/migration-numbering-state.js.map +1 -0
- package/dist/prompt-sections/unclaimed-migration-section.d.ts +38 -0
- package/dist/prompt-sections/unclaimed-migration-section.d.ts.map +1 -0
- package/dist/prompt-sections/unclaimed-migration-section.js +57 -0
- package/dist/prompt-sections/unclaimed-migration-section.js.map +1 -0
- package/dist/queries/claim-pass-focuses.d.ts +19 -0
- package/dist/queries/claim-pass-focuses.d.ts.map +1 -0
- package/dist/queries/claim-pass-focuses.js +72 -0
- package/dist/queries/claim-pass-focuses.js.map +1 -0
- package/dist/queries/daemon-connection.d.ts.map +1 -1
- package/dist/queries/daemon-connection.js +1 -0
- package/dist/queries/daemon-connection.js.map +1 -1
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +3 -1
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/delivery-gate-state.js +1 -1
- package/dist/queries/escalation-suppression.js +1 -1
- package/dist/queries/focus-discovery.d.ts +25 -2
- package/dist/queries/focus-discovery.d.ts.map +1 -1
- package/dist/queries/focus-discovery.js +16 -9
- package/dist/queries/focus-discovery.js.map +1 -1
- package/dist/queries/focus-integration-conflict.d.ts +7 -4
- package/dist/queries/focus-integration-conflict.d.ts.map +1 -1
- package/dist/queries/focus-integration-conflict.js +6 -3
- package/dist/queries/focus-integration-conflict.js.map +1 -1
- package/dist/queries/focus-unclaimed-migration.d.ts +146 -0
- package/dist/queries/focus-unclaimed-migration.d.ts.map +1 -0
- package/dist/queries/focus-unclaimed-migration.js +266 -0
- package/dist/queries/focus-unclaimed-migration.js.map +1 -0
- package/dist/queries/live-focus-branches.d.ts +32 -0
- package/dist/queries/live-focus-branches.d.ts.map +1 -0
- package/dist/queries/live-focus-branches.js +66 -0
- package/dist/queries/live-focus-branches.js.map +1 -0
- package/dist/queries/migration-claims.d.ts +25 -0
- package/dist/queries/migration-claims.d.ts.map +1 -0
- package/dist/queries/migration-claims.js +79 -0
- package/dist/queries/migration-claims.js.map +1 -0
- package/dist/queries/schemas.d.ts +17 -0
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +18 -1
- package/dist/queries/schemas.js.map +1 -1
- package/dist/queries/shared.js +1 -1
- package/dist/queries/shortfall-park-record.d.ts +6 -1
- package/dist/queries/shortfall-park-record.d.ts.map +1 -1
- package/dist/queries/shortfall-park-record.js.map +1 -1
- package/dist/queries/shortfall-rulings.d.ts +14 -2
- package/dist/queries/shortfall-rulings.d.ts.map +1 -1
- package/dist/queries/shortfall-rulings.js +17 -3
- package/dist/queries/shortfall-rulings.js.map +1 -1
- package/dist/queries/verification.js +1 -1
- package/dist/queries/verify-own-holds.d.ts.map +1 -1
- package/dist/queries/verify-own-holds.js +1 -0
- package/dist/queries/verify-own-holds.js.map +1 -1
- package/dist/session/session-lineage.d.ts.map +1 -1
- package/dist/session/session-lineage.js +3 -0
- package/dist/session/session-lineage.js.map +1 -1
- package/dist/shell/heartbeat-metadata.d.ts +48 -2
- package/dist/shell/heartbeat-metadata.d.ts.map +1 -1
- package/dist/shell/heartbeat-metadata.js +80 -3
- package/dist/shell/heartbeat-metadata.js.map +1 -1
- package/dist/shell/heartbeat.d.ts +13 -0
- package/dist/shell/heartbeat.d.ts.map +1 -1
- package/dist/shell/heartbeat.js +31 -10
- package/dist/shell/heartbeat.js.map +1 -1
- package/dist/shell/mcp-resolution.js +1 -1
- package/dist/shell/mcp-resolution.js.map +1 -1
- package/dist/shell/migration-held-set-publish.d.ts +170 -0
- package/dist/shell/migration-held-set-publish.d.ts.map +1 -0
- package/dist/shell/migration-held-set-publish.js +172 -0
- package/dist/shell/migration-held-set-publish.js.map +1 -0
- package/dist/shell/worker-pidfile.d.ts.map +1 -1
- package/dist/shell/worker-pidfile.js +1 -0
- package/dist/shell/worker-pidfile.js.map +1 -1
- package/dist/spawn/helpers.d.ts.map +1 -1
- package/dist/spawn/helpers.js +10 -1
- package/dist/spawn/helpers.js.map +1 -1
- package/dist/spawn/lead-continuation.d.ts +10 -2
- package/dist/spawn/lead-continuation.d.ts.map +1 -1
- package/dist/spawn/lead-continuation.js +39 -22
- package/dist/spawn/lead-continuation.js.map +1 -1
- package/dist/spawn/lead-launch.d.ts.map +1 -1
- package/dist/spawn/lead-launch.js +1 -0
- package/dist/spawn/lead-launch.js.map +1 -1
- package/dist/spawn/lead-process-ownership.d.ts.map +1 -1
- package/dist/spawn/lead-process-ownership.js +1 -0
- package/dist/spawn/lead-process-ownership.js.map +1 -1
- package/dist/spawn/one-shot-model.d.ts.map +1 -1
- package/dist/spawn/one-shot-model.js +1 -0
- package/dist/spawn/one-shot-model.js.map +1 -1
- package/dist/spawn/process-group-kill.d.ts.map +1 -1
- package/dist/spawn/process-group-kill.js +1 -0
- package/dist/spawn/process-group-kill.js.map +1 -1
- package/dist/spawn/process-spawn.d.ts +18 -1
- package/dist/spawn/process-spawn.d.ts.map +1 -1
- package/dist/spawn/process-spawn.js +11 -6
- package/dist/spawn/process-spawn.js.map +1 -1
- package/dist/spawn/prompt-assembly.d.ts +115 -18
- package/dist/spawn/prompt-assembly.d.ts.map +1 -1
- package/dist/spawn/prompt-assembly.js +121 -2
- package/dist/spawn/prompt-assembly.js.map +1 -1
- package/dist/spawn/spawn-and-acknowledge.d.ts +61 -0
- package/dist/spawn/spawn-and-acknowledge.d.ts.map +1 -0
- package/dist/spawn/spawn-and-acknowledge.js +117 -0
- package/dist/spawn/spawn-and-acknowledge.js.map +1 -0
- package/dist/spawn/spawn-cooldown.js +1 -1
- package/dist/spawn/spawn-decision.d.ts +10 -10
- package/dist/spawn/spawn-decision.d.ts.map +1 -1
- package/dist/spawn/spawn-decision.js +33 -5
- package/dist/spawn/spawn-decision.js.map +1 -1
- package/dist/spawn/worktree-session.d.ts.map +1 -1
- package/dist/spawn/worktree-session.js +11 -1
- package/dist/spawn/worktree-session.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 +24 -0
- package/dist/templates/claude-md.js.map +1 -1
- package/dist/testing/fixtures/conflicting-repo.d.ts +17 -0
- package/dist/testing/fixtures/conflicting-repo.d.ts.map +1 -1
- package/dist/testing/fixtures/conflicting-repo.js +31 -0
- package/dist/testing/fixtures/conflicting-repo.js.map +1 -1
- package/dist/testing/fixtures/index.d.ts.map +1 -1
- package/dist/testing/fixtures/index.js +1 -2
- package/dist/testing/fixtures/index.js.map +1 -1
- package/dist/testing/fixtures/migration-namespace-repo.d.ts +63 -0
- package/dist/testing/fixtures/migration-namespace-repo.d.ts.map +1 -0
- package/dist/testing/fixtures/migration-namespace-repo.js +164 -0
- package/dist/testing/fixtures/migration-namespace-repo.js.map +1 -0
- package/dist/testing/fixtures/stubborn-lead-process.d.ts.map +1 -1
- package/dist/testing/fixtures/stubborn-lead-process.js +1 -0
- package/dist/testing/fixtures/stubborn-lead-process.js.map +1 -1
- package/dist/types/focus.d.ts +59 -26
- package/dist/types/focus.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/verify/commit-verdict-pull.d.ts +28 -3
- package/dist/verify/commit-verdict-pull.d.ts.map +1 -1
- package/dist/verify/commit-verdict-pull.js +160 -23
- package/dist/verify/commit-verdict-pull.js.map +1 -1
- package/dist/verify/credit-rearm.d.ts.map +1 -1
- package/dist/verify/credit-rearm.js +72 -17
- package/dist/verify/credit-rearm.js.map +1 -1
- package/dist/verify/default-on-guards.d.ts +54 -8
- package/dist/verify/default-on-guards.d.ts.map +1 -1
- package/dist/verify/default-on-guards.js +132 -17
- package/dist/verify/default-on-guards.js.map +1 -1
- package/dist/verify/explicit-rearm.d.ts.map +1 -1
- package/dist/verify/explicit-rearm.js +1 -0
- package/dist/verify/explicit-rearm.js.map +1 -1
- package/dist/verify/explicit-row-selection.d.ts +47 -0
- package/dist/verify/explicit-row-selection.d.ts.map +1 -0
- package/dist/verify/explicit-row-selection.js +37 -0
- package/dist/verify/explicit-row-selection.js.map +1 -0
- package/dist/verify/gate-run-registry.d.ts.map +1 -1
- package/dist/verify/gate-run-registry.js +2 -0
- package/dist/verify/gate-run-registry.js.map +1 -1
- package/dist/verify/no-own-delta-verdict.d.ts +16 -2
- package/dist/verify/no-own-delta-verdict.d.ts.map +1 -1
- package/dist/verify/no-own-delta-verdict.js +18 -2
- package/dist/verify/no-own-delta-verdict.js.map +1 -1
- package/dist/verify/parked-shortfall-reuse.d.ts +194 -0
- package/dist/verify/parked-shortfall-reuse.d.ts.map +1 -0
- package/dist/verify/parked-shortfall-reuse.js +310 -0
- package/dist/verify/parked-shortfall-reuse.js.map +1 -0
- package/dist/verify/reselection-log.d.ts +22 -0
- package/dist/verify/reselection-log.d.ts.map +1 -0
- package/dist/verify/reselection-log.js +87 -0
- package/dist/verify/reselection-log.js.map +1 -0
- package/dist/verify/shortfall-park.d.ts +8 -1
- package/dist/verify/shortfall-park.d.ts.map +1 -1
- package/dist/verify/shortfall-park.js +17 -3
- package/dist/verify/shortfall-park.js.map +1 -1
- package/dist/verify/shortfall-repeat.d.ts.map +1 -1
- package/dist/verify/shortfall-repeat.js +7 -2
- package/dist/verify/shortfall-repeat.js.map +1 -1
- package/dist/verify/shortfall-rulings.d.ts +93 -6
- package/dist/verify/shortfall-rulings.d.ts.map +1 -1
- package/dist/verify/shortfall-rulings.js +69 -12
- package/dist/verify/shortfall-rulings.js.map +1 -1
- package/dist/verify/stall-detector-config.d.ts.map +1 -1
- package/dist/verify/stall-detector-config.js +2 -1
- package/dist/verify/stall-detector-config.js.map +1 -1
- package/dist/verify/stall-detectors.d.ts +6 -4
- package/dist/verify/stall-detectors.d.ts.map +1 -1
- package/dist/verify/stall-detectors.js +9 -6
- package/dist/verify/stall-detectors.js.map +1 -1
- package/dist/verify/stalled-team-backstop.d.ts +8 -2
- package/dist/verify/stalled-team-backstop.d.ts.map +1 -1
- package/dist/verify/stalled-team-backstop.js +15 -11
- package/dist/verify/stalled-team-backstop.js.map +1 -1
- package/dist/verify/team-stall-reapers.d.ts +28 -0
- package/dist/verify/team-stall-reapers.d.ts.map +1 -0
- package/dist/verify/team-stall-reapers.js +23 -0
- package/dist/verify/team-stall-reapers.js.map +1 -0
- package/dist/verify/verification-attribution-deps.d.ts +1 -1
- package/dist/verify/verification-attribution-deps.d.ts.map +1 -1
- package/dist/verify/verification-attribution-deps.js +20 -1
- package/dist/verify/verification-attribution-deps.js.map +1 -1
- package/dist/verify/verification-boundary-env.d.ts.map +1 -1
- package/dist/verify/verification-boundary-env.js +23 -9
- package/dist/verify/verification-boundary-env.js.map +1 -1
- package/dist/verify/verification-checkout.d.ts +1 -1
- package/dist/verify/verification-checkout.d.ts.map +1 -1
- package/dist/verify/verification-checkout.js.map +1 -1
- package/dist/verify/verification-commit-sharing.d.ts.map +1 -1
- package/dist/verify/verification-commit-sharing.js +14 -3
- package/dist/verify/verification-commit-sharing.js.map +1 -1
- package/dist/verify/verification-config.d.ts.map +1 -1
- package/dist/verify/verification-config.js +1 -20
- package/dist/verify/verification-config.js.map +1 -1
- package/dist/verify/verification-default-on.d.ts +4 -1
- package/dist/verify/verification-default-on.d.ts.map +1 -1
- package/dist/verify/verification-default-on.js +29 -2
- package/dist/verify/verification-default-on.js.map +1 -1
- package/dist/verify/verification-deps-default.d.ts.map +1 -1
- package/dist/verify/verification-deps-default.js +13 -0
- package/dist/verify/verification-deps-default.js.map +1 -1
- package/dist/verify/verification-deps.d.ts +38 -0
- package/dist/verify/verification-deps.d.ts.map +1 -1
- package/dist/verify/verification-deps.js +2 -1
- package/dist/verify/verification-deps.js.map +1 -1
- package/dist/verify/verification-engine.d.ts.map +1 -1
- package/dist/verify/verification-engine.js +44 -15
- package/dist/verify/verification-engine.js.map +1 -1
- package/dist/verify/verification-feedback.d.ts.map +1 -1
- package/dist/verify/verification-feedback.js +1 -19
- package/dist/verify/verification-feedback.js.map +1 -1
- package/dist/verify/verify-restatement.d.ts.map +1 -1
- package/dist/verify/verify-restatement.js +5 -1
- package/dist/verify/verify-restatement.js.map +1 -1
- package/dist/worktree/provision.d.ts.map +1 -1
- package/dist/worktree/provision.js +3 -1
- package/dist/worktree/provision.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/verify/stall-detectors-clock-wiring.test.ts,
|
|
3
|
+
// packages/daemon/src/verify/team-stall-reapers.test.ts
|
|
4
|
+
// PINNED-BY-END
|
|
5
|
+
import { getFocusWorktree } from '../focus/focus-worktree-state.js';
|
|
6
|
+
import { getActiveTeams, getTeamLastActivityAt } from '../focus/focus-team-state.js';
|
|
7
|
+
import { getFocusIssues } from '../queries/focuses.js';
|
|
8
|
+
import { readWorktreeHeadSha } from '../git/index.js';
|
|
9
|
+
import { takeDeliveryAdvancementSnapshot } from './delivery-advancement-guard.js';
|
|
10
|
+
import { readTeamActivityMarks, teamProgressMoved } from './team-progress-measure.js';
|
|
11
|
+
const observations = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* The measure's axes for a focus now, read from its registered worktree. HEAD
|
|
14
|
+
* and the diff are required when a worktree is registered: either unreadable
|
|
15
|
+
* makes the reading unreadable.
|
|
16
|
+
*/
|
|
17
|
+
export function readFocusProgress(focusId, deliveries, issues) {
|
|
18
|
+
const worktreePath = getFocusWorktree(focusId)?.worktreePath ?? null;
|
|
19
|
+
const head = worktreePath ? readWorktreeHeadSha(worktreePath) : null;
|
|
20
|
+
const activity = readTeamActivityMarks(focusId, worktreePath);
|
|
21
|
+
return {
|
|
22
|
+
axes: takeDeliveryAdvancementSnapshot(deliveries, issues, head, activity),
|
|
23
|
+
readable: worktreePath === null || (head !== null && activity.worktreeDiffFingerprint !== null),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Record a reading of the measure for a focus. A readable reading stamps
|
|
28
|
+
* `nowMs` as the last movement when it is the first, the first after an
|
|
29
|
+
* unreadable one (a fresh window), or when any axis moved since the last
|
|
30
|
+
* readable one. An unreadable reading changes no movement
|
|
31
|
+
* instant; it only marks the latest reading unreadable.
|
|
32
|
+
*/
|
|
33
|
+
export function observeTeamProgress(focusId, reading, nowMs) {
|
|
34
|
+
const prior = observations.get(focusId);
|
|
35
|
+
if (!reading.readable) {
|
|
36
|
+
if (prior)
|
|
37
|
+
prior.readable = false;
|
|
38
|
+
else
|
|
39
|
+
observations.set(focusId, { axes: reading.axes, movedAt: nowMs, readable: false });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// A reading after an unreadable one is a fresh baseline: the blind interval
|
|
43
|
+
// proved nothing, so it must not count toward a stall window (TEL-8).
|
|
44
|
+
const movedAt = !prior || !prior.readable || teamProgressMoved(prior.axes, reading.axes) ? nowMs : prior.movedAt;
|
|
45
|
+
observations.set(focusId, { axes: reading.axes, movedAt, readable: true });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* When the team last showed progress by the ONE measure, for the reapers.
|
|
49
|
+
* Null -- never stalled -- while the team has produced no event yet, before its
|
|
50
|
+
* first reading, or while its latest reading was unreadable.
|
|
51
|
+
*/
|
|
52
|
+
export function readTeamLastProgressAt(focusId) {
|
|
53
|
+
if (getTeamLastActivityAt(focusId) === null)
|
|
54
|
+
return null;
|
|
55
|
+
const observation = observations.get(focusId);
|
|
56
|
+
if (!observation || !observation.readable)
|
|
57
|
+
return null;
|
|
58
|
+
return observation.movedAt;
|
|
59
|
+
}
|
|
60
|
+
const defaultObserveDeps = {
|
|
61
|
+
isTeamLive: (focusId) => getActiveTeams().has(focusId),
|
|
62
|
+
getFocusIssues,
|
|
63
|
+
readProgress: readFocusProgress,
|
|
64
|
+
now: () => Date.now(),
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* The cascade pass's reading (the ONE writer): for a focus with a live team,
|
|
68
|
+
* read the measure's axes and record them; for a focus without one, forget its
|
|
69
|
+
* readings. An unreadable issue list is an unreadable reading (fail closed).
|
|
70
|
+
*/
|
|
71
|
+
export async function observeLiveTeamProgress(focusId, deliveries, deps = {}) {
|
|
72
|
+
const d = { ...defaultObserveDeps, ...deps };
|
|
73
|
+
if (!d.isTeamLive(focusId)) {
|
|
74
|
+
forgetTeamProgress(focusId);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let issues;
|
|
78
|
+
try {
|
|
79
|
+
issues = await d.getFocusIssues(focusId);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
const prior = observations.get(focusId);
|
|
83
|
+
observeTeamProgress(focusId, { axes: prior?.axes ?? { deliveryStatuses: {}, focusHeadSha: null }, readable: false }, d.now());
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
observeTeamProgress(focusId, d.readProgress(focusId, deliveries, issues), d.now());
|
|
87
|
+
}
|
|
88
|
+
/** Forget a focus's readings (its team is gone; the next team starts a new baseline). */
|
|
89
|
+
export function forgetTeamProgress(focusId) {
|
|
90
|
+
observations.delete(focusId);
|
|
91
|
+
}
|
|
92
|
+
/** Test-only: forget every focus. */
|
|
93
|
+
export function __resetTeamStillnessForTesting() {
|
|
94
|
+
observations.clear();
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=team-stillness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-stillness.js","sourceRoot":"","sources":["../../src/completion/team-stillness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Writable } from 'node:stream';
|
|
2
|
+
import type { CompletionEventPhaseState, CompletionEventPhaseOutcome } from './event.js';
|
|
3
|
+
/**
|
|
4
|
+
* What a delivery attempt can produce.
|
|
5
|
+
*
|
|
6
|
+
* `no_live_team` is separated from `write_failed` on purpose. Keeping a team
|
|
7
|
+
* alive so the next event can retry only makes sense when there IS a team: a
|
|
8
|
+
* focus whose lead is already gone emits no further event, so holding it would
|
|
9
|
+
* park the teardown for the full ten minutes of the hold and change nothing.
|
|
10
|
+
* The record is not lost in that case -- it stays unnamed, and the NEXT spawn
|
|
11
|
+
* of this focus carries it in the prompt. Two carriers, one record.
|
|
12
|
+
*/
|
|
13
|
+
export type NoticeDelivery = 'delivered' | 'write_failed' | 'no_live_team';
|
|
14
|
+
/** The seams: the record's reader and marker, and the write to the team. */
|
|
15
|
+
export interface UnclaimedNoticeDeps {
|
|
16
|
+
readRecord: (focusId: string) => Promise<string | null>;
|
|
17
|
+
markNamed: (focusId: string, namedAt: string) => Promise<void>;
|
|
18
|
+
deliver: (state: CompletionEventPhaseState, message: string) => NoticeDelivery;
|
|
19
|
+
now: () => string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* How long to wait before re-driving after a transient failure.
|
|
23
|
+
*
|
|
24
|
+
* A kept team is PARKED: a lead only emits a completion event in response to a
|
|
25
|
+
* wake, so a keep with no stimulus behind it waits for the hold bound to expire
|
|
26
|
+
* and then tears the team down having told it nothing -- the failure this phase
|
|
27
|
+
* exists to prevent, arriving by a slower route. The re-drive supplies the
|
|
28
|
+
* event. It is bounded from above by the hold itself
|
|
29
|
+
* (UNCLAIMED_MIGRATION_NOTICE_MAX_MS), so a persistently failing read retries
|
|
30
|
+
* about twenty times and then ends in teardown rather than forever.
|
|
31
|
+
*/
|
|
32
|
+
export declare const UNCLAIMED_NOTICE_RETRY_MS = 30000;
|
|
33
|
+
/**
|
|
34
|
+
* Production: the real record queries, and a write to the live team's stdin.
|
|
35
|
+
*
|
|
36
|
+
* The two QUERIES here are a convenience for a caller that drives this phase
|
|
37
|
+
* directly with explicit deps; they are NOT how production reaches them. The
|
|
38
|
+
* completion event wires `readUnclaimedMigrationRecord` /
|
|
39
|
+
* `markUnclaimedMigrationNamed` on its own deps (`defaultDeps` in event.ts),
|
|
40
|
+
* and the phase runs only when a reader is actually wired -- see the gate in
|
|
41
|
+
* `runUnclaimedMigrationNoticePhase`. Falling back to a live API call whenever
|
|
42
|
+
* the dep happened to be absent is what made every caller of
|
|
43
|
+
* `handleCompletionEvent` an unwitting caller of this one.
|
|
44
|
+
*
|
|
45
|
+
* `deliver` is different and stays here: it needs the phase STATE (the live
|
|
46
|
+
* team's stdin), which a `(focusId, message)` event dep cannot carry.
|
|
47
|
+
*/
|
|
48
|
+
export declare const defaultUnclaimedNoticeDeps: UnclaimedNoticeDeps;
|
|
49
|
+
/**
|
|
50
|
+
* Write the notice to a lead's stdin, and classify what that stream IS.
|
|
51
|
+
*
|
|
52
|
+
* A STREAM THAT HAS BEEN ENDED IS NOT A TRANSIENT FAILURE. The Codex backend
|
|
53
|
+
* declares `closeStdinAfterInput`, so `spawnTeamProcess` ends the lead's stdin
|
|
54
|
+
* the moment the kickoff message is written. From then on the stream is still
|
|
55
|
+
* an object and is NOT destroyed -- it is `writableEnded` -- so the old check
|
|
56
|
+
* (absent or destroyed) let it through, `sendMessage` returned false, and the
|
|
57
|
+
* phase read that as `write_failed`: keep the team, schedule a re-drive, try
|
|
58
|
+
* again. Every retry was a write-after-end on a stream that can never accept
|
|
59
|
+
* another byte, about twenty times over, until the hold bound expired into the
|
|
60
|
+
* teardown it had been holding back -- the team torn down having been told
|
|
61
|
+
* nothing, by the branch that exists to prevent exactly that.
|
|
62
|
+
*
|
|
63
|
+
* So an ended or non-writable stream answers `no_live_team`, which is the
|
|
64
|
+
* truthful answer: there is no carrier here, and no retry can make one. Nothing
|
|
65
|
+
* is marked, the record stays unnamed, and the next coding spawn carries it in
|
|
66
|
+
* its PROMPT -- which on Codex is the only carrier that ever existed, its
|
|
67
|
+
* kickoff message being the last thing that stream accepts.
|
|
68
|
+
*/
|
|
69
|
+
export declare function stdinDelivery(stdin: Writable | null | undefined, message: string): NoticeDelivery;
|
|
70
|
+
/**
|
|
71
|
+
* The message a live team receives: the stored record, and what resolves it.
|
|
72
|
+
*
|
|
73
|
+
* `false` is not a default here, it is a fact: the phase returns before this is
|
|
74
|
+
* reached on a review session (see the guard in
|
|
75
|
+
* `runUnclaimedMigrationNoticePhase`), so the only team this ever composes for
|
|
76
|
+
* is a coding team.
|
|
77
|
+
*/
|
|
78
|
+
export declare function buildUnclaimedNoticeMessage(record: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* Phase: deliver the unclaimed-migration notice.
|
|
81
|
+
*
|
|
82
|
+
* Continues (changing nothing) when there is no record, when the record has
|
|
83
|
+
* already been delivered, or when delivery failed. Halts 'kept' only when a
|
|
84
|
+
* notice was actually written to a live team.
|
|
85
|
+
*/
|
|
86
|
+
export declare function runUnclaimedMigrationNoticePhase(state: CompletionEventPhaseState,
|
|
87
|
+
/**
|
|
88
|
+
* Explicit seams, for a caller driving this phase on its own. Omitted by the
|
|
89
|
+
* registry, which supplies them through the completion event's deps instead.
|
|
90
|
+
*
|
|
91
|
+
* `= undefined` rather than `?:` so the function's ARITY stays 1: the registry
|
|
92
|
+
* calls every phase as `run(state)`, and its structure test pins that shape
|
|
93
|
+
* (an adapter whose signature has grown a second parameter the registry never
|
|
94
|
+
* passes is how a seam goes quietly inert).
|
|
95
|
+
*/
|
|
96
|
+
noticeDeps?: UnclaimedNoticeDeps | undefined): Promise<CompletionEventPhaseOutcome>;
|
|
97
|
+
//# sourceMappingURL=unclaimed-migration-notice-phase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unclaimed-migration-notice-phase.d.ts","sourceRoot":"","sources":["../../src/completion/unclaimed-migration-notice-phase.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAS5C,OAAO,KAAK,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAIzF;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;AAE3E,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,OAAO,EAAE,CAAC,KAAK,EAAE,yBAAyB,EAAE,OAAO,EAAE,MAAM,KAAK,cAAc,CAAC;IAC/E,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,EAAE,mBAQxC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAIjG;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,yBAAyB;AAChC;;;;;;;;GAQG;AACH,UAAU,GAAE,mBAAmB,GAAG,SAAqB,GACtD,OAAO,CAAC,2BAA2B,CAAC,CAwEtC"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/completion/unclaimed-migration-notice-phase.test.ts
|
|
3
|
+
// PINNED-BY-END
|
|
4
|
+
/**
|
|
5
|
+
* DELIVERING the unclaimed-migration notice to the team that can act on it,
|
|
6
|
+
* before anything tears that team down.
|
|
7
|
+
*
|
|
8
|
+
* WHAT WENT WRONG WITHOUT THIS PHASE. The record existed, the hold existed, and
|
|
9
|
+
* the team was still never told:
|
|
10
|
+
*
|
|
11
|
+
* - `scope-coverage-terminate` runs BEFORE the decide phase, so a focus whose
|
|
12
|
+
* deliveries are all verify/done/cancelled was terminated before anything
|
|
13
|
+
* read the flag. That is the common ending, not an edge case.
|
|
14
|
+
* - On the non-terminal path the flag produced a re-engagement, and the
|
|
15
|
+
* re-engagement message carries deliveries and issues -- not this. The team
|
|
16
|
+
* was woken and told nothing about the file.
|
|
17
|
+
* - The spawn path marked the record NAMED while gathering section inputs,
|
|
18
|
+
* before the session existed. A spawn that then failed lifted the hold with
|
|
19
|
+
* nobody having read anything.
|
|
20
|
+
*
|
|
21
|
+
* A notice nobody reads is not a notice. The file lands on integration holding
|
|
22
|
+
* a number no claim knows about, and the team that wrote it is gone.
|
|
23
|
+
*
|
|
24
|
+
* SO THE PHASE RUNS EARLY AND DELIVERS ITSELF. It sits ahead of EVERY
|
|
25
|
+
* teardown-capable phase -- not merely the first one found. Sitting between
|
|
26
|
+
* `review-window-routing` and `scope-coverage-terminate` was not that: a coding
|
|
27
|
+
* lead with verify work and an open review window commonly has no open coding
|
|
28
|
+
* issues, and review-window-routing terminated it one line above. It writes the
|
|
29
|
+
* notice into the LIVE team's stdin and marks the record named ONLY after the
|
|
30
|
+
* write succeeds. A failed write marks nothing and schedules the event that
|
|
31
|
+
* retries -- retryable unnamed state rather than a lost notice.
|
|
32
|
+
*
|
|
33
|
+
* IT KEEPS THE TEAM FOR THAT TURN, and exactly that turn. Halting 'kept' is
|
|
34
|
+
* what stops the teardown below it from running in the same event; the marker
|
|
35
|
+
* then lets the next event fall straight through. The record clears only on a
|
|
36
|
+
* claim or a removal, neither of which the daemon can perform, so a hold that
|
|
37
|
+
* waited for compliance would never lift on its own.
|
|
38
|
+
*
|
|
39
|
+
* @module completion/unclaimed-migration-notice-phase
|
|
40
|
+
*/
|
|
41
|
+
import { sendMessage } from '@telora/daemon-core';
|
|
42
|
+
import { scheduleDeferredReDrive } from './reengagement-redrive.js';
|
|
43
|
+
import { createLogger } from '../shell/log.js';
|
|
44
|
+
import { parseUnclaimedNamedAt, readUnclaimedMigrationRecordStrict, markUnclaimedMigrationNamed, } from '../queries/focus-unclaimed-migration.js';
|
|
45
|
+
import { buildUnclaimedMigrationSection } from '../prompt-sections/unclaimed-migration-section.js';
|
|
46
|
+
const log = createLogger({ module: 'unclaimed-migration-notice' });
|
|
47
|
+
/**
|
|
48
|
+
* How long to wait before re-driving after a transient failure.
|
|
49
|
+
*
|
|
50
|
+
* A kept team is PARKED: a lead only emits a completion event in response to a
|
|
51
|
+
* wake, so a keep with no stimulus behind it waits for the hold bound to expire
|
|
52
|
+
* and then tears the team down having told it nothing -- the failure this phase
|
|
53
|
+
* exists to prevent, arriving by a slower route. The re-drive supplies the
|
|
54
|
+
* event. It is bounded from above by the hold itself
|
|
55
|
+
* (UNCLAIMED_MIGRATION_NOTICE_MAX_MS), so a persistently failing read retries
|
|
56
|
+
* about twenty times and then ends in teardown rather than forever.
|
|
57
|
+
*/
|
|
58
|
+
export const UNCLAIMED_NOTICE_RETRY_MS = 30_000;
|
|
59
|
+
/**
|
|
60
|
+
* Production: the real record queries, and a write to the live team's stdin.
|
|
61
|
+
*
|
|
62
|
+
* The two QUERIES here are a convenience for a caller that drives this phase
|
|
63
|
+
* directly with explicit deps; they are NOT how production reaches them. The
|
|
64
|
+
* completion event wires `readUnclaimedMigrationRecord` /
|
|
65
|
+
* `markUnclaimedMigrationNamed` on its own deps (`defaultDeps` in event.ts),
|
|
66
|
+
* and the phase runs only when a reader is actually wired -- see the gate in
|
|
67
|
+
* `runUnclaimedMigrationNoticePhase`. Falling back to a live API call whenever
|
|
68
|
+
* the dep happened to be absent is what made every caller of
|
|
69
|
+
* `handleCompletionEvent` an unwitting caller of this one.
|
|
70
|
+
*
|
|
71
|
+
* `deliver` is different and stays here: it needs the phase STATE (the live
|
|
72
|
+
* team's stdin), which a `(focusId, message)` event dep cannot carry.
|
|
73
|
+
*/
|
|
74
|
+
export const defaultUnclaimedNoticeDeps = {
|
|
75
|
+
// The STRICT read: the lenient one swallows its own failure and returns
|
|
76
|
+
// null, which this phase would read as "nothing to tell" -- defeating the
|
|
77
|
+
// fail-closed handler below before it could ever run.
|
|
78
|
+
readRecord: (focusId) => readUnclaimedMigrationRecordStrict(focusId),
|
|
79
|
+
markNamed: (focusId, namedAt) => markUnclaimedMigrationNamed(focusId, namedAt),
|
|
80
|
+
deliver: (state, message) => stdinDelivery(state.ctx.proc?.stdin ?? null, message),
|
|
81
|
+
now: () => new Date().toISOString(),
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Write the notice to a lead's stdin, and classify what that stream IS.
|
|
85
|
+
*
|
|
86
|
+
* A STREAM THAT HAS BEEN ENDED IS NOT A TRANSIENT FAILURE. The Codex backend
|
|
87
|
+
* declares `closeStdinAfterInput`, so `spawnTeamProcess` ends the lead's stdin
|
|
88
|
+
* the moment the kickoff message is written. From then on the stream is still
|
|
89
|
+
* an object and is NOT destroyed -- it is `writableEnded` -- so the old check
|
|
90
|
+
* (absent or destroyed) let it through, `sendMessage` returned false, and the
|
|
91
|
+
* phase read that as `write_failed`: keep the team, schedule a re-drive, try
|
|
92
|
+
* again. Every retry was a write-after-end on a stream that can never accept
|
|
93
|
+
* another byte, about twenty times over, until the hold bound expired into the
|
|
94
|
+
* teardown it had been holding back -- the team torn down having been told
|
|
95
|
+
* nothing, by the branch that exists to prevent exactly that.
|
|
96
|
+
*
|
|
97
|
+
* So an ended or non-writable stream answers `no_live_team`, which is the
|
|
98
|
+
* truthful answer: there is no carrier here, and no retry can make one. Nothing
|
|
99
|
+
* is marked, the record stays unnamed, and the next coding spawn carries it in
|
|
100
|
+
* its PROMPT -- which on Codex is the only carrier that ever existed, its
|
|
101
|
+
* kickoff message being the last thing that stream accepts.
|
|
102
|
+
*/
|
|
103
|
+
export function stdinDelivery(stdin, message) {
|
|
104
|
+
if (!stdin)
|
|
105
|
+
return 'no_live_team';
|
|
106
|
+
if (stdin.destroyed || stdin.writableEnded || !stdin.writable)
|
|
107
|
+
return 'no_live_team';
|
|
108
|
+
return sendMessage(stdin, message) ? 'delivered' : 'write_failed';
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The message a live team receives: the stored record, and what resolves it.
|
|
112
|
+
*
|
|
113
|
+
* `false` is not a default here, it is a fact: the phase returns before this is
|
|
114
|
+
* reached on a review session (see the guard in
|
|
115
|
+
* `runUnclaimedMigrationNoticePhase`), so the only team this ever composes for
|
|
116
|
+
* is a coding team.
|
|
117
|
+
*/
|
|
118
|
+
export function buildUnclaimedNoticeMessage(record) {
|
|
119
|
+
return buildUnclaimedMigrationSection(record, false).join('\n');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Phase: deliver the unclaimed-migration notice.
|
|
123
|
+
*
|
|
124
|
+
* Continues (changing nothing) when there is no record, when the record has
|
|
125
|
+
* already been delivered, or when delivery failed. Halts 'kept' only when a
|
|
126
|
+
* notice was actually written to a live team.
|
|
127
|
+
*/
|
|
128
|
+
export async function runUnclaimedMigrationNoticePhase(state,
|
|
129
|
+
/**
|
|
130
|
+
* Explicit seams, for a caller driving this phase on its own. Omitted by the
|
|
131
|
+
* registry, which supplies them through the completion event's deps instead.
|
|
132
|
+
*
|
|
133
|
+
* `= undefined` rather than `?:` so the function's ARITY stays 1: the registry
|
|
134
|
+
* calls every phase as `run(state)`, and its structure test pins that shape
|
|
135
|
+
* (an adapter whose signature has grown a second parameter the registry never
|
|
136
|
+
* passes is how a seam goes quietly inert).
|
|
137
|
+
*/
|
|
138
|
+
noticeDeps = undefined) {
|
|
139
|
+
const { focusId, focusName } = state.ctx;
|
|
140
|
+
// A REVIEW PASS IS NOT THE PARTY THAT CAN ACT, so it is not told and the
|
|
141
|
+
// obligation is RETAINED.
|
|
142
|
+
//
|
|
143
|
+
// The file was written by a coding team, and the two things that resolve it
|
|
144
|
+
// -- claiming the number, or deleting the file -- are that team's to do. A
|
|
145
|
+
// reviewer can do neither. Delivering here would nonetheless CONSUME the
|
|
146
|
+
// record: the write succeeds against the review lead's stdin, the marker is
|
|
147
|
+
// written, and the next coding team -- the one party that could have fixed it
|
|
148
|
+
// -- reads a record already marked named and is told nothing. One notice,
|
|
149
|
+
// spent on the only session that cannot use it.
|
|
150
|
+
//
|
|
151
|
+
// Returning 'continue' rather than keeping: a review pass has its own routing
|
|
152
|
+
// and its own ending, and neither is this phase's business to hold.
|
|
153
|
+
if (state.ctx.teamState.sessionType === 'review') {
|
|
154
|
+
log.info(`[unclaimed-migration] "${focusName}": review pass -- the record is retained, unnamed, `
|
|
155
|
+
+ 'for the coding team that can claim or remove the file');
|
|
156
|
+
return 'continue';
|
|
157
|
+
}
|
|
158
|
+
// The registry calls this as run(state), so the seams a test needs are taken
|
|
159
|
+
// from the event deps when present -- that is what lets the phase be driven
|
|
160
|
+
// through the REAL registry, which is the only place the ordering (notice
|
|
161
|
+
// before teardown) is observable.
|
|
162
|
+
const deps = resolveNoticeDeps(state, noticeDeps);
|
|
163
|
+
if (deps === null)
|
|
164
|
+
return 'continue';
|
|
165
|
+
let record;
|
|
166
|
+
try {
|
|
167
|
+
record = await deps.readRecord(focusId);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
// FAIL CLOSED on the read. An unreadable artifact is not evidence that
|
|
171
|
+
// there is nothing to tell, and the destructive reading of it -- "no
|
|
172
|
+
// record, carry on" -- is the one that ends with the file on integration.
|
|
173
|
+
// Keeping the team costs one turn and the next event asks again.
|
|
174
|
+
log.warn(`[unclaimed-migration] "${focusName}": record read failed `
|
|
175
|
+
+ `(${String(err?.message ?? err)}) -- keeping the team rather than `
|
|
176
|
+
+ 'reading a failed read as "nothing to tell"');
|
|
177
|
+
// The keep needs a stimulus behind it, or it is a park: schedule the event
|
|
178
|
+
// that will try the read again.
|
|
179
|
+
scheduleDeferredReDrive(state.ctx, state.deps, UNCLAIMED_NOTICE_RETRY_MS);
|
|
180
|
+
return { halt: 'kept' };
|
|
181
|
+
}
|
|
182
|
+
if (record === null || record.trim() === '')
|
|
183
|
+
return 'continue';
|
|
184
|
+
if (parseUnclaimedNamedAt(record) !== null)
|
|
185
|
+
return 'continue'; // already told
|
|
186
|
+
const delivery = deps.deliver(state, buildUnclaimedNoticeMessage(record));
|
|
187
|
+
if (delivery !== 'delivered')
|
|
188
|
+
return handleUndelivered(state, delivery);
|
|
189
|
+
// Marked ONLY after a successful write. Before it, a failed delivery would
|
|
190
|
+
// lift the hold with nobody having read anything -- which is the defect.
|
|
191
|
+
try {
|
|
192
|
+
await deps.markNamed(focusId, deps.now());
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
// The team HAS the notice; only the marker failed to persist. That is the
|
|
196
|
+
// safe direction -- the next event re-delivers rather than skipping -- and
|
|
197
|
+
// it must not propagate: an exception here aborts the whole completion
|
|
198
|
+
// event, which is a far larger failure than telling a team twice.
|
|
199
|
+
log.warn(`[unclaimed-migration] "${focusName}": notice delivered but the marker did not `
|
|
200
|
+
+ `persist (${String(err?.message ?? err)}) -- it will be delivered again`);
|
|
201
|
+
}
|
|
202
|
+
log.info(`[unclaimed-migration] "${focusName}": notice delivered to the team`);
|
|
203
|
+
return { halt: 'kept' };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* What a delivery that did not land means for this event.
|
|
207
|
+
*
|
|
208
|
+
* The two outcomes are opposites and the difference is whether a retry could
|
|
209
|
+
* ever work: a stream that FAILED a write may accept the next one, and a stream
|
|
210
|
+
* that is gone or ended never will.
|
|
211
|
+
*/
|
|
212
|
+
function handleUndelivered(state, delivery) {
|
|
213
|
+
const { focusName } = state.ctx;
|
|
214
|
+
if (delivery === 'no_live_team') {
|
|
215
|
+
// Nobody to write to, and nothing a keep could achieve: a lead that is
|
|
216
|
+
// gone emits no further event, so the hold would simply expire. The record
|
|
217
|
+
// stays unnamed and the next SPAWN of this focus carries it in the prompt.
|
|
218
|
+
log.info(`[unclaimed-migration] "${focusName}": no live team to write to -- the record stays `
|
|
219
|
+
+ 'unnamed and the next spawn carries it');
|
|
220
|
+
return 'continue';
|
|
221
|
+
}
|
|
222
|
+
// Nothing written, so nothing is marked: the record stays unnamed and the
|
|
223
|
+
// scheduled re-drive tries again. Not halting here would let the teardown
|
|
224
|
+
// below run on a focus nobody has been told about, so this holds too.
|
|
225
|
+
log.warn(`[unclaimed-migration] "${focusName}": could not write the notice to the team -- `
|
|
226
|
+
+ 'record left unnamed, retrying');
|
|
227
|
+
scheduleDeferredReDrive(state.ctx, state.deps, UNCLAIMED_NOTICE_RETRY_MS);
|
|
228
|
+
return { halt: 'kept' };
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The seams this run should use, or null when nobody wired a record reader.
|
|
232
|
+
*
|
|
233
|
+
* Precedence: an explicitly-passed seam wins (the caller is saying exactly what
|
|
234
|
+
* this run should do), then the completion event's deps, then the module
|
|
235
|
+
* defaults.
|
|
236
|
+
*/
|
|
237
|
+
function resolveNoticeDeps(state, noticeDeps) {
|
|
238
|
+
const eventDeps = state.deps ?? {};
|
|
239
|
+
// NO READER WIRED, NOTHING TO READ.
|
|
240
|
+
//
|
|
241
|
+
// This phase used to fall back to the real API query whenever its dep was
|
|
242
|
+
// absent. That made it run -- and, on an uninitialised client, take its
|
|
243
|
+
// fail-closed keep -- for every caller of `handleCompletionEvent`, twenty-odd
|
|
244
|
+
// suites of which construct a deps object to drive one unrelated decision and
|
|
245
|
+
// have no record to read at all. A phase that reaches for a live backend the
|
|
246
|
+
// caller never handed it is not fail-closed, it is uninvited.
|
|
247
|
+
//
|
|
248
|
+
// Production wires the reader on `defaultDeps` (event.ts), pinned there, so
|
|
249
|
+
// an absent reader HERE means the caller does not model the record.
|
|
250
|
+
if (!noticeDeps?.readRecord && !eventDeps.readUnclaimedMigrationRecord)
|
|
251
|
+
return null;
|
|
252
|
+
return {
|
|
253
|
+
...defaultUnclaimedNoticeDeps,
|
|
254
|
+
...(eventDeps.readUnclaimedMigrationRecord
|
|
255
|
+
? { readRecord: eventDeps.readUnclaimedMigrationRecord }
|
|
256
|
+
: {}),
|
|
257
|
+
...(eventDeps.markUnclaimedMigrationNamed
|
|
258
|
+
? { markNamed: eventDeps.markUnclaimedMigrationNamed }
|
|
259
|
+
: {}),
|
|
260
|
+
...(eventDeps.deliverUnclaimedMigrationNotice
|
|
261
|
+
? {
|
|
262
|
+
deliver: (s, message) => eventDeps.deliverUnclaimedMigrationNotice(s.ctx.focusId, message),
|
|
263
|
+
}
|
|
264
|
+
: {}),
|
|
265
|
+
// An explicitly-passed seam wins over both: it is the caller saying exactly
|
|
266
|
+
// what this run should do.
|
|
267
|
+
...noticeDeps,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=unclaimed-migration-notice-phase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unclaimed-migration-notice-phase.js","sourceRoot":"","sources":["../../src/completion/unclaimed-migration-notice-phase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A lead waiting on its workers is left to wait.
|
|
3
|
+
*
|
|
4
|
+
* On 2026-09-24 ("A ruling reaches the gate it rules on") a lead handed its
|
|
5
|
+
* edits to background workers and ended its turn while they ran. The daemon
|
|
6
|
+
* re-woke it with a mid-focus handoff every ~20s; each wake returned in seconds
|
|
7
|
+
* and was counted as an empty completion cycle, until the team was killed as a
|
|
8
|
+
* team_failure with its workers still editing. The daemon's own pokes were the
|
|
9
|
+
* cycles.
|
|
10
|
+
*
|
|
11
|
+
* So while the team's workers are live (completion/team-progress-measure.ts
|
|
12
|
+
* teamWorkersLive: a started worker that has not ended and is still reporting),
|
|
13
|
+
* the daemon sends the lead no handoff, no re-engagement and no continuation
|
|
14
|
+
* turn. The lead is next woken by:
|
|
15
|
+
* - its workers' completion -- the engine itself resumes the lead on a
|
|
16
|
+
* worker's task notification, and that turn's result is an ordinary cycle;
|
|
17
|
+
* - genuinely new work: a delivery the team has not been shown, or an issue
|
|
18
|
+
* that appeared since the team was last handed its work;
|
|
19
|
+
* - the normal handoff path once the workers go quiet (WORKER_QUIET_MS with no
|
|
20
|
+
* event) -- a re-check is scheduled for exactly then.
|
|
21
|
+
* A lead whose workers have all finished is re-engaged as before, and a team
|
|
22
|
+
* with no events at all is still reaped by the stalled-team backstop.
|
|
23
|
+
*
|
|
24
|
+
* The wait is logged ONCE per park episode (teamState.waitingOnWorkersSince).
|
|
25
|
+
*
|
|
26
|
+
* @module completion/worker-wait
|
|
27
|
+
*/
|
|
28
|
+
import type { FocusDeliveryInfo, FocusIssueInfo, FocusTeamState } from '../types/index.js';
|
|
29
|
+
type WaitState = Pick<FocusTeamState, 'waitingOnWorkersSince' | 'shownIssueIds'>;
|
|
30
|
+
/**
|
|
31
|
+
* Record the issues the lead has now been handed (at every wake actually sent),
|
|
32
|
+
* so an issue that appears later is recognisably new.
|
|
33
|
+
*/
|
|
34
|
+
export declare function recordIssuesShown(teamState: WaitState, issues: Pick<FocusIssueInfo, 'id'>[]): void;
|
|
35
|
+
/** True when an issue exists that the lead has not been handed (none, before any record). */
|
|
36
|
+
export declare function hasUnshownIssue(teamState: WaitState, issues: Pick<FocusIssueInfo, 'id'>[]): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Genuinely new work for a lead waiting on its workers: an agent-actionable
|
|
39
|
+
* delivery the team has never been told about, or an issue on a delivery the
|
|
40
|
+
* running arm owes that the lead has not been handed. Work RECORDED as new
|
|
41
|
+
* intent under the arm is invisible to the team and wakes nothing.
|
|
42
|
+
*/
|
|
43
|
+
export declare function hasUnshownWork(teamState: FocusTeamState, deliveries: FocusDeliveryInfo[], issues: Pick<FocusIssueInfo, 'id' | 'deliveryId'>[]): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* While the lead waits on live workers, what the waiting re-check does next:
|
|
46
|
+
* a number is "still waiting -- check again in that many ms" (no completion
|
|
47
|
+
* cycle, no wake); null is "re-drive the completion decision now", because the
|
|
48
|
+
* workers are done or quiet, or because work the lead has not been shown has
|
|
49
|
+
* ARRIVED -- that arrival is itself the trigger, not the next unrelated event.
|
|
50
|
+
*/
|
|
51
|
+
export declare function nextWorkerWaitCheck(args: {
|
|
52
|
+
teamState: FocusTeamState;
|
|
53
|
+
focusId: string;
|
|
54
|
+
quietInMs: number | null;
|
|
55
|
+
readWork: () => Promise<{
|
|
56
|
+
deliveries: FocusDeliveryInfo[];
|
|
57
|
+
issues: FocusIssueInfo[];
|
|
58
|
+
}>;
|
|
59
|
+
}): Promise<number | null>;
|
|
60
|
+
/**
|
|
61
|
+
* How often a waiting lead's focus is re-read for newly arrived work -- the
|
|
62
|
+
* daemon's own poll cadence, so new work reaches a waiting lead no later than
|
|
63
|
+
* it would reach an idle one.
|
|
64
|
+
*/
|
|
65
|
+
export declare const WORKER_WAIT_RECHECK_MS = 30000;
|
|
66
|
+
/**
|
|
67
|
+
* Decide whether to HOLD a wake to the lead because its workers are live.
|
|
68
|
+
* Returns true to hold (send nothing). Logs once per park episode, and ends the
|
|
69
|
+
* episode (so the next one logs again) whenever a wake is let through.
|
|
70
|
+
*/
|
|
71
|
+
export declare function holdWakeForLiveWorkers(args: {
|
|
72
|
+
teamState: WaitState;
|
|
73
|
+
focusId: string;
|
|
74
|
+
focusName: string;
|
|
75
|
+
nowMs: number;
|
|
76
|
+
workersLive: boolean;
|
|
77
|
+
/** Genuinely new work the lead has not been shown (a delivery or an issue). */
|
|
78
|
+
hasUnshownWork: boolean;
|
|
79
|
+
issues: Pick<FocusIssueInfo, 'id'>[];
|
|
80
|
+
/** What the held wake would have been, for the log line. */
|
|
81
|
+
wakeKind: string;
|
|
82
|
+
}): boolean;
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=worker-wait.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-wait.d.ts","sourceRoot":"","sources":["../../src/completion/worker-wait.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQ3F,KAAK,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,uBAAuB,GAAG,eAAe,CAAC,CAAC;AAEjF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,GAAG,IAAI,CAElG;AAED,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,GAAG,OAAO,CAGnG;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,cAAc,EACzB,UAAU,EAAE,iBAAiB,EAAE,EAC/B,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,GAAG,YAAY,CAAC,EAAE,GAClD,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,SAAS,EAAE,cAAc,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC;QAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC;QAAC,MAAM,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC,CAAC;CACxF,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWzB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,+EAA+E;IAC/E,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC;IACrC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAuBV"}
|