@telora/daemon 0.15.1 → 0.15.3
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/README.md +11 -11
- package/build-info.json +2 -2
- package/dist/assembly-engine.d.ts +1 -1
- package/dist/assembly-engine.d.ts.map +1 -1
- package/dist/assembly-resolvers.js +41 -41
- package/dist/assembly-resolvers.js.map +1 -1
- package/dist/branch-status.d.ts +4 -4
- package/dist/branch-status.d.ts.map +1 -1
- package/dist/branch-status.js +23 -23
- package/dist/branch-status.js.map +1 -1
- package/dist/cli/connect.js +1 -1
- package/dist/cli/connect.js.map +1 -1
- package/dist/completion-detector.d.ts +1 -1
- package/dist/completion-detector.js +1 -1
- package/dist/completion-handler.d.ts +1 -1
- package/dist/completion-handler.js +4 -4
- package/dist/completion-handler.js.map +1 -1
- package/dist/condition-evaluators.js +4 -4
- package/dist/condition-evaluators.js.map +1 -1
- package/dist/control-state.d.ts +6 -6
- package/dist/control-state.d.ts.map +1 -1
- package/dist/control-state.js +43 -43
- package/dist/control-state.js.map +1 -1
- package/dist/crash-recovery-scan.d.ts +1 -1
- package/dist/crash-recovery-scan.js +20 -20
- package/dist/crash-recovery-scan.js.map +1 -1
- package/dist/crash-recovery-types.d.ts +3 -3
- package/dist/crash-recovery-types.d.ts.map +1 -1
- package/dist/crash-recovery-types.js +2 -2
- package/dist/crash-recovery-types.js.map +1 -1
- package/dist/crash-recovery.d.ts +3 -3
- package/dist/crash-recovery.d.ts.map +1 -1
- package/dist/crash-recovery.js +21 -21
- package/dist/crash-recovery.js.map +1 -1
- package/dist/daemon-process.d.ts +1 -1
- package/dist/daemon-process.d.ts.map +1 -1
- package/dist/dag-validator.d.ts +6 -6
- package/dist/dag-validator.d.ts.map +1 -1
- package/dist/dag-validator.js +2 -2
- package/dist/dag-validator.js.map +1 -1
- package/dist/delivery-guards.d.ts +1 -1
- package/dist/delivery-guards.js +1 -1
- package/dist/delivery-lifecycle.d.ts +5 -5
- package/dist/delivery-lifecycle.d.ts.map +1 -1
- package/dist/delivery-lifecycle.js +12 -12
- package/dist/delivery-lifecycle.js.map +1 -1
- package/dist/delivery-merge.js +1 -1
- package/dist/delivery-merge.js.map +1 -1
- package/dist/dependency-resolver.d.ts +7 -7
- package/dist/dependency-resolver.d.ts.map +1 -1
- package/dist/dependency-resolver.js.map +1 -1
- package/dist/directive-executor.d.ts +15 -15
- package/dist/directive-executor.d.ts.map +1 -1
- package/dist/directive-executor.js +76 -76
- package/dist/directive-executor.js.map +1 -1
- package/dist/evaluation-context.d.ts +2 -2
- package/dist/evaluation-context.d.ts.map +1 -1
- package/dist/evaluation-context.js +4 -4
- package/dist/evaluation-context.js.map +1 -1
- package/dist/focus-completion-event.d.ts +97 -0
- package/dist/focus-completion-event.d.ts.map +1 -0
- package/dist/focus-completion-event.js +257 -0
- package/dist/focus-completion-event.js.map +1 -0
- package/dist/focus-completion.d.ts +85 -0
- package/dist/focus-completion.d.ts.map +1 -0
- package/dist/focus-completion.js +459 -0
- package/dist/focus-completion.js.map +1 -0
- package/dist/focus-engine.d.ts +47 -0
- package/dist/focus-engine.d.ts.map +1 -0
- package/dist/focus-engine.js +421 -0
- package/dist/focus-engine.js.map +1 -0
- package/dist/focus-executor.d.ts +55 -0
- package/dist/focus-executor.d.ts.map +1 -0
- package/dist/focus-executor.js +549 -0
- package/dist/focus-executor.js.map +1 -0
- package/dist/focus-lifecycle.d.ts +61 -0
- package/dist/focus-lifecycle.d.ts.map +1 -0
- package/dist/focus-lifecycle.js +544 -0
- package/dist/focus-lifecycle.js.map +1 -0
- package/dist/focus-merge.d.ts +77 -0
- package/dist/focus-merge.d.ts.map +1 -0
- package/dist/focus-merge.js +378 -0
- package/dist/focus-merge.js.map +1 -0
- package/dist/focus-prompt-builder.d.ts +35 -0
- package/dist/focus-prompt-builder.d.ts.map +1 -0
- package/dist/focus-prompt-builder.js +138 -0
- package/dist/focus-prompt-builder.js.map +1 -0
- package/dist/focus-provisioning.d.ts +16 -0
- package/dist/focus-provisioning.d.ts.map +1 -0
- package/dist/focus-provisioning.js +119 -0
- package/dist/focus-provisioning.js.map +1 -0
- package/dist/focus-spawn-helpers.d.ts +67 -0
- package/dist/focus-spawn-helpers.d.ts.map +1 -0
- package/dist/focus-spawn-helpers.js +160 -0
- package/dist/focus-spawn-helpers.js.map +1 -0
- package/dist/focus-team-lifecycle.d.ts +50 -0
- package/dist/focus-team-lifecycle.d.ts.map +1 -0
- package/dist/focus-team-lifecycle.js +256 -0
- package/dist/focus-team-lifecycle.js.map +1 -0
- package/dist/focus-team-state.d.ts +24 -0
- package/dist/focus-team-state.d.ts.map +1 -0
- package/dist/focus-team-state.js +43 -0
- package/dist/focus-team-state.js.map +1 -0
- package/dist/focus-worktree-state.d.ts +47 -0
- package/dist/focus-worktree-state.d.ts.map +1 -0
- package/dist/focus-worktree-state.js +104 -0
- package/dist/focus-worktree-state.js.map +1 -0
- package/dist/git-merge.d.ts +5 -5
- package/dist/git-merge.d.ts.map +1 -1
- package/dist/git-merge.js +5 -5
- package/dist/git-merge.js.map +1 -1
- package/dist/git-state-detector.d.ts +1 -1
- package/dist/git-state-detector.js +9 -9
- package/dist/git-state-detector.js.map +1 -1
- package/dist/git-utils.d.ts +1 -1
- package/dist/git-utils.js +1 -1
- package/dist/git.d.ts +2 -2
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +3 -3
- package/dist/git.js.map +1 -1
- package/dist/heartbeat.d.ts +4 -4
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +7 -7
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/listener-auto-advance.d.ts +2 -2
- package/dist/listener-auto-advance.js +21 -21
- package/dist/listener-auto-advance.js.map +1 -1
- package/dist/listener.d.ts +12 -12
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +80 -75
- package/dist/listener.js.map +1 -1
- package/dist/loop-engine.d.ts +20 -20
- package/dist/loop-engine.d.ts.map +1 -1
- package/dist/loop-engine.js +82 -82
- package/dist/loop-engine.js.map +1 -1
- package/dist/loop-event-bus.d.ts +5 -5
- package/dist/loop-event-bus.d.ts.map +1 -1
- package/dist/loop-event-bus.js +3 -3
- package/dist/loop-llm-client.d.ts +1 -1
- package/dist/loop-llm-client.js +1 -1
- package/dist/loop-variance.d.ts +1 -1
- package/dist/loop-variance.js +1 -1
- package/dist/merge-detector.d.ts +6 -6
- package/dist/merge-detector.d.ts.map +1 -1
- package/dist/merge-detector.js +47 -47
- package/dist/merge-detector.js.map +1 -1
- package/dist/otlp-log-parser.js +2 -2
- package/dist/otlp-log-parser.js.map +1 -1
- package/dist/otlp-metric-parser.js +1 -1
- package/dist/otlp-metric-parser.js.map +1 -1
- package/dist/otlp-receiver.d.ts +1 -1
- package/dist/otlp-receiver.js +7 -7
- package/dist/otlp-receiver.js.map +1 -1
- package/dist/otlp-types.d.ts +1 -1
- package/dist/otlp-types.d.ts.map +1 -1
- package/dist/otlp-types.js +3 -3
- package/dist/otlp-types.js.map +1 -1
- package/dist/output-monitor.d.ts +6 -6
- package/dist/output-monitor.d.ts.map +1 -1
- package/dist/output-monitor.js +11 -11
- package/dist/output-monitor.js.map +1 -1
- package/dist/planning-prompt-builder.d.ts +17 -15
- package/dist/planning-prompt-builder.d.ts.map +1 -1
- package/dist/planning-prompt-builder.js +34 -32
- package/dist/planning-prompt-builder.js.map +1 -1
- package/dist/pm/mitigation-correlator.d.ts +7 -7
- package/dist/pm/mitigation-correlator.d.ts.map +1 -1
- package/dist/pm/mitigation-correlator.js +33 -33
- package/dist/pm/mitigation-correlator.js.map +1 -1
- package/dist/pm-engine.js +1 -1
- package/dist/pm-engine.js.map +1 -1
- package/dist/prompt-builder.d.ts +1 -1
- package/dist/prompt-builder.js +9 -9
- package/dist/prompt-builder.js.map +1 -1
- package/dist/prompts/starter-prompt.d.ts +2 -2
- package/dist/prompts/starter-prompt.d.ts.map +1 -1
- package/dist/prompts/starter-prompt.js +6 -6
- package/dist/qa-crash-recovery.d.ts +10 -10
- package/dist/qa-crash-recovery.d.ts.map +1 -1
- package/dist/qa-crash-recovery.js +32 -32
- package/dist/qa-crash-recovery.js.map +1 -1
- package/dist/qa-dev-server.d.ts +3 -3
- package/dist/qa-dev-server.d.ts.map +1 -1
- package/dist/qa-dev-server.js +3 -3
- package/dist/qa-dev-server.js.map +1 -1
- package/dist/qa-orchestrator.d.ts +18 -18
- package/dist/qa-orchestrator.d.ts.map +1 -1
- package/dist/qa-orchestrator.js +47 -47
- package/dist/qa-orchestrator.js.map +1 -1
- package/dist/qa-provisioner.d.ts +3 -3
- package/dist/qa-provisioner.d.ts.map +1 -1
- package/dist/qa-provisioner.js +14 -14
- package/dist/qa-provisioner.js.map +1 -1
- package/dist/qa-state.d.ts +10 -10
- package/dist/qa-state.d.ts.map +1 -1
- package/dist/qa-state.js +11 -11
- package/dist/qa-state.js.map +1 -1
- package/dist/queries/control-state.d.ts +5 -5
- package/dist/queries/control-state.d.ts.map +1 -1
- package/dist/queries/control-state.js +4 -4
- package/dist/queries/control-state.js.map +1 -1
- package/dist/queries/deliveries.d.ts +28 -24
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +32 -28
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/focuses.d.ts +97 -0
- package/dist/queries/focuses.d.ts.map +1 -0
- package/dist/queries/focuses.js +136 -0
- package/dist/queries/focuses.js.map +1 -0
- package/dist/queries/index.d.ts +3 -3
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +2 -2
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/qa.d.ts +16 -16
- package/dist/queries/qa.d.ts.map +1 -1
- package/dist/queries/qa.js +22 -22
- package/dist/queries/qa.js.map +1 -1
- package/dist/queries/schemas.d.ts +40 -34
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +31 -26
- package/dist/queries/schemas.js.map +1 -1
- package/dist/queries/sessions.d.ts +1 -1
- package/dist/queries/sessions.d.ts.map +1 -1
- package/dist/queries/sessions.js +2 -2
- package/dist/queries/sessions.js.map +1 -1
- package/dist/queries/shared.js +10 -10
- package/dist/queries/shared.js.map +1 -1
- package/dist/queries/workflows.d.ts +1 -1
- package/dist/queries/workflows.js +1 -1
- package/dist/queries/worktrees.d.ts +7 -7
- package/dist/queries/worktrees.d.ts.map +1 -1
- package/dist/queries/worktrees.js +7 -7
- package/dist/queries/worktrees.js.map +1 -1
- package/dist/review-defect-detector.d.ts +125 -0
- package/dist/review-defect-detector.d.ts.map +1 -0
- package/dist/review-defect-detector.js +289 -0
- package/dist/review-defect-detector.js.map +1 -0
- package/dist/session-lifecycle.d.ts +17 -17
- package/dist/session-lifecycle.d.ts.map +1 -1
- package/dist/session-lifecycle.js +82 -82
- package/dist/session-lifecycle.js.map +1 -1
- package/dist/spawn-cooldown.d.ts +8 -8
- package/dist/spawn-cooldown.d.ts.map +1 -1
- package/dist/spawn-cooldown.js +15 -15
- package/dist/spawn-cooldown.js.map +1 -1
- package/dist/spawn-environment.d.ts +2 -2
- package/dist/spawn-environment.d.ts.map +1 -1
- package/dist/spawn-environment.js +3 -3
- package/dist/spawn-environment.js.map +1 -1
- package/dist/spawner-lifecycle.d.ts +2 -2
- package/dist/spawner-lifecycle.d.ts.map +1 -1
- package/dist/spawner-lifecycle.js +3 -3
- package/dist/spawner-lifecycle.js.map +1 -1
- package/dist/spawner-resolution.d.ts +3 -3
- package/dist/spawner-resolution.d.ts.map +1 -1
- package/dist/spawner-resolution.js +4 -4
- package/dist/spawner-resolution.js.map +1 -1
- package/dist/spawner-stream-handlers.js +2 -2
- package/dist/spawner-stream-handlers.js.map +1 -1
- package/dist/spawner.d.ts +1 -1
- package/dist/spawner.d.ts.map +1 -1
- package/dist/spawner.js +6 -6
- package/dist/spawner.js.map +1 -1
- package/dist/stage-classifier.d.ts +1 -1
- package/dist/stage-classifier.js +1 -1
- package/dist/state-cascade.d.ts +25 -25
- package/dist/state-cascade.d.ts.map +1 -1
- package/dist/state-cascade.js +89 -89
- package/dist/state-cascade.js.map +1 -1
- package/dist/strategy-completion-event.d.ts +37 -3
- package/dist/strategy-completion-event.d.ts.map +1 -1
- package/dist/strategy-completion-event.js +78 -9
- package/dist/strategy-completion-event.js.map +1 -1
- package/dist/strategy-completion.d.ts +11 -0
- package/dist/strategy-completion.d.ts.map +1 -1
- package/dist/strategy-completion.js +22 -1
- package/dist/strategy-completion.js.map +1 -1
- package/dist/strategy-executor.d.ts.map +1 -1
- package/dist/strategy-executor.js +46 -14
- package/dist/strategy-executor.js.map +1 -1
- package/dist/strategy-merge.d.ts.map +1 -1
- package/dist/strategy-merge.js +4 -0
- package/dist/strategy-merge.js.map +1 -1
- package/dist/strategy-team-lifecycle.d.ts.map +1 -1
- package/dist/strategy-team-lifecycle.js +3 -0
- package/dist/strategy-team-lifecycle.js.map +1 -1
- package/dist/supabase.d.ts +4 -4
- package/dist/supabase.d.ts.map +1 -1
- package/dist/supabase.js +5 -5
- package/dist/supabase.js.map +1 -1
- package/dist/task-converter.d.ts +4 -4
- package/dist/task-converter.d.ts.map +1 -1
- package/dist/task-converter.js +1 -1
- package/dist/task-converter.js.map +1 -1
- package/dist/team-prompt-base.d.ts +59 -19
- package/dist/team-prompt-base.d.ts.map +1 -1
- package/dist/team-prompt-base.js +206 -25
- package/dist/team-prompt-base.js.map +1 -1
- package/dist/team-spawner.d.ts +9 -9
- package/dist/team-spawner.d.ts.map +1 -1
- package/dist/team-spawner.js +87 -83
- package/dist/team-spawner.js.map +1 -1
- package/dist/telemetry-writer.d.ts +2 -2
- package/dist/telemetry-writer.d.ts.map +1 -1
- package/dist/templates/claude-md.js +8 -8
- package/dist/templates/claude-settings.d.ts +1 -1
- package/dist/templates/claude-settings.js +2 -2
- package/dist/templates/claude-settings.js.map +1 -1
- package/dist/trigger-executor.d.ts +4 -4
- package/dist/trigger-executor.d.ts.map +1 -1
- package/dist/trigger-executor.js +11 -11
- package/dist/trigger-executor.js.map +1 -1
- package/dist/types/dag.d.ts +1 -1
- package/dist/types/delivery.d.ts +3 -3
- package/dist/types/delivery.d.ts.map +1 -1
- package/dist/types/focus.d.ts +214 -0
- package/dist/types/focus.d.ts.map +1 -0
- package/dist/types/focus.js +5 -0
- package/dist/types/focus.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/merge.d.ts +1 -1
- package/dist/types/session.d.ts +2 -2
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/strategy.d.ts +7 -0
- package/dist/types/strategy.d.ts.map +1 -1
- package/dist/unified-engine-lifecycle.js +11 -11
- package/dist/unified-engine-lifecycle.js.map +1 -1
- package/dist/unified-init.d.ts +1 -1
- package/dist/unified-init.js +9 -9
- package/dist/unified-init.js.map +1 -1
- package/dist/unified-shell-config.d.ts +4 -4
- package/dist/unified-shell-config.d.ts.map +1 -1
- package/dist/unified-shell-config.js +5 -5
- package/dist/unified-shell-config.js.map +1 -1
- package/dist/unified-shell-status.js +3 -3
- package/dist/unified-shell-status.js.map +1 -1
- package/dist/unified-shell.d.ts +1 -1
- package/dist/unified-shell.js +4 -4
- package/dist/unified-shell.js.map +1 -1
- package/dist/workflow-engine.d.ts +1 -1
- package/dist/workflow-engine.d.ts.map +1 -1
- package/dist/worktree-focus.d.ts +69 -0
- package/dist/worktree-focus.d.ts.map +1 -0
- package/dist/worktree-focus.js +214 -0
- package/dist/worktree-focus.js.map +1 -0
- package/dist/worktree.d.ts +10 -10
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +39 -39
- package/dist/worktree.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-defect re-engagement loop.
|
|
3
|
+
*
|
|
4
|
+
* The review subsystem (review_requested_at + review session_type) audits
|
|
5
|
+
* completed work and files defects. Without this module, defects sit
|
|
6
|
+
* indefinitely in `in_review` because nothing drives them to resolution.
|
|
7
|
+
*
|
|
8
|
+
* This module closes that quality loop:
|
|
9
|
+
* * Detector -- finds strategies in `in_review` with open issues filed
|
|
10
|
+
* during the most recent review pass, and transitions them back to
|
|
11
|
+
* `building` so the executor spawns a remediation team.
|
|
12
|
+
* * Re-entry -- when all review-filed issues for a focus are Done
|
|
13
|
+
* (and the focus is back in `building`), transitions the focus
|
|
14
|
+
* to `verify` so the existing review subsystem can pass it through to
|
|
15
|
+
* `in_review` for a fresh review pass.
|
|
16
|
+
* * Bound -- tracks per-focus remediation cycle count. After N
|
|
17
|
+
* consecutive cycles, escalates to humans via `agent_escalations`.
|
|
18
|
+
*
|
|
19
|
+
* Identifying review-filed issues:
|
|
20
|
+
* We use `created_by_role_id` (filters out human/UI-filed issues, which
|
|
21
|
+
* leave the column NULL) AND timing -- the issue was created after the
|
|
22
|
+
* focus's most recent `review_requested_at` while in `in_review`. A
|
|
23
|
+
* single role is often shared across team and review sessions, so role
|
|
24
|
+
* alone is insufficient; the timing-plus-focus-status combination is
|
|
25
|
+
* what reliably identifies "filed during a review pass".
|
|
26
|
+
*/
|
|
27
|
+
import { withRetry, ESCALATION_REASONS } from '@telora/daemon-core';
|
|
28
|
+
import { getActiveFocuses } from './supabase.js';
|
|
29
|
+
import { getFocusDeliveries, getFocusIssues, updateFocusStatus, fetchFocusWorkflowWithTransitions, } from './queries/focuses.js';
|
|
30
|
+
import { createEscalation as defaultCreateEscalation } from './queries/issues.js';
|
|
31
|
+
import { OPEN_ISSUE_STATUSES } from './constants.js';
|
|
32
|
+
// ── Configuration ────────────────────────────────────────────────────────
|
|
33
|
+
/** Reason string emitted when remediation cycles exceed the bound. */
|
|
34
|
+
export const REVIEW_REMEDIATION_ESCALATION_REASON = 'review-defect remediation exceeded N cycles';
|
|
35
|
+
/** Default cap on remediation cycles before escalation. Configurable via env. */
|
|
36
|
+
export const REVIEW_REMEDIATION_LIMIT = (() => {
|
|
37
|
+
const raw = process.env.TELORA_REVIEW_REMEDIATION_LIMIT;
|
|
38
|
+
if (!raw)
|
|
39
|
+
return 3;
|
|
40
|
+
const parsed = Number.parseInt(raw, 10);
|
|
41
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 3;
|
|
42
|
+
})();
|
|
43
|
+
// ── Per-focus cycle counter ──────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* In-memory map of focus ID -> consecutive remediation cycles. Cycle
|
|
46
|
+
* counts are not persisted to the database -- a daemon restart resets the
|
|
47
|
+
* counter, which is acceptable because the bound exists to prevent runaway
|
|
48
|
+
* loops within a single daemon lifetime, not across restarts.
|
|
49
|
+
*
|
|
50
|
+
* Exported for testability.
|
|
51
|
+
*/
|
|
52
|
+
const remediationCycles = new Map();
|
|
53
|
+
export function getRemediationCycles(focusId) {
|
|
54
|
+
return remediationCycles.get(focusId) ?? 0;
|
|
55
|
+
}
|
|
56
|
+
export function incrementRemediationCycles(focusId) {
|
|
57
|
+
const next = (remediationCycles.get(focusId) ?? 0) + 1;
|
|
58
|
+
remediationCycles.set(focusId, next);
|
|
59
|
+
return next;
|
|
60
|
+
}
|
|
61
|
+
export function resetRemediationCycles(focusId) {
|
|
62
|
+
remediationCycles.delete(focusId);
|
|
63
|
+
}
|
|
64
|
+
/** Test-only: clear all cycle state. */
|
|
65
|
+
export function _resetAllRemediationCyclesForTest() {
|
|
66
|
+
remediationCycles.clear();
|
|
67
|
+
}
|
|
68
|
+
// ── Issue classification ────────────────────────────────────────────────
|
|
69
|
+
/**
|
|
70
|
+
* Returns true when an issue was filed during the most recent review pass
|
|
71
|
+
* on the given focus.
|
|
72
|
+
*
|
|
73
|
+
* An issue is "review-filed" when ALL of:
|
|
74
|
+
* - It has a non-null created_by_role_id (excludes human/UI creates).
|
|
75
|
+
* - Its created_at is later than the focus's review_requested_at
|
|
76
|
+
* (or the focus is in `in_review` with no recorded request time --
|
|
77
|
+
* covers manual review trigger).
|
|
78
|
+
* - Its status is open (To Do / In Progress / Blocked).
|
|
79
|
+
*/
|
|
80
|
+
export function isReviewFiledIssue(issue, reviewRequestedAt) {
|
|
81
|
+
if (!issue.createdByRoleId)
|
|
82
|
+
return false;
|
|
83
|
+
if (!OPEN_ISSUE_STATUSES.has(issue.status))
|
|
84
|
+
return false;
|
|
85
|
+
if (!reviewRequestedAt) {
|
|
86
|
+
// No review timestamp -- conservative: do not treat as review-filed.
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (!issue.createdAt)
|
|
90
|
+
return false;
|
|
91
|
+
return new Date(issue.createdAt).getTime() >= new Date(reviewRequestedAt).getTime();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Filter a focus's issues to only those that were filed during the most
|
|
95
|
+
* recent review pass and are still open. Used to drive both the detector
|
|
96
|
+
* (transition to building) and the re-entry check (return to in_review when
|
|
97
|
+
* all are Done).
|
|
98
|
+
*/
|
|
99
|
+
export function filterReviewFiledIssues(issues, reviewRequestedAt) {
|
|
100
|
+
return issues.filter(i => isReviewFiledIssue(i, reviewRequestedAt));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Returns true when there are any review-filed issues (open or closed)
|
|
104
|
+
* since the most recent review pass. Used by the re-entry check: if there
|
|
105
|
+
* were review-filed issues AND all of them are Done, the focus is
|
|
106
|
+
* eligible to return to in_review.
|
|
107
|
+
*/
|
|
108
|
+
export function reviewFiledIssueExists(issues, reviewRequestedAt) {
|
|
109
|
+
if (!reviewRequestedAt)
|
|
110
|
+
return false;
|
|
111
|
+
for (const i of issues) {
|
|
112
|
+
if (!i.createdByRoleId)
|
|
113
|
+
continue;
|
|
114
|
+
if (!i.createdAt)
|
|
115
|
+
continue;
|
|
116
|
+
if (new Date(i.createdAt).getTime() >= new Date(reviewRequestedAt).getTime()) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
const defaultDeps = {
|
|
123
|
+
getActiveFocuses,
|
|
124
|
+
getFocusDeliveries,
|
|
125
|
+
getFocusIssues,
|
|
126
|
+
updateFocusStatus,
|
|
127
|
+
fetchFocusWorkflowWithTransitions,
|
|
128
|
+
createEscalation: defaultCreateEscalation,
|
|
129
|
+
};
|
|
130
|
+
// ── Detector and re-entry ───────────────────────────────────────────────
|
|
131
|
+
/**
|
|
132
|
+
* For each active focus in `in_review` status, check whether any
|
|
133
|
+
* review-filed issues remain open. If so, transition the focus back to
|
|
134
|
+
* `building` and bump the remediation counter. When the counter exceeds
|
|
135
|
+
* the bound, escalate instead of transitioning -- the team has been
|
|
136
|
+
* stuck in a remediation loop and a human needs to intervene.
|
|
137
|
+
*
|
|
138
|
+
* Designed to be called from the daemon poll loop on every tick; it is
|
|
139
|
+
* a no-op for strategies that don't satisfy the trigger conditions.
|
|
140
|
+
*/
|
|
141
|
+
export async function detectAndHandleReviewDefects(config, deps = defaultDeps) {
|
|
142
|
+
let strategies;
|
|
143
|
+
try {
|
|
144
|
+
strategies = await deps.getActiveFocuses(config.organizationId, config.productId);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
console.warn('[review-defect-detector] Failed to fetch active strategies:', err.message);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
for (const s of strategies) {
|
|
151
|
+
if (s.status !== 'in_review')
|
|
152
|
+
continue;
|
|
153
|
+
try {
|
|
154
|
+
const issues = await deps.getFocusIssues(s.focus_id);
|
|
155
|
+
const reviewOpen = filterReviewFiledIssues(issues, s.review_requested_at ?? null);
|
|
156
|
+
if (reviewOpen.length === 0)
|
|
157
|
+
continue;
|
|
158
|
+
const cycles = incrementRemediationCycles(s.focus_id);
|
|
159
|
+
if (cycles > REVIEW_REMEDIATION_LIMIT) {
|
|
160
|
+
console.warn(`[review-defect-detector] Remediation bound exceeded for "${s.focus_name}" ` +
|
|
161
|
+
`(cycle ${cycles}/${REVIEW_REMEDIATION_LIMIT}); escalating`);
|
|
162
|
+
await escalateReviewRemediation({
|
|
163
|
+
organizationId: config.organizationId,
|
|
164
|
+
focusId: s.focus_id,
|
|
165
|
+
focusName: s.focus_name,
|
|
166
|
+
cycles,
|
|
167
|
+
openIssues: reviewOpen,
|
|
168
|
+
}, deps);
|
|
169
|
+
// Reset so a future review pass starts fresh after human intervention.
|
|
170
|
+
resetRemediationCycles(s.focus_id);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
// Transition the focus from in_review back to building so the
|
|
174
|
+
// focus executor's poll loop spawns a remediation team.
|
|
175
|
+
const workflow = await deps.fetchFocusWorkflowWithTransitions(s.focus_id);
|
|
176
|
+
const buildingStage = workflow.stages.find(st => st.name === 'building');
|
|
177
|
+
try {
|
|
178
|
+
await deps.updateFocusStatus(s.focus_id, 'building', buildingStage?.id ?? null);
|
|
179
|
+
console.log(`[review-defect-detector] Focus "${s.focus_name}" -> building ` +
|
|
180
|
+
`(${reviewOpen.length} review-filed issue(s) open, remediation cycle ${cycles}/${REVIEW_REMEDIATION_LIMIT})`);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
console.warn(`[review-defect-detector] Failed to move "${s.focus_name}" to building: ${err.message}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
console.warn(`[review-defect-detector] Error checking focus "${s.focus_name}":`, err.message);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* For each active focus in `building` status that has had a review pass
|
|
193
|
+
* (review_requested_at set) and review-filed issues since, check whether
|
|
194
|
+
* all of those issues are now Done. If so, transition the focus back to
|
|
195
|
+
* `verify` so the existing review pipeline can re-run and either close it
|
|
196
|
+
* out or file new defects.
|
|
197
|
+
*
|
|
198
|
+
* Called alongside the detector; safe to invoke on every poll tick.
|
|
199
|
+
*/
|
|
200
|
+
export async function detectAndHandleRemediationComplete(config, deps = defaultDeps) {
|
|
201
|
+
let strategies;
|
|
202
|
+
try {
|
|
203
|
+
strategies = await deps.getActiveFocuses(config.organizationId, config.productId);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
console.warn('[review-defect-detector] Failed to fetch active strategies:', err.message);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
for (const s of strategies) {
|
|
210
|
+
// Only act on strategies that were just remediating: status='building'
|
|
211
|
+
// with a recorded review request.
|
|
212
|
+
if (s.status !== 'building')
|
|
213
|
+
continue;
|
|
214
|
+
if (!s.review_requested_at)
|
|
215
|
+
continue;
|
|
216
|
+
try {
|
|
217
|
+
const issues = await deps.getFocusIssues(s.focus_id);
|
|
218
|
+
const allReviewFiled = issues.filter(i => i.createdByRoleId && i.createdAt &&
|
|
219
|
+
new Date(i.createdAt).getTime() >= new Date(s.review_requested_at).getTime());
|
|
220
|
+
if (allReviewFiled.length === 0)
|
|
221
|
+
continue; // no remediation in progress
|
|
222
|
+
const stillOpen = allReviewFiled.filter(i => OPEN_ISSUE_STATUSES.has(i.status));
|
|
223
|
+
if (stillOpen.length > 0)
|
|
224
|
+
continue; // still remediating
|
|
225
|
+
// All review-filed issues are Done -- transition to verify so the
|
|
226
|
+
// review pipeline re-runs.
|
|
227
|
+
const workflow = await deps.fetchFocusWorkflowWithTransitions(s.focus_id);
|
|
228
|
+
const verifyStage = workflow.stages.find(st => st.name === 'verify');
|
|
229
|
+
await deps.updateFocusStatus(s.focus_id, 'verify', verifyStage?.id ?? null);
|
|
230
|
+
console.log(`[review-defect-detector] Focus "${s.focus_name}" -> verify ` +
|
|
231
|
+
`(${allReviewFiled.length} review-filed issue(s) all Done, remediation cycle complete)`);
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
console.warn(`[review-defect-detector] Error checking remediation completion for "${s.focus_name}":`, err.message);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Escalate when remediation cycles exceed the configured bound. Surfaces
|
|
240
|
+
* the issue list and a clear call to action so the human reviewer can
|
|
241
|
+
* unblock the loop.
|
|
242
|
+
*/
|
|
243
|
+
export async function escalateReviewRemediation(params, deps = defaultDeps) {
|
|
244
|
+
const issueList = params.openIssues
|
|
245
|
+
.slice(0, 25)
|
|
246
|
+
.map(i => `- [${i.status}] ${i.key}: ${i.title}`)
|
|
247
|
+
.join('\n');
|
|
248
|
+
const overflow = params.openIssues.length > 25
|
|
249
|
+
? `\n(... and ${params.openIssues.length - 25} more)`
|
|
250
|
+
: '';
|
|
251
|
+
try {
|
|
252
|
+
await withRetry(() => deps.createEscalation({
|
|
253
|
+
organizationId: params.organizationId,
|
|
254
|
+
sessionId: '',
|
|
255
|
+
issueId: null,
|
|
256
|
+
reasonType: ESCALATION_REASONS.BLOCKED_BY_EXTERNAL,
|
|
257
|
+
description: `Focus "${params.focusName}" has cycled through review-defect remediation ` +
|
|
258
|
+
`${params.cycles} time(s). Reason: ${REVIEW_REMEDIATION_ESCALATION_REASON}.\n\n` +
|
|
259
|
+
`**Focus:** ${params.focusName}\n` +
|
|
260
|
+
`**Focus ID:** ${params.focusId}\n` +
|
|
261
|
+
`**Cycles:** ${params.cycles} (limit: ${REVIEW_REMEDIATION_LIMIT})\n\n` +
|
|
262
|
+
`**Open review-filed issues (${params.openIssues.length}):**\n${issueList}${overflow}`,
|
|
263
|
+
whatWasTried: `The daemon respawned remediation teams ${params.cycles} time(s) and the team ` +
|
|
264
|
+
`was unable to close all review-filed defects between review passes.`,
|
|
265
|
+
helpNeeded: `Review the open issues above. Either close out genuinely-blocked items, ` +
|
|
266
|
+
`clarify acceptance criteria so the next remediation cycle can succeed, or ` +
|
|
267
|
+
`cancel the focus if it is no longer viable.`,
|
|
268
|
+
}), { maxAttempts: 3, label: `escalation-review-remediation-${params.focusId}` });
|
|
269
|
+
console.log(`[review-defect-detector] Created remediation escalation for "${params.focusName}" ` +
|
|
270
|
+
`(reason: ${REVIEW_REMEDIATION_ESCALATION_REASON})`);
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
console.error(`[review-defect-detector] Failed to create remediation escalation for "${params.focusName}": ${err.message}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Combined entry point: call both halves of the loop on each poll tick.
|
|
278
|
+
*
|
|
279
|
+
* Order matters slightly: handle remediation completion first (returns
|
|
280
|
+
* Done strategies to verify) before the defect detector (kicks fresh
|
|
281
|
+
* defects to building). Doing it in this order means a focus can flow
|
|
282
|
+
* verify -> in_review -> building -> verify in a single cycle when work
|
|
283
|
+
* is fast.
|
|
284
|
+
*/
|
|
285
|
+
export async function tickReviewDefectLoop(config, deps = defaultDeps) {
|
|
286
|
+
await detectAndHandleRemediationComplete(config, deps);
|
|
287
|
+
await detectAndHandleReviewDefects(config, deps);
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=review-defect-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-defect-detector.js","sourceRoot":"","sources":["../src/review-defect-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Session lifecycle management for
|
|
2
|
+
* Session lifecycle management for focus teams.
|
|
3
3
|
*
|
|
4
|
-
* Extracted from
|
|
4
|
+
* Extracted from focus-executor.ts. Contains functions for session
|
|
5
5
|
* start/end, cleanup, error handling, team completion detection,
|
|
6
6
|
* termination, and deactivation checks.
|
|
7
7
|
*/
|
|
8
8
|
import type { ChildProcess } from 'node:child_process';
|
|
9
|
-
import type { DaemonConfig,
|
|
9
|
+
import type { DaemonConfig, FocusTeamState } from './types.js';
|
|
10
10
|
import type { CompletionDetector } from './completion-detector.js';
|
|
11
11
|
import type { ActivityTracker } from './activity-tracker.js';
|
|
12
|
-
import type {
|
|
12
|
+
import type { SpawnFocusTeamParams } from './team-spawner.js';
|
|
13
13
|
import type { LogStreams } from './types.js';
|
|
14
14
|
export interface SessionLifecycleContext {
|
|
15
15
|
proc: ChildProcess;
|
|
16
|
-
params:
|
|
17
|
-
teamState:
|
|
16
|
+
params: SpawnFocusTeamParams;
|
|
17
|
+
teamState: FocusTeamState;
|
|
18
18
|
sessionId: string;
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
focusId: string;
|
|
20
|
+
focusName: string;
|
|
21
21
|
completionDetector: CompletionDetector;
|
|
22
22
|
activityTracker: ActivityTracker;
|
|
23
23
|
logStreams: LogStreams;
|
|
@@ -34,36 +34,36 @@ export interface SessionLifecycleContext {
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function attachSessionLifecycle(ctx: SessionLifecycleContext): void;
|
|
36
36
|
/**
|
|
37
|
-
* Terminate a
|
|
37
|
+
* Terminate a focus team.
|
|
38
38
|
*
|
|
39
39
|
* Sends a deactivation message via stdin (if open) before SIGTERM
|
|
40
40
|
* to allow the team lead to process the shutdown gracefully.
|
|
41
41
|
*/
|
|
42
|
-
export declare function terminateTeam(
|
|
42
|
+
export declare function terminateTeam(focusId: string): boolean;
|
|
43
43
|
/**
|
|
44
44
|
* Wait for a team's process to exit (leave activeTeams).
|
|
45
45
|
*
|
|
46
|
-
* Polls activeTeams until the
|
|
46
|
+
* Polls activeTeams until the focus is no longer present,
|
|
47
47
|
* which happens when handleTeamCompletion runs on the 'close' event.
|
|
48
48
|
* If the timeout expires, sends SIGKILL and waits briefly.
|
|
49
49
|
*
|
|
50
|
-
* @param
|
|
50
|
+
* @param focusId - Focus to wait for
|
|
51
51
|
* @param timeoutMs - Max wait time in ms (default 30s)
|
|
52
52
|
* @returns true if team exited within timeout, false if forced
|
|
53
53
|
*/
|
|
54
|
-
export declare function waitForTeamExit(
|
|
54
|
+
export declare function waitForTeamExit(focusId: string, timeoutMs?: number): Promise<boolean>;
|
|
55
55
|
/**
|
|
56
56
|
* Terminate all active teams.
|
|
57
57
|
*/
|
|
58
58
|
export declare function terminateAllTeams(): void;
|
|
59
59
|
/**
|
|
60
|
-
* Detect
|
|
60
|
+
* Detect focuses that have been deactivated (agent role removed)
|
|
61
61
|
* and shut down their active teams.
|
|
62
62
|
*/
|
|
63
|
-
export declare function
|
|
63
|
+
export declare function detectDeactivatedFocuses(config: DaemonConfig): Promise<void>;
|
|
64
64
|
/**
|
|
65
65
|
* Check active teams for newly completed deliveries and merge
|
|
66
|
-
* the
|
|
66
|
+
* the focus branch to integration incrementally.
|
|
67
67
|
*
|
|
68
68
|
* Called from the poll loop. For each active team, queries delivery
|
|
69
69
|
* statuses and triggers a merge when any delivery reaches verify/done
|
|
@@ -71,7 +71,7 @@ export declare function detectDeactivatedStrategies(config: DaemonConfig): Promi
|
|
|
71
71
|
*
|
|
72
72
|
* After processing merges, checks if ALL active deliveries are terminal
|
|
73
73
|
* and merged. If so, terminates the team proactively since no more work
|
|
74
|
-
* remains. The
|
|
74
|
+
* remains. The focus stays active in the DB -- if new deliveries
|
|
75
75
|
* arrive later, the next poll cycle spawns a fresh team.
|
|
76
76
|
*/
|
|
77
77
|
export declare function checkAndMergeCompletedDeliveries(config: DaemonConfig): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-lifecycle.d.ts","sourceRoot":"","sources":["../src/session-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"session-lifecycle.d.ts","sourceRoot":"","sources":["../src/session-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAM/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAc7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA0F7C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,eAAe,EAAE,eAAe,CAAC;IACjC,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,uBAAuB,GAAG,IAAI,CA2HzE;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CA2CtD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAsB1F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CA0Ff"}
|