opencode-swarm 7.14.0 → 7.16.0

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.
Files changed (34) hide show
  1. package/README.md +4 -3
  2. package/dist/cli/index.js +2114 -553
  3. package/dist/commands/close.d.ts +14 -1
  4. package/dist/commands/registry.d.ts +3 -3
  5. package/dist/commands/turbo.d.ts +4 -4
  6. package/dist/config/constants.d.ts +12 -1
  7. package/dist/config/index.d.ts +2 -2
  8. package/dist/config/schema.d.ts +116 -0
  9. package/dist/index.js +5288 -2128
  10. package/dist/parallel/file-locks.d.ts +50 -2
  11. package/dist/services/skill-improver.d.ts +1 -0
  12. package/dist/services/status-service.d.ts +29 -0
  13. package/dist/state.d.ts +17 -0
  14. package/dist/tools/index.d.ts +6 -0
  15. package/dist/tools/lean-turbo-acquire-locks.d.ts +36 -0
  16. package/dist/tools/lean-turbo-plan-lanes.d.ts +35 -0
  17. package/dist/tools/lean-turbo-review.d.ts +34 -0
  18. package/dist/tools/lean-turbo-run-phase.d.ts +44 -0
  19. package/dist/tools/lean-turbo-runner-status.d.ts +36 -0
  20. package/dist/tools/lean-turbo-status.d.ts +44 -0
  21. package/dist/tools/tool-names.d.ts +1 -1
  22. package/dist/tools/update-task-status.d.ts +7 -4
  23. package/dist/turbo/lean/conflicts.d.ts +100 -0
  24. package/dist/turbo/lean/evidence.d.ts +91 -0
  25. package/dist/turbo/lean/index.d.ts +27 -0
  26. package/dist/turbo/lean/integration.d.ts +137 -0
  27. package/dist/turbo/lean/phase-ready.d.ts +105 -0
  28. package/dist/turbo/lean/planner.d.ts +115 -0
  29. package/dist/turbo/lean/reviewer.d.ts +124 -0
  30. package/dist/turbo/lean/risk.d.ts +47 -0
  31. package/dist/turbo/lean/runner.d.ts +322 -0
  32. package/dist/turbo/lean/state.d.ts +61 -0
  33. package/dist/turbo/lean/task-completion.d.ts +53 -0
  34. package/package.json +1 -1
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Lean Turbo Module — barrel export.
3
+ *
4
+ * Re-exports all public symbols from sub-modules so consumers can import
5
+ * everything from a single path:
6
+ *
7
+ * ```ts
8
+ * import { LeanTurboRunner, planLeanTurboLanes, LeanTurboLane, ... } from './turbo/lean';
9
+ * ```
10
+ */
11
+ export type { LaneDispatchResult, LaneResult, LaneStatus, LeanTurboPhaseResult, } from './runner';
12
+ export { LeanTurboRunner } from './runner';
13
+ export type { LeanTurboLanePlan, PlanPhase, PlanTask, } from './planner';
14
+ export { GLOBAL_FILES_LIST, isGlobalFile, isPathSafe, isProtectedPath, normalizePath, PROTECTED_PATTERNS_LIST, pathsConflict, planLeanTurboLanes, readTaskScopes, } from './planner';
15
+ export type { LeanTurboCounters, LeanTurboDegradedTask, LeanTurboLane, LeanTurboPersistedState, LeanTurboRunState, LeanTurboStatus, } from './state';
16
+ export { emptyCounters, emptyPersisted, emptyRunState, isLeanTurboRunActive, isStateUnreadable, loadLeanTurboRunState, pauseLeanTurboRun, repairStateUnreadable, resetLeanTurboRun, saveLeanTurboRunState, } from './state';
17
+ export type { LeanTurboConfig } from '../../config/schema';
18
+ export type { LaneEvidence, PhaseEvidence } from './evidence';
19
+ export { listLaneEvidence, readLaneEvidence, readPhaseEvidence, writeLaneEvidence, writePhaseEvidence, } from './evidence';
20
+ export type { LeanTurboPhaseReadyConfig, LeanTurboPhaseReadyResult, } from './phase-ready';
21
+ export { verifyLeanTurboPhaseReady } from './phase-ready';
22
+ export type { TaskRiskAssessment, TaskRiskCategory } from './risk';
23
+ export { assessTaskRisk } from './risk';
24
+ export type { LeanTurboPhaseCriticConfig, PhaseCriticResult, } from './integration';
25
+ export { dispatchPhaseCritic } from './integration';
26
+ export type { LeanTurboPhaseReviewerConfig, PhaseReviewerResult, } from './reviewer';
27
+ export { dispatchPhaseReviewer } from './reviewer';
@@ -0,0 +1,137 @@
1
+ import { type LaneEvidence, listLaneEvidence, readPhaseEvidence } from './evidence';
2
+ /**
3
+ * Configuration options for phase critic dispatch.
4
+ */
5
+ export interface LeanTurboPhaseCriticConfig {
6
+ /**
7
+ * Override the critic agent name.
8
+ * Default: derived from `generatedAgentNames` via `{swarmId}_critic` pattern
9
+ * when a swarm has multiple critics, or `critic` for the default swarm.
10
+ */
11
+ criticAgent?: string;
12
+ /**
13
+ * Timeout in milliseconds for the critic dispatch.
14
+ * Default: no timeout (critic is awaited indefinitely).
15
+ */
16
+ timeoutMs?: number;
17
+ }
18
+ /**
19
+ * Result of a phase critic dispatch.
20
+ */
21
+ export interface PhaseCriticResult {
22
+ /** Critic verdict */
23
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED' | 'ESCALATE_TO_HUMAN';
24
+ /** Human-readable reason for the verdict */
25
+ reason?: string;
26
+ /** Path to the persisted critic evidence file */
27
+ evidencePath: string;
28
+ }
29
+ /**
30
+ * Reviewer evidence record (lean-turbo-reviewer.json).
31
+ */
32
+ interface ReviewerEvidence {
33
+ phase: number;
34
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED';
35
+ reason?: string | null;
36
+ timestamp: string;
37
+ }
38
+ /**
39
+ * Resolves the default critic agent name from the generated agent names.
40
+ *
41
+ * Uses the `{swarmId}_critic` pattern for named swarms and bare `critic`
42
+ * for the default swarm. Follows the same suffix-based resolution used by
43
+ * `getCanonicalAgentRole` so that arbitrary swarm prefixes are handled correctly.
44
+ */
45
+ declare function resolveDefaultCriticAgent(generatedAgentNames: string[]): string;
46
+ /**
47
+ * Reads the reviewer evidence from .swarm/evidence/{phase}/lean-turbo-reviewer.json.
48
+ *
49
+ * @returns Parsed reviewer evidence, or null if file does not exist or is invalid
50
+ */
51
+ declare function readReviewerEvidence(directory: string, phase: number): Promise<ReviewerEvidence | null>;
52
+ /**
53
+ * Compiles a structured boundary review package from reviewer and phase evidence.
54
+ */
55
+ interface CriticPackage {
56
+ phase: number;
57
+ sessionID: string;
58
+ /** Reviewer verdict if available */
59
+ reviewerVerdict?: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED';
60
+ /** Whether reviewer evidence was missing or invalid */
61
+ reviewerMissing: boolean;
62
+ /** Safety concerns noted during compilation */
63
+ safetyConcerns: string[];
64
+ laneSummaries: Array<{
65
+ laneId: string;
66
+ taskIds: string[];
67
+ files: string[];
68
+ status: LaneEvidence['status'];
69
+ agent?: string;
70
+ }>;
71
+ filesChanged: string[];
72
+ testResults: {
73
+ totalLanes: number;
74
+ completedLanes: number;
75
+ failedLanes: number;
76
+ };
77
+ degradationSummary: {
78
+ totalDegraded: number;
79
+ resolvedDegraded: number;
80
+ pendingDegraded: number;
81
+ };
82
+ }
83
+ declare function compileCriticPackage(directory: string, phase: number, sessionID: string): Promise<CriticPackage>;
84
+ /**
85
+ * Parses a critic verdict from the agent's text response.
86
+ *
87
+ * Looks for a verdict marker line: `VERDICT: APPROVED`, `VERDICT: NEEDS_REVISION`,
88
+ * `VERDICT: REJECTED`, or `VERDICT: ESCALATE_TO_HUMAN` (case-insensitive).
89
+ * Returns null if no marker is found.
90
+ *
91
+ * The optional reason is extracted from a `REASON:` marker line that follows
92
+ * the verdict marker on a subsequent line.
93
+ */
94
+ declare function parseCriticVerdict(responseText: string): {
95
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED' | 'ESCALATE_TO_HUMAN';
96
+ reason?: string;
97
+ } | null;
98
+ /**
99
+ * Writes the critic verdict to the evidence file.
100
+ * Uses atomic write (temp file + rename) to prevent partial-file artifacts.
101
+ */
102
+ declare function writeCriticEvidence(directory: string, phase: number, verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED' | 'ESCALATE_TO_HUMAN', reason?: string): Promise<string>;
103
+ /**
104
+ * Test-only dependency-injection seam.
105
+ * Allows tests to intercept critic dispatch without mock.module leakage.
106
+ */
107
+ export declare const _internals: {
108
+ compileCriticPackage: typeof compileCriticPackage;
109
+ parseCriticVerdict: typeof parseCriticVerdict;
110
+ writeCriticEvidence: typeof writeCriticEvidence;
111
+ dispatchCriticAgent: (directory: string, pkg: CriticPackage, agentName: string, timeoutMs: number) => Promise<string>;
112
+ resolveDefaultCriticAgent: typeof resolveDefaultCriticAgent;
113
+ readReviewerEvidence: typeof readReviewerEvidence;
114
+ listLaneEvidence: typeof listLaneEvidence;
115
+ readPhaseEvidence: typeof readPhaseEvidence;
116
+ };
117
+ /**
118
+ * Dispatch a read-only critic agent to evaluate boundary conditions for a completed Lean Turbo phase.
119
+ *
120
+ * Steps:
121
+ * 1. Read reviewer evidence from `.swarm/evidence/{phase}/lean-turbo-reviewer.json`
122
+ * 2. Read lane and phase evidence from `.swarm/evidence/{phase}/lean-turbo/`
123
+ * 3. Compile a boundary review package with safety concerns noted
124
+ * 4. Dispatch a read-only critic agent (tools: write=false, edit=false, patch=false)
125
+ * 5. Parse the verdict from the agent's response
126
+ * 6. Write the verdict to `.swarm/evidence/{phase}/lean-turbo-critic.json`
127
+ * 7. Return the result
128
+ *
129
+ * @param directory - Project root directory
130
+ * @param phase - Phase number being reviewed
131
+ * @param sessionID - Lean Turbo session ID
132
+ * @param config - Optional configuration overrides
133
+ * @returns PhaseCriticResult with verdict, optional reason, and evidence path
134
+ * @throws Error if dispatch fails or response cannot be parsed (fail-closed)
135
+ */
136
+ export declare function dispatchPhaseCritic(directory: string, phase: number, sessionID: string, config?: LeanTurboPhaseCriticConfig): Promise<PhaseCriticResult>;
137
+ export {};
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Lean Turbo Phase Boundary Gate Verification.
3
+ *
4
+ * Provides a synchronous helper to check whether a Lean Turbo phase is ready
5
+ * to advance to the next phase — i.e., whether all gates (lane completion,
6
+ * lock clearance, degraded task resolution, reviewer/critic approval) have
7
+ * been satisfied.
8
+ */
9
+ import { listActiveLocks } from '../../parallel/file-locks';
10
+ import { listLaneEvidence } from './evidence';
11
+ import { readPersisted } from './state';
12
+ /**
13
+ * Configuration options for phase gate checks.
14
+ * Passed optionally so callers can control whether reviewer/critic checks run.
15
+ */
16
+ export interface LeanTurboPhaseReadyConfig {
17
+ phase_reviewer?: boolean;
18
+ phase_critic?: boolean;
19
+ integrated_diff_required?: boolean;
20
+ }
21
+ /**
22
+ * Result of the Lean Turbo phase readiness check.
23
+ */
24
+ export interface LeanTurboPhaseReadyResult {
25
+ ok: boolean;
26
+ reason: string;
27
+ evidence?: {
28
+ lanes: string[];
29
+ degradedTasks: string[];
30
+ reviewerVerdict?: string;
31
+ criticVerdict?: string;
32
+ };
33
+ }
34
+ /**
35
+ * Shape of the plan.json file read by _internals.readPlanJson.
36
+ */
37
+ interface PlanJson {
38
+ phases: Array<{
39
+ id?: number;
40
+ tasks: Array<{
41
+ id: string;
42
+ status: string;
43
+ }>;
44
+ }>;
45
+ }
46
+ /**
47
+ * Shape of the reviewer evidence file (lean-turbo-reviewer.json).
48
+ */
49
+ interface ReviewerEvidence {
50
+ phase: number;
51
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED';
52
+ reason?: string | null;
53
+ timestamp: string;
54
+ }
55
+ /**
56
+ * Shape of the critic evidence file (lean-turbo-critic.json).
57
+ */
58
+ interface CriticEvidence {
59
+ phase: number;
60
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED' | 'ESCALATE_TO_HUMAN';
61
+ reason?: string | null;
62
+ timestamp: string;
63
+ }
64
+ /**
65
+ * Test-only seam. Replaces the lock-list and state-load functions so tests
66
+ * can inject mock results without touching the real `file-locks` module or
67
+ * the module-level `stateUnreadable` flag used by `loadLeanTurboRunState`.
68
+ */
69
+ export declare const _internals: {
70
+ listActiveLocks: typeof listActiveLocks;
71
+ readPersisted: typeof readPersisted;
72
+ readPlanJson: (dir: string) => PlanJson | null;
73
+ readReviewerEvidence: (dir: string, phase: number) => ReviewerEvidence | null;
74
+ readCriticEvidence: (dir: string, phase: number) => CriticEvidence | null;
75
+ listLaneEvidence: typeof listLaneEvidence;
76
+ listLaneEvidenceSync: (dir: string, phase: number) => string[];
77
+ verifyLeanTurboPhaseReady: typeof verifyLeanTurboPhaseReady;
78
+ };
79
+ /**
80
+ * Synchronously verify whether a Lean Turbo phase is ready to advance.
81
+ *
82
+ * Checks are performed in fail-fast order:
83
+ * 1. Read `.swarm/turbo-state.json` via readPersisted → null/unreadable → ok: false
84
+ * 2. Find a session with status === 'running' and phase === args.phase and strategy === 'lean'
85
+ * If sessionID is provided, also require sessionId === sessionID → none → ok: false
86
+ * 3. Validate session.lanes is a non-empty array → empty → ok: false
87
+ * 4. Check all eligible lanes have status 'completed' or 'failed' → not → ok: false
88
+ * 5. Check no active lane locks exist for lanes in this phase → locks → ok: false
89
+ * 6. Check all degraded tasks in lane plan are resolved → pending/in_progress → ok: false
90
+ * 7. Check integrated diff evidence exists (when required) → missing → ok: false
91
+ * 8. Check reviewer approval if phase_reviewer enabled → missing/rejected → ok: false
92
+ * 9. Check critic approval if phase_critic enabled → missing/rejected → ok: false
93
+ * 10. All checks pass → ok: true
94
+ *
95
+ * Supports two calling conventions for backward compatibility:
96
+ * - New: verifyLeanTurboPhaseReady(dir, phase, sessionID?, config?)
97
+ * - Legacy: verifyLeanTurboPhaseReady(dir, phase, config?) — config was previously the 3rd param
98
+ *
99
+ * @param directory - Project root directory
100
+ * @param phase - Phase number to verify readiness for
101
+ * @param sessionIDOrConfig - Optional session ID (string) OR config object (legacy 3rd-param style)
102
+ * @param config - Optional config; defaults to { phase_reviewer: true, phase_critic: true, integrated_diff_required: true }
103
+ */
104
+ export declare function verifyLeanTurboPhaseReady(directory: string, phase: number, sessionIDOrConfig?: string | LeanTurboPhaseReadyConfig, config?: LeanTurboPhaseReadyConfig): LeanTurboPhaseReadyResult;
105
+ export {};
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Lane Planning Engine for Lean Turbo.
3
+ *
4
+ * Lean Turbo is a parallel execution strategy that dispatches up to N non-conflicting
5
+ * coder lanes concurrently. This module implements the lane planner that partitions
6
+ * phase tasks into parallel lanes based on file-scope conflicts.
7
+ *
8
+ * ## Lane Planning Algorithm
9
+ *
10
+ * The planner operates in several phases:
11
+ *
12
+ * 1. **Task Extraction**: Extract tasks for the specified phase, filtering out
13
+ * already-completed tasks.
14
+ *
15
+ * 2. **Scope Resolution**: For each task, resolve its file scope:
16
+ * - Use provided scopes map if available
17
+ * - Otherwise, read from `.swarm/scopes/scope-{taskId}.json`
18
+ * - Fall back to `files_touched` from plan.json if `require_declared_scope` is false
19
+ * - If no scope available and `require_declared_scope` is true, serialize the task
20
+ *
21
+ * 3. **Conflict Detection**: Classify each task's files into:
22
+ * - **Global files**: High-risk files that affect all coders (package.json, etc.)
23
+ * → marked as degraded with reason "global file conflict"
24
+ * - **Protected paths**: Paths containing security-sensitive patterns
25
+ * → marked as degraded with reason "protected path" (if `degrade_on_risk` is true)
26
+ * → serialized otherwise
27
+ * - **Normal files**: Regular scoped files that need conflict checking
28
+ *
29
+ * 4. **Lane Assignment**:
30
+ * - Sort tasks by dependency order (tasks with no deps first)
31
+ * - For each non-conflicting task group, create a lane (up to `max_parallel_coders`)
32
+ * - Tasks with conflicts are serialized or degraded based on `conflict_policy`
33
+ *
34
+ * 5. **Counter Population**: Track planned lanes, serialized tasks, and degraded tasks.
35
+ *
36
+ * ## Conflict Detection Rules
37
+ *
38
+ * Two tasks conflict if:
39
+ * - They touch the **same file**
40
+ * - One task touches a **parent directory** of a file the other task touches
41
+ * (e.g., `src/auth/` vs `src/auth/login.ts`)
42
+ * - A task touches a **global file** (affects all coders)
43
+ * - A task touches a **protected path** (security-sensitive areas)
44
+ *
45
+ * ## Path Normalization
46
+ *
47
+ * All paths are normalized to POSIX-style (forward slashes, no trailing slash)
48
+ * before conflict detection. This ensures consistent behavior across platforms.
49
+ */
50
+ import type { LeanTurboConfig } from '../../config/schema';
51
+ import type { LeanTurboCounters, LeanTurboDegradedTask, LeanTurboLane } from './state';
52
+ export { GLOBAL_FILES_LIST, isGlobalFile, isPathSafe, isProtectedPath, normalizePath, PROTECTED_PATTERNS_LIST, pathsConflict, readTaskScopes, } from './conflicts';
53
+ /**
54
+ * A single task within a plan phase.
55
+ * Matches the structure stored in .swarm/plan.json.
56
+ */
57
+ export interface PlanTask {
58
+ id: string;
59
+ description: string;
60
+ status: 'pending' | 'in_progress' | 'completed' | 'blocked';
61
+ depends?: string[];
62
+ files_touched?: string[];
63
+ }
64
+ /**
65
+ * A phase within a plan, containing multiple tasks.
66
+ */
67
+ export interface PlanPhase {
68
+ id: number;
69
+ name: string;
70
+ tasks: PlanTask[];
71
+ }
72
+ /**
73
+ * The complete lane plan produced by `planLeanTurboLanes`.
74
+ * Describes how phase tasks are partitioned into parallel lanes.
75
+ */
76
+ export interface LeanTurboLanePlan {
77
+ /** The phase number this plan covers */
78
+ phase: number;
79
+ /** Unique identifier for this lane plan (planId from run state) */
80
+ planId: string;
81
+ /** The computed parallel lanes */
82
+ lanes: LeanTurboLane[];
83
+ /** Tasks that were degraded (risk conditions detected) */
84
+ degradedTasks: LeanTurboDegradedTask[];
85
+ /** Tasks that were serialized (conflicts resolved by ordering) */
86
+ serializedTasks: string[];
87
+ /** Human-readable summary when all tasks are degraded */
88
+ degradationSummary?: string;
89
+ /** Execution counters for this planning run */
90
+ counters: LeanTurboCounters;
91
+ /** Map of taskId -> array of dependency taskIds that are in other lanes.
92
+ * The runner must serialize execution of these tasks until the referenced
93
+ * dependencies complete. */
94
+ crossLaneDependencies: Record<string, string[]>;
95
+ }
96
+ /**
97
+ * Partition phase tasks into parallel lanes based on file-scope conflicts.
98
+ *
99
+ * This is the main entry point for Lean Turbo lane planning. It:
100
+ * 1. Extracts tasks for the specified phase
101
+ * 2. Resolves file scopes for each task
102
+ * 3. Detects conflicts between tasks
103
+ * 4. Assigns non-conflicting tasks to parallel lanes
104
+ * 5. Serializes or degrades conflicting tasks based on config
105
+ *
106
+ * @param directory - Project root directory
107
+ * @param phaseNumber - Phase number to plan
108
+ * @param plan - The full plan object (from .swarm/plan.json)
109
+ * @param config - Lean Turbo configuration
110
+ * @param scopes - Optional pre-loaded scopes map (taskId -> file paths)
111
+ * @returns Complete lane plan with lanes, degraded tasks, and counters
112
+ */
113
+ export declare function planLeanTurboLanes(directory: string, phaseNumber: number, plan: {
114
+ phases: PlanPhase[];
115
+ }, config: LeanTurboConfig, scopes?: Record<string, string[]>): LeanTurboLanePlan;
@@ -0,0 +1,124 @@
1
+ import { type LaneEvidence, listLaneEvidence, readPhaseEvidence } from './evidence';
2
+ import { readPersisted } from './state';
3
+ /**
4
+ * Configuration options for phase reviewer dispatch.
5
+ */
6
+ export interface LeanTurboPhaseReviewerConfig {
7
+ /**
8
+ * Override the reviewer agent name.
9
+ * Default: derived from `generatedAgentNames` via `{swarmId}_reviewer` pattern
10
+ * when a swarm has multiple reviewers, or `reviewer` for the default swarm.
11
+ */
12
+ reviewerAgent?: string;
13
+ /**
14
+ * Timeout in milliseconds for the reviewer dispatch.
15
+ * Default: no timeout (reviewer is awaited indefinitely).
16
+ */
17
+ timeoutMs?: number;
18
+ /**
19
+ * Require a diff summary in the compiled review package.
20
+ * When true, the package must include an `integratedDiffSummary` field.
21
+ * Default: false.
22
+ */
23
+ requireDiffSummary?: boolean;
24
+ }
25
+ /**
26
+ * Result of a phase reviewer dispatch.
27
+ */
28
+ export interface PhaseReviewerResult {
29
+ /** Reviewer verdict */
30
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED';
31
+ /** Human-readable reason for the verdict */
32
+ reason?: string;
33
+ /** Path to the persisted reviewer evidence file */
34
+ evidencePath: string;
35
+ }
36
+ /**
37
+ * Resolves the default reviewer agent name from the generated agent names.
38
+ *
39
+ * Uses the `{swarmId}_reviewer` pattern for named swarms and bare `reviewer`
40
+ * for the default swarm. Follows the same suffix-based resolution used by
41
+ * `getCanonicalAgentRole` so that arbitrary swarm prefixes are handled correctly.
42
+ */
43
+ declare function resolveDefaultReviewerAgent(generatedAgentNames: string[]): string;
44
+ /**
45
+ * Compiles a structured review package from lane and phase evidence.
46
+ */
47
+ interface ReviewPackage {
48
+ phase: number;
49
+ sessionID: string;
50
+ laneSummaries: Array<{
51
+ laneId: string;
52
+ taskIds: string[];
53
+ files: string[];
54
+ status: LaneEvidence['status'];
55
+ agent?: string;
56
+ }>;
57
+ filesChanged: string[];
58
+ testResults: {
59
+ totalLanes: number;
60
+ completedLanes: number;
61
+ failedLanes: number;
62
+ };
63
+ buildStatus: 'unknown' | 'passed' | 'failed';
64
+ degradationSummary: {
65
+ totalDegraded: number;
66
+ resolvedDegraded: number;
67
+ pendingDegraded: number;
68
+ };
69
+ integratedDiffSummary?: string;
70
+ }
71
+ declare function compileReviewPackage(directory: string, phase: number, sessionID: string, requireDiffSummary: boolean): Promise<ReviewPackage>;
72
+ /**
73
+ * Parses a reviewer verdict from the agent's text response.
74
+ *
75
+ * Looks for a verdict marker line: `VERDICT: APPROVED`, `VERDICT: NEEDS_REVISION`,
76
+ * or `VERDICT: REJECTED` (case-insensitive). Returns null if no marker is found.
77
+ *
78
+ * The optional reason is extracted from a `REASON:` marker line that follows
79
+ * the verdict marker on a subsequent line.
80
+ */
81
+ declare function parseReviewerVerdict(responseText: string): {
82
+ verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED';
83
+ reason?: string;
84
+ } | null;
85
+ /**
86
+ * Writes the reviewer verdict to the evidence file.
87
+ * Uses atomic write (temp file + rename) to prevent partial-file artifacts.
88
+ */
89
+ declare function writeReviewerEvidence(directory: string, phase: number, verdict: 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED', reason?: string): Promise<string>;
90
+ /**
91
+ * Test-only dependency-injection seam.
92
+ * Allows tests to intercept reviewer dispatch without mock.module leakage.
93
+ */
94
+ export declare const _internals: {
95
+ compileReviewPackage: typeof compileReviewPackage;
96
+ parseReviewerVerdict: typeof parseReviewerVerdict;
97
+ writeReviewerEvidence: typeof writeReviewerEvidence;
98
+ dispatchReviewerAgent: (directory: string, pkg: ReviewPackage, agentName: string, timeoutMs: number) => Promise<string>;
99
+ resolveDefaultReviewerAgent: typeof resolveDefaultReviewerAgent;
100
+ listLaneEvidence: typeof listLaneEvidence;
101
+ readPhaseEvidence: typeof readPhaseEvidence;
102
+ readPersisted: typeof readPersisted | null;
103
+ };
104
+ /**
105
+ * Dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase.
106
+ *
107
+ * Steps:
108
+ * 1. Read all lane evidence from `.swarm/evidence/{phase}/lean-turbo/`
109
+ * 2. Read phase evidence from `.swarm/evidence/{phase}/lean-turbo/lean-turbo-phase.json`
110
+ * 3. Compile a combined review package
111
+ * 4. Dispatch a read-only reviewer agent (tools: write=false, edit=false, patch=false)
112
+ * 5. Parse the verdict from the agent's response
113
+ * 6. Write the verdict to `.swarm/evidence/{phase}/lean-turbo-reviewer.json`
114
+ * 7. Return the result
115
+ *
116
+ * @param directory - Project root directory
117
+ * @param phase - Phase number being reviewed
118
+ * @param sessionID - Lean Turbo session ID
119
+ * @param config - Optional configuration overrides
120
+ * @returns PhaseReviewerResult with verdict, optional reason, and evidence path
121
+ * @throws Error if dispatch fails or response cannot be parsed (fail-closed)
122
+ */
123
+ export declare function dispatchPhaseReviewer(directory: string, phase: number, sessionID: string, config?: LeanTurboPhaseReviewerConfig): Promise<PhaseReviewerResult>;
124
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Risk Classification for Lean Turbo Tasks.
3
+ *
4
+ * This module provides risk assessment for tasks based on their file scopes,
5
+ * determining whether tasks can execute in parallel or must be serialized/degraded.
6
+ *
7
+ * ## Risk Categories
8
+ *
9
+ * - **normal**: Regular scoped files that can be parallelized
10
+ * - **global**: Tasks touching global files (affects all coders) → always degraded
11
+ * - **protected**: Tasks touching protected paths → degraded or serialized based on config
12
+ * - **no-scope**: Tasks without declared scope when `require_declared_scope` is true → serialized
13
+ * - **invalid-scope**: Tasks with invalid scope entries → serialized
14
+ */
15
+ import type { LeanTurboConfig } from '../../config/schema';
16
+ /**
17
+ * Risk category classification for a task.
18
+ */
19
+ export type TaskRiskCategory = 'normal' | 'global' | 'protected' | 'no-scope' | 'invalid-scope';
20
+ /**
21
+ * Result of risk assessment for a task.
22
+ */
23
+ export interface TaskRiskAssessment {
24
+ /** The risk category */
25
+ category: TaskRiskCategory;
26
+ /** Human-readable reason for the classification (undefined for 'normal') */
27
+ reason?: string;
28
+ /** Files that contributed to the risk assessment */
29
+ files: string[];
30
+ }
31
+ /**
32
+ * Assess the risk category of a task based on its file scope.
33
+ *
34
+ * Classification priority (first match wins):
35
+ * 1. Global files → 'global' (always degraded)
36
+ * 2. Protected paths → 'protected' (degraded if degrade_on_risk, else serialized)
37
+ * 3. Invalid scope entries → 'invalid-scope' (serialized)
38
+ * 4. No declared scope (when required) → 'no-scope' (serialized)
39
+ * 5. Otherwise → 'normal'
40
+ *
41
+ * @param files - The task's file scope (already validated and normalized)
42
+ * @param hasDeclaredScope - Whether the task has an explicit declared scope
43
+ * @param hasInvalidScope - Whether the scope contains invalid/unsafe entries
44
+ * @param config - Lean Turbo configuration
45
+ * @returns Risk assessment with category, reason, and contributing files
46
+ */
47
+ export declare function assessTaskRisk(files: string[], hasDeclaredScope: boolean, hasInvalidScope: boolean, config: LeanTurboConfig): TaskRiskAssessment;