opencode-swarm 7.173.1 → 7.175.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 (112) hide show
  1. package/.opencode/skills/swarm-pr-review/references/findings-persistence-contract.md +37 -0
  2. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  3. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  4. package/dist/agents/critic.d.ts +44 -2
  5. package/dist/background/pending-delegations.d.ts +10 -0
  6. package/dist/background/pr-review-contract.d.ts +27 -0
  7. package/dist/background/stage-b-gates.d.ts +29 -0
  8. package/dist/background/status-artifact.d.ts +24 -1
  9. package/dist/cli/{coder-settlement-kxxmd9jt.js → coder-settlement-f2n9yp7a.js} +11 -11
  10. package/dist/cli/{config-doctor-nzcya5zr.js → config-doctor-zcyz614n.js} +2 -2
  11. package/dist/cli/{core-s9a9kmcc.js → core-jar8cmzf.js} +3 -3
  12. package/dist/cli/{curation-policy-tx4kb30e.js → curation-policy-e5p147bb.js} +5 -5
  13. package/dist/cli/{curator-jkp8558s.js → curator-3xfz7wdp.js} +36 -36
  14. package/dist/cli/{curator-drift-047n8fjw.js → curator-drift-x3tt8apf.js} +4 -4
  15. package/dist/cli/curator-llm-factory-rc7cqtx8.js +72 -0
  16. package/dist/cli/{evidence-summary-service-ek50h5b3.js → evidence-summary-service-bpe04ngj.js} +15 -15
  17. package/dist/cli/{gate-evidence-8dk50ten.js → gate-evidence-pyzzafp3.js} +6 -6
  18. package/dist/cli/guardrail-explain-ncrw7k8h.js +73 -0
  19. package/dist/cli/{guardrail-log-hq5xpm7g.js → guardrail-log-nn2t8xyd.js} +7 -7
  20. package/dist/cli/{guardrail-reset-gttz1y0h.js → guardrail-reset-3c3c7e5e.js} +36 -36
  21. package/dist/cli/{hive-promoter-44p7ng87.js → hive-promoter-xfbabpnm.js} +36 -36
  22. package/dist/cli/{index-53c0ajk4.js → index-20q20gpd.js} +1 -1
  23. package/dist/cli/{index-m51cmzxt.js → index-2dv07mw2.js} +1 -1
  24. package/dist/cli/{index-fnx0jzf7.js → index-2xwavnbg.js} +1 -1
  25. package/dist/cli/{index-62pcs7jg.js → index-4rm5saxs.js} +3 -3
  26. package/dist/cli/{index-za1kvsa0.js → index-5t71wd7j.js} +2 -2
  27. package/dist/cli/{index-dktpzjy9.js → index-6tbnev6y.js} +1 -1
  28. package/dist/cli/{index-1xfxzjq9.js → index-6yqszgky.js} +2 -2
  29. package/dist/cli/{index-pynk60z5.js → index-8bbhh3kx.js} +8 -8
  30. package/dist/cli/{index-bsnpv4xd.js → index-8tn4yx8b.js} +2 -2
  31. package/dist/cli/{index-mt8pbzda.js → index-96hz14wr.js} +12 -12
  32. package/dist/cli/{index-z35ynvj4.js → index-98r0bh1c.js} +1 -1
  33. package/dist/cli/{index-psb9rxt8.js → index-9gpe25nr.js} +5 -5
  34. package/dist/cli/{index-wf3s2t1t.js → index-ar3ve24w.js} +3005 -2328
  35. package/dist/cli/{index-dx9pz5n6.js → index-bmk77mpq.js} +7 -7
  36. package/dist/cli/{index-ndvgkxpf.js → index-c60t3sw6.js} +2 -2
  37. package/dist/cli/{index-43dmpa9w.js → index-cpgh76bk.js} +2 -2
  38. package/dist/cli/{index-evf5r7bk.js → index-czhbsgdh.js} +1 -1
  39. package/dist/cli/{index-j0vvq8se.js → index-d0wq7paf.js} +7 -7
  40. package/dist/cli/{index-cm0339fe.js → index-ddvva9fn.js} +4 -4
  41. package/dist/cli/{index-mjqjbq94.js → index-fzvh6trw.js} +11 -11
  42. package/dist/cli/{index-pjw95rxm.js → index-gtej1br8.js} +65 -10
  43. package/dist/cli/{index-c5nrcde1.js → index-hdwdapp6.js} +38 -38
  44. package/dist/cli/{index-m53v442a.js → index-hej0z0sm.js} +36 -36
  45. package/dist/cli/{index-r93ptj7j.js → index-hqmr21qx.js} +19 -1
  46. package/dist/cli/{index-18b9snn6.js → index-j1yd2gbz.js} +6 -6
  47. package/dist/cli/{index-kdyvk541.js → index-jgkva4r4.js} +2 -2
  48. package/dist/cli/{index-0dfhahxm.js → index-jj09bfnn.js} +2 -2
  49. package/dist/cli/{index-hhws1xkc.js → index-jn3m9s61.js} +1 -1
  50. package/dist/cli/{index-wr4m11x4.js → index-kj7h2yfv.js} +1 -1
  51. package/dist/cli/{index-6z404f7y.js → index-m6bsy0jb.js} +4 -4
  52. package/dist/cli/{index-90qbc4rp.js → index-mat5rawf.js} +11 -3
  53. package/dist/cli/{index-samx6zgc.js → index-n5jac8z9.js} +1 -1
  54. package/dist/cli/{index-r8g2meas.js → index-nr96hbpy.js} +5 -3
  55. package/dist/cli/{index-yeehyat1.js → index-ppb5krpy.js} +2 -2
  56. package/dist/cli/{index-jmn35na4.js → index-qz6ee73z.js} +3 -3
  57. package/dist/cli/{index-7gkdxs00.js → index-tr9jz898.js} +7 -7
  58. package/dist/cli/{index-yzwb6ja4.js → index-vqjkr1kd.js} +1 -1
  59. package/dist/cli/{index-p36b6t7w.js → index-vt9a5rbg.js} +16 -9
  60. package/dist/cli/{index-vwnd2szd.js → index-yk3es7m2.js} +22 -13
  61. package/dist/cli/{index-gwtb07gc.js → index-zpygn1tn.js} +3 -3
  62. package/dist/cli/{index-gwz9p53s.js → index-zz40vfbz.js} +2 -2
  63. package/dist/cli/index.js +37 -37
  64. package/dist/cli/{knowledge-escalator-ttp4x29h.js → knowledge-escalator-2zjpwg0q.js} +12 -12
  65. package/dist/cli/{knowledge-events-dx9mjgqb.js → knowledge-events-gp2ckzqm.js} +10 -10
  66. package/dist/cli/{knowledge-link-f7bhq7cx.js → knowledge-link-s77cyqxk.js} +4 -4
  67. package/dist/cli/{knowledge-store-6sq9rxma.js → knowledge-store-kd88k067.js} +5 -5
  68. package/dist/cli/{knowledge-validator-h49dkw2z.js → knowledge-validator-22t16mba.js} +7 -7
  69. package/dist/cli/{mcp-kd7w2572.js → mcp-1fjc89yp.js} +1 -1
  70. package/dist/cli/{pending-delegations-n4qyymj2.js → pending-delegations-k4hfqz12.js} +11 -11
  71. package/dist/cli/{pr-subscriptions-n8vkm5mv.js → pr-subscriptions-8g6w41vz.js} +11 -11
  72. package/dist/cli/{pr-workflow-gate-j67jhtzt.js → pr-workflow-gate-kb3e709n.js} +42 -36
  73. package/dist/cli/{runner-58k70bnr.js → runner-nzppg2ky.js} +5 -5
  74. package/dist/cli/{scan-cursor-sz8ncpw2.js → scan-cursor-erm49azh.js} +6 -6
  75. package/dist/cli/{schema-70c0yw8p.js → schema-kts10txe.js} +5 -1
  76. package/dist/cli/{scope-persistence-0dzyv0vt.js → scope-persistence-krnvsmsz.js} +14 -14
  77. package/dist/cli/{server-njmemwbm.js → server-9bqh036q.js} +36 -36
  78. package/dist/cli/{skill-generator-kf5yqmvk.js → skill-generator-7q75h2kr.js} +14 -14
  79. package/dist/cli/{snapshot-coordination-init-ezf5xqy2.js → snapshot-coordination-init-bw9mn21x.js} +36 -36
  80. package/dist/cli/{telemetry-zed80n86.js → telemetry-7bk8ps5p.js} +1 -1
  81. package/dist/cli/{workspace-snapshot-62be4368.js → workspace-snapshot-6aw002e8.js} +3 -3
  82. package/dist/cli/{worktree-collision-ownership-fe176vyv.js → worktree-collision-ownership-ajagwzh8.js} +12 -12
  83. package/dist/cli/{worktree-isolation-c0b1h3f1.js → worktree-isolation-rmqp04fx.js} +36 -36
  84. package/dist/commands/registry.d.ts +1 -1
  85. package/dist/config/index.d.ts +2 -2
  86. package/dist/config/schema.d.ts +22 -8
  87. package/dist/events/core-events.d.ts +2 -0
  88. package/dist/evidence/task-gate-requirements.d.ts +24 -0
  89. package/dist/gate-evidence.d.ts +12 -0
  90. package/dist/hooks/pr-workflow-gate.d.ts +28 -0
  91. package/dist/index.d.ts +8 -0
  92. package/dist/index.js +501 -488
  93. package/dist/parallel/review-router.d.ts +8 -2
  94. package/dist/pr-review/completion.d.ts +2 -1
  95. package/dist/pr-review/finding-policy.d.ts +194 -0
  96. package/dist/pr-review/types.d.ts +8 -0
  97. package/dist/review/routing-enforcement.d.ts +163 -0
  98. package/dist/session/snapshot-writer.d.ts +2 -0
  99. package/dist/state.d.ts +28 -0
  100. package/dist/tools/complete-pr-workflow.d.ts +2 -1
  101. package/dist/tools/dispatch-lanes.d.ts +29 -0
  102. package/dist/tools/tool-metadata.d.ts +16 -16
  103. package/dist/tools/update-task-status.d.ts +0 -10
  104. package/dist/tools/write-pr-review-artifact.d.ts +7 -0
  105. package/dist/workflow/coder-settlement.d.ts +7 -0
  106. package/dist/workflow/recovery-invocation.d.ts +35 -0
  107. package/dist/workflow/stage-a-repair.d.ts +17 -0
  108. package/dist/workflow/task-recovery-status.d.ts +61 -0
  109. package/opencode-swarm.schema.json +11 -0
  110. package/package.json +2 -1
  111. package/dist/cli/curator-llm-factory-dza1qtwr.js +0 -72
  112. package/dist/cli/guardrail-explain-s29vngen.js +0 -73
@@ -16,10 +16,16 @@ export interface SemanticRoutingResult {
16
16
  routing: ReviewRouting;
17
17
  classifications: ClassifiedChange[];
18
18
  }
19
+ /**
20
+ * One bounded budget covers the complete route computation. The AST helper
21
+ * has its own per-file guard, but that alone does not bound the surrounding
22
+ * complexity scan plus the sequence of git/AST operations.
23
+ */
24
+ export declare const REVIEW_ROUTING_TIMEOUT_MS = 10000;
19
25
  /**
20
26
  * Compute complexity metrics for a set of files
21
27
  */
22
- export declare function computeComplexity(directory: string, changedFiles: string[]): Promise<ComplexityMetrics>;
28
+ export declare function computeComplexity(directory: string, changedFiles: string[], deadline?: number): Promise<ComplexityMetrics>;
23
29
  /**
24
30
  * Determine review routing based on complexity
25
31
  */
@@ -28,7 +34,7 @@ export declare function routeReview(metrics: ComplexityMetrics): ReviewRouting;
28
34
  * Attempt AST-based semantic classification of changes.
29
35
  * Returns null if AST analysis is unavailable, times out, or exceeds bounds.
30
36
  */
31
- export declare function computeSemanticClassifications(directory: string, changedFiles: string[]): Promise<ClassifiedChange[] | null>;
37
+ export declare function computeSemanticClassifications(directory: string, changedFiles: string[], deadline?: number): Promise<ClassifiedChange[] | null>;
32
38
  /**
33
39
  * Route review based on semantic classifications.
34
40
  * High-risk categories (GUARD_REMOVED, SIGNATURE_CHANGE, API_CHANGE,
@@ -39,6 +39,7 @@ import { z } from 'zod';
39
39
  import { type LaneOutputArtifact } from '../background/lane-output-store.js';
40
40
  import { type BackgroundDelegationRecord, type BackgroundDelegationResult, type BackgroundDelegationWorkflowLaneFailureClass } from '../background/pending-delegations.js';
41
41
  import { type PrReviewBaseDimensionId, type PrReviewResultReceipt } from '../background/pr-review-contract.js';
42
+ import { type FinalPolicyFinding } from './finding-policy.js';
42
43
  /** Declared lane shape of a base dispatch, as the settlement reads it. */
43
44
  export interface PrReviewCompletionLane {
44
45
  laneId: string;
@@ -202,7 +203,7 @@ export type PrReviewReportVerdict = (typeof PR_REVIEW_REPORT_VERDICTS)[number];
202
203
  * is a forced INCOMPLETE operational report. Neither may ever APPROVE or
203
204
  * claim a full review.
204
205
  */
205
- export declare function allowedPrReviewReportVerdicts(kind: PrReviewTerminalCoverageKind): readonly PrReviewReportVerdict[];
206
+ export declare function allowedPrReviewReportVerdicts(kind: PrReviewTerminalCoverageKind, findings?: ReadonlyArray<FinalPolicyFinding>): readonly PrReviewReportVerdict[];
206
207
  export interface PrReviewTerminalCoverageSettlement {
207
208
  kind: PrReviewTerminalCoverageKind;
208
209
  coveredDimensions: PrReviewBaseDimensionId[];
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Versioned PR-review finding synthesis and terminal projection policy.
3
+ *
4
+ * This is the policy boundary between authenticated lane output and the
5
+ * terminal report/handoff projections. It intentionally has no dependency on
6
+ * the workflow gate so it can be exercised in isolation and reused by every
7
+ * settlement caller.
8
+ */
9
+ import { type CoreEventCoverage } from '../events/core-events.js';
10
+ export declare const FINDING_POLICY_VERSION: 1;
11
+ export type FindingSeverity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO' | 'NONE';
12
+ export type FindingAction = 'route_to_reviewer' | 'route_to_critic' | 'report' | 'suppress_with_reason' | 'handoff_to_feedback';
13
+ export type FindingStatus = 'UNRESOLVED' | 'CONFIRMED' | 'DISPROVED' | 'NON_ACTIONABLE' | 'PRE_EXISTING';
14
+ export type ConfidenceLabel = 'LOW' | 'MEDIUM' | 'HIGH';
15
+ export type CriticOutcome = 'UPHELD' | 'DOWNGRADED' | 'DISPROVED' | 'NEEDS_MORE_EVIDENCE';
16
+ export interface ParsedCandidateConfidence {
17
+ label: ConfidenceLabel;
18
+ score: number;
19
+ }
20
+ /** Parse the version-1 categorical confidence vocabulary. */
21
+ export declare function parseCandidateConfidence(value: unknown): ParsedCandidateConfidence;
22
+ export interface FindingProvenance {
23
+ identity: string;
24
+ lane?: string;
25
+ [key: string]: unknown;
26
+ }
27
+ export interface FindingLocation {
28
+ file: string;
29
+ line: number;
30
+ lineEnd?: number;
31
+ }
32
+ export interface FindingCandidateInput {
33
+ finding: string;
34
+ severity: FindingSeverity | string;
35
+ action?: FindingAction | string;
36
+ confidence: ConfidenceLabel | string;
37
+ category: string;
38
+ location: FindingLocation;
39
+ provenance: FindingProvenance | FindingProvenance[];
40
+ status?: FindingStatus | string;
41
+ [key: string]: unknown;
42
+ }
43
+ export interface SynthesizedFinding {
44
+ id: string;
45
+ finding: string;
46
+ severity: FindingSeverity;
47
+ action: FindingAction;
48
+ confidence: ConfidenceLabel;
49
+ confidenceScore: number;
50
+ agreementCount: number;
51
+ category: string;
52
+ location: FindingLocation;
53
+ provenance: FindingProvenance[];
54
+ status: FindingStatus;
55
+ sourceFindingIds: string[];
56
+ }
57
+ export interface CriticSettlementRecord {
58
+ findingId: string;
59
+ terminal: boolean;
60
+ status: CriticOutcome;
61
+ finalFinding: CriticSettlementInput['finding'];
62
+ handoffFindingIds: string[];
63
+ }
64
+ export interface FindingSynthesis {
65
+ policyVersion: typeof FINDING_POLICY_VERSION;
66
+ findings: SynthesizedFinding[];
67
+ diagnostics: string[];
68
+ criticSettlements?: CriticSettlementRecord[];
69
+ }
70
+ /**
71
+ * Keep synthesis bounded independently of the JSONL byte ceiling. A review
72
+ * result may carry at most this many findings, and synthesis uses the same
73
+ * bound so a caller cannot turn the pairwise agreement pass into an
74
+ * unbounded CPU cost (issue #2491 F-017).
75
+ */
76
+ export declare const MAX_FINDING_SYNTHESIS_CANDIDATES = 256;
77
+ /** Synthesize semantically equivalent findings and independent agreement. */
78
+ export declare function synthesizePrReviewFindings(input: {
79
+ candidates: FindingCandidateInput[];
80
+ }): FindingSynthesis;
81
+ export interface FinalPolicyFinding {
82
+ id?: string;
83
+ severity: FindingSeverity | string;
84
+ action: FindingAction | string;
85
+ status: FindingStatus | string;
86
+ [key: string]: unknown;
87
+ }
88
+ export interface FinalPolicyCoverage {
89
+ kind: 'base' | 'micro';
90
+ quality: 'complete' | 'degraded' | 'partial' | 'none' | string;
91
+ provenance?: 'valid' | 'invalid' | string;
92
+ disclosed?: boolean;
93
+ }
94
+ export interface FinalFindingPolicyInput {
95
+ policyVersion: number;
96
+ finalStatus: 'COMPLETE' | 'INCOMPLETE' | string;
97
+ coverage: FinalPolicyCoverage;
98
+ findings: FinalPolicyFinding[];
99
+ }
100
+ export interface FinalFindingPolicyProjection {
101
+ policyVersion: typeof FINDING_POLICY_VERSION;
102
+ /** The registered terminal report vocabulary; no internal-only verdicts. */
103
+ permittedVerdicts: Array<'APPROVE' | 'REQUEST_CHANGES' | 'INCOMPLETE'>;
104
+ coverageDisposition: 'COMPLETE' | 'PARTIAL' | 'DEGRADED_DISCLOSED' | 'INVALID_PROVENANCE' | 'NO_COVERAGE';
105
+ blockingFindingIds: string[];
106
+ }
107
+ /** Project final finding status/action and coverage through policy v1. */
108
+ export declare function evaluateFinalFindingPolicy(input: FinalFindingPolicyInput): FinalFindingPolicyProjection;
109
+ export interface CriticSettlementInput {
110
+ finding: {
111
+ id: string;
112
+ severity: FindingSeverity | string;
113
+ action: FindingAction | string;
114
+ status: FindingStatus | string;
115
+ };
116
+ outcome: CriticOutcome;
117
+ finalSeverity?: FindingSeverity | string;
118
+ finalAction?: FindingAction | string;
119
+ }
120
+ export interface CriticSettlement {
121
+ terminal: boolean;
122
+ status: CriticOutcome;
123
+ finalFinding: CriticSettlementInput['finding'];
124
+ handoffFindingIds: string[];
125
+ }
126
+ /** Apply critic settlement; NEEDS_MORE_EVIDENCE remains explicitly open. */
127
+ export declare function settleCriticFinding(input: CriticSettlementInput): CriticSettlement;
128
+ /**
129
+ * Derive the feedback handoff set from the final ledger projection only.
130
+ * Earlier reviewer/candidate records and caller-supplied IDs are deliberately
131
+ * ignored; this keeps handoff membership tied to terminal CONFIRMED records.
132
+ */
133
+ export declare function deriveFeedbackHandoffFindingIds(records: ReadonlyArray<{
134
+ finding_id: string;
135
+ status: string;
136
+ next_action: string;
137
+ }>): string[];
138
+ export interface TerminalReceipt {
139
+ id: string;
140
+ valid: boolean;
141
+ }
142
+ export interface TerminalReadinessInput {
143
+ baseReceipt: TerminalReceipt | null;
144
+ reviewerReceipts: TerminalReceipt[];
145
+ criticReceipt: TerminalReceipt | null;
146
+ coverage: FinalPolicyCoverage;
147
+ council: {
148
+ enabled: boolean;
149
+ receipt?: TerminalReceipt | null;
150
+ };
151
+ criticSettlements?: Array<{
152
+ terminal: boolean;
153
+ status?: CriticOutcome;
154
+ }>;
155
+ }
156
+ export interface TerminalReadiness {
157
+ ready: boolean;
158
+ blockers: string[];
159
+ degradedCoverageDisclosed: boolean;
160
+ }
161
+ export declare function assessTerminalReadiness(input: TerminalReadinessInput): TerminalReadiness;
162
+ export interface ReviewOutcomeRouteReceipt {
163
+ kind: string;
164
+ version: number;
165
+ sessionId: string;
166
+ taskId: string;
167
+ [key: string]: unknown;
168
+ }
169
+ export interface PersistReviewOutcomeInput {
170
+ projectRoot: string;
171
+ routeReceipt: ReviewOutcomeRouteReceipt;
172
+ synthesis: Record<string, unknown>;
173
+ }
174
+ export interface PersistReviewOutcomeResult {
175
+ persisted: true;
176
+ evidencePath: string;
177
+ eventsPath: string;
178
+ }
179
+ /** Digest the exact JSON projection carried by finding-policy evidence. */
180
+ export declare function reviewOutcomeSynthesisDigest(synthesis: unknown): string;
181
+ /** Persist policy evidence plus canonical, identity-only audit events. */
182
+ export declare function persistReviewOutcome(input: PersistReviewOutcomeInput): Promise<PersistReviewOutcomeResult>;
183
+ export interface ReadReviewOutcomeInput {
184
+ projectRoot: string;
185
+ sessionId: string;
186
+ taskId: string;
187
+ }
188
+ export interface ReadReviewOutcomeResult {
189
+ evidence: Record<string, unknown>;
190
+ events: Array<Record<string, unknown>>;
191
+ /** Coverage of the bounded core-event audit window used for this read. */
192
+ auditCoverage: CoreEventCoverage;
193
+ }
194
+ export declare function readReviewOutcome(input: ReadReviewOutcomeInput): Promise<ReadReviewOutcomeResult>;
@@ -155,6 +155,14 @@ export type PrReviewEvent = {
155
155
  semanticEnvelopeDigest: string;
156
156
  outcome: 'CLEAN' | 'FINDINGS' | 'INCOMPLETE';
157
157
  existingReceiptDigest?: string | undefined;
158
+ /**
159
+ * Provenance marker on the reducer event. Currently no consumer reads
160
+ * this field — the durable provenance record is the receipt-side
161
+ * `submittedBy` / `submittedByParentSessionId` (see
162
+ * `PrReviewResultReceiptSchema`). Kept for ledger parity with the
163
+ * receipt.
164
+ */
165
+ submittedBy?: 'workflow_parent' | undefined;
158
166
  } | {
159
167
  type: 'circuit_advance_requested';
160
168
  nowMs: number;
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Versioned semantic-review routing receipts (issue #2491).
3
+ *
4
+ * A route is an authorization input for Stage B, not an advisory message. A
5
+ * successful receipt names the exact reviewer/test-engineer identities that
6
+ * owe an independent completion. Router failures have a separate typed
7
+ * receipt; an absent or malformed success receipt never receives fail-open
8
+ * treatment.
9
+ */
10
+ import { z } from 'zod';
11
+ export declare const REVIEW_ROUTE_RECEIPT_VERSION: 1;
12
+ export declare const ReviewRouteReceiptSchema: z.ZodObject<{
13
+ kind: z.ZodLiteral<"review_route_receipt">;
14
+ version: z.ZodLiteral<1>;
15
+ sessionId: z.ZodString;
16
+ taskId: z.ZodString;
17
+ complexity: z.ZodString;
18
+ semanticRisk: z.ZodString;
19
+ required: z.ZodObject<{
20
+ reviewers: z.ZodNumber;
21
+ testEngineers: z.ZodNumber;
22
+ }, z.core.$strip>;
23
+ identities: z.ZodObject<{
24
+ reviewers: z.ZodArray<z.ZodString>;
25
+ testEngineers: z.ZodArray<z.ZodString>;
26
+ }, z.core.$strip>;
27
+ slots: z.ZodOptional<z.ZodObject<{
28
+ reviewers: z.ZodArray<z.ZodString>;
29
+ testEngineers: z.ZodArray<z.ZodString>;
30
+ }, z.core.$strip>>;
31
+ createdAt: z.ZodOptional<z.ZodString>;
32
+ mac: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strict>;
34
+ export declare const ReviewRouteRouterErrorReceiptSchema: z.ZodObject<{
35
+ kind: z.ZodLiteral<"review_route_router_error">;
36
+ version: z.ZodLiteral<1>;
37
+ code: z.ZodEnum<{
38
+ NO_CHANGED_FILES: "NO_CHANGED_FILES";
39
+ ROUTER_UNAVAILABLE: "ROUTER_UNAVAILABLE";
40
+ ROUTER_FAILED: "ROUTER_FAILED";
41
+ }>;
42
+ failOpen: z.ZodLiteral<true>;
43
+ sessionId: z.ZodOptional<z.ZodString>;
44
+ taskId: z.ZodOptional<z.ZodString>;
45
+ detail: z.ZodOptional<z.ZodString>;
46
+ createdAt: z.ZodOptional<z.ZodString>;
47
+ mac: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strict>;
49
+ declare const ReviewRoutePendingReceiptSchema: z.ZodObject<{
50
+ kind: z.ZodLiteral<"review_route_pending">;
51
+ version: z.ZodLiteral<1>;
52
+ sessionId: z.ZodString;
53
+ taskId: z.ZodString;
54
+ createdAt: z.ZodOptional<z.ZodString>;
55
+ mac: z.ZodOptional<z.ZodString>;
56
+ }, z.core.$strict>;
57
+ export type ReviewRouteReceipt = z.infer<typeof ReviewRouteReceiptSchema>;
58
+ export type ReviewRouteRouterErrorReceipt = z.infer<typeof ReviewRouteRouterErrorReceiptSchema>;
59
+ export type ReviewRouteRecord = ReviewRouteReceipt | ReviewRouteRouterErrorReceipt | ReviewRoutePendingReceipt;
60
+ export type ReviewRoutePendingReceipt = z.infer<typeof ReviewRoutePendingReceiptSchema>;
61
+ export interface BuildReviewRouteReceiptArgs {
62
+ sessionId: string;
63
+ taskId: string;
64
+ complexity: string;
65
+ semanticRisk: string;
66
+ requiredReviewers: readonly string[];
67
+ requiredTestEngineers: readonly string[];
68
+ /** Optional explicit slot IDs. If absent they are deterministic by index. */
69
+ reviewerSlots?: readonly string[];
70
+ testEngineerSlots?: readonly string[];
71
+ createdAt?: string;
72
+ }
73
+ export interface ReviewRouteEvidence {
74
+ role: 'reviewer' | 'test_engineer';
75
+ identity: string;
76
+ /** Optional exact route binding fields used by live Stage-B callers. */
77
+ sessionId?: string;
78
+ taskId?: string;
79
+ slotId?: string;
80
+ callId?: string;
81
+ childSessionId?: string;
82
+ generation?: number;
83
+ }
84
+ export interface EnforceReviewRouteReceiptArgs {
85
+ enforcementEnabled: boolean;
86
+ routeReceipt: unknown;
87
+ receipts: readonly ReviewRouteEvidence[];
88
+ sessionId?: string;
89
+ taskId?: string;
90
+ /** Live callers must provide the full call/child/generation-bound tuple. */
91
+ requireEvidenceBindings?: boolean;
92
+ /** Current live dispatch tuple, when a caller is authorizing one completion. */
93
+ expectedDispatch?: Pick<ReviewRouteEvidence, 'role' | 'identity' | 'callId' | 'childSessionId' | 'generation'>;
94
+ /**
95
+ * When false, authorize the current exact dispatch tuple without requiring
96
+ * every route slot. Callers use this admission check before publishing the
97
+ * completion; the full-route check remains the advancement barrier.
98
+ */
99
+ requireCompleteEvidence?: boolean;
100
+ }
101
+ export interface EnforceReviewRouteReceiptResult {
102
+ canAdvance: boolean;
103
+ mode?: 'enforced' | 'disabled' | 'fail_open' | 'legacy_unrouted';
104
+ reason?: string;
105
+ routerFailure?: ReviewRouteRouterErrorReceipt['code'];
106
+ }
107
+ export declare function buildReviewRouteReceipt(input: BuildReviewRouteReceiptArgs): ReviewRouteReceipt;
108
+ export declare function buildReviewRouteRouterError(input: {
109
+ code: ReviewRouteRouterErrorReceipt['code'];
110
+ sessionId: string;
111
+ taskId: string;
112
+ detail?: string;
113
+ createdAt?: string;
114
+ }): ReviewRouteRouterErrorReceipt;
115
+ export declare function buildReviewRoutePending(input: {
116
+ sessionId: string;
117
+ taskId: string;
118
+ createdAt?: string;
119
+ }): ReviewRoutePendingReceipt;
120
+ export declare function persistReviewRouteReceipt(input: {
121
+ projectRoot: string;
122
+ receipt: ReviewRouteRecord;
123
+ }): Promise<{
124
+ persisted: true;
125
+ path: string;
126
+ }>;
127
+ export declare function readReviewRouteReceipt(input: {
128
+ projectRoot: string;
129
+ sessionId: string;
130
+ taskId: string;
131
+ }): Promise<ReviewRouteRecord | null>;
132
+ /** Synchronous twin for the existing synchronous reviewer-gate predicate. */
133
+ export declare function readReviewRouteReceiptSync(input: {
134
+ projectRoot: string;
135
+ sessionId: string;
136
+ taskId: string;
137
+ }): ReviewRouteRecord | null;
138
+ /**
139
+ * Authorize Stage-B advancement from the exact route receipt. The explicit
140
+ * router error is the only enabled fail-open branch; malformed/absent records
141
+ * fail closed. Optional identity fields on evidence are checked when present
142
+ * so old callers can migrate without fabricating bindings.
143
+ */
144
+ export declare function enforceReviewRouteReceipt(input: EnforceReviewRouteReceiptArgs): EnforceReviewRouteReceiptResult;
145
+ export declare function routeReceiptPathForTask(directory: string, sessionId: string, taskId: string): string;
146
+ /**
147
+ * Read and enforce one task's persisted route using the synchronous gate
148
+ * contract. A missing receipt is intentionally a hard failure for new work;
149
+ * callers that have positively identified pre-version legacy state may opt
150
+ * into the disclosed one-release compatibility result.
151
+ */
152
+ export declare function enforcePersistedReviewRouteReceipt(input: {
153
+ projectRoot: string;
154
+ sessionId: string;
155
+ taskId: string;
156
+ receipts: readonly ReviewRouteEvidence[];
157
+ enforcementEnabled: boolean;
158
+ legacyUnrouted?: boolean;
159
+ requireEvidenceBindings?: boolean;
160
+ expectedDispatch?: EnforceReviewRouteReceiptArgs['expectedDispatch'];
161
+ requireCompleteEvidence?: boolean;
162
+ }): EnforceReviewRouteReceiptResult;
163
+ export {};
@@ -83,6 +83,8 @@ export interface SerializedAgentSession {
83
83
  sessionRehydratedAt?: number;
84
84
  /** Stage B completion tracking: per-task set of completed Stage B agents. Optional for backward compat with old snapshots. */
85
85
  stageBCompletion?: Record<string, string[]>;
86
+ /** v1 review-routing requirement markers, persisted so missing receipts fail closed after restart. */
87
+ stageBRouteRequiredTasks?: string[];
86
88
  /** Session-scoped concurrency override for max_concurrent_tasks (Issue #761) */
87
89
  maxConcurrencyOverride?: number;
88
90
  /** Session-level auto-proceed override (Phase 1) */
package/dist/state.d.ts CHANGED
@@ -13,6 +13,7 @@ import { type EnvironmentProfile } from './environment/profile.js';
13
13
  import { type TaskWorkflowMetadata } from './gate-evidence';
14
14
  import type { EscalationTracker } from './prm/escalation.js';
15
15
  import type { PatternMatch } from './prm/types.js';
16
+ import type { ReviewRouteEvidence } from './review/routing-enforcement.js';
16
17
  import { AgentRunContext } from './state/agent-run-context.js';
17
18
  export { AgentRunContext } from './state/agent-run-context.js';
18
19
  /**
@@ -244,6 +245,13 @@ export interface AgentSessionState {
244
245
  * Always populated — Stage B is unconditionally parallel.
245
246
  */
246
247
  stageBCompletion?: Map<string, Set<'reviewer' | 'test_engineer'>>;
248
+ /** Exact route-bound Stage B evidence; role presence alone is not authoritative. */
249
+ stageBRouteEvidence?: Map<string, ReviewRouteEvidence[]>;
250
+ /**
251
+ * Tasks dispatched through v1 review routing. This positive marker prevents a
252
+ * missing route receipt from being mistaken for pre-v1 legacy state.
253
+ */
254
+ stageBRouteRequiredTasks?: Set<string>;
247
255
  /** v6.71+ Council mode: per-task council verdict, recorded by delegation-gate when submit_council_verdicts resolves. */
248
256
  taskCouncilApproved?: Map<string, {
249
257
  verdict: 'APPROVE' | 'REJECT' | 'CONCERNS';
@@ -1262,6 +1270,26 @@ export declare function getTaskState(session: AgentSessionState, taskId: string)
1262
1270
  * @param agent - Which Stage B agent completed ('reviewer' or 'test_engineer')
1263
1271
  */
1264
1272
  export declare function recordStageBCompletion(session: AgentSessionState, taskId: string, agent: 'reviewer' | 'test_engineer'): void;
1273
+ /**
1274
+ * Reserve a bounded in-memory route-evidence slot and return a rollback for
1275
+ * callers that still have to publish the corresponding durable evidence.
1276
+ *
1277
+ * The reservation remains visible while the caller awaits its durable write,
1278
+ * which prevents concurrent completions from oversubscribing the 32-entry
1279
+ * projection. If that write fails, invoking the rollback restores the exact
1280
+ * prior slot (or removes a newly-added slot), so a retry is not poisoned by a
1281
+ * failed attempt.
1282
+ */
1283
+ export declare function reserveStageBRouteEvidence(session: AgentSessionState, taskId: string, evidence: ReviewRouteEvidence): (() => void) | null;
1284
+ export declare function recordStageBRouteEvidence(session: AgentSessionState, taskId: string, evidence: ReviewRouteEvidence): boolean;
1285
+ export declare function getStageBRouteEvidence(session: AgentSessionState, taskId: string): ReviewRouteEvidence[];
1286
+ export declare function clearStageBRouteEvidence(session: AgentSessionState, taskId: string): void;
1287
+ /** Mark a task as requiring the versioned review-route receipt contract. */
1288
+ export declare function markStageBRouteRequired(session: AgentSessionState, taskId: string): void;
1289
+ /** True only for a task positively marked as v1-routed in this session. */
1290
+ export declare function isStageBRouteRequired(session: AgentSessionState, taskId: string): boolean;
1291
+ /** Clear the route requirement after a task reaches its terminal state. */
1292
+ export declare function clearStageBRouteRequired(session: AgentSessionState, taskId: string): void;
1265
1293
  /**
1266
1294
  * PR 2 Stage B barrier: returns true iff both 'reviewer' and 'test_engineer' have
1267
1295
  * been recorded for the given task in this session.
@@ -1,4 +1,4 @@
1
- import { completePrWorkflow, readPrReviewTerminalCoverageForReport, readPrWorkflowGateState, settlePresumedStalePrWorkflowLanes } from '../hooks/pr-workflow-gate.js';
1
+ import { completePrWorkflow, readPrReviewFinalFindingPolicyForReport, readPrReviewTerminalCoverageForReport, readPrWorkflowGateState, settlePresumedStalePrWorkflowLanes } from '../hooks/pr-workflow-gate.js';
2
2
  import { createSwarmTool } from './create-tool.js';
3
3
  import { listPendingPrWorkflowCheckoutRestores } from './prepare-pr-workflow-checkout.js';
4
4
  export declare function executeCompletePrWorkflow(args: unknown, directory: string, context?: {
@@ -10,5 +10,6 @@ export declare const _internals: {
10
10
  listPendingPrWorkflowCheckoutRestores: typeof listPendingPrWorkflowCheckoutRestores;
11
11
  readPrWorkflowGateState: typeof readPrWorkflowGateState;
12
12
  readPrReviewTerminalCoverageForReport: typeof readPrReviewTerminalCoverageForReport;
13
+ readPrReviewFinalFindingPolicyForReport: typeof readPrReviewFinalFindingPolicyForReport;
13
14
  settlePresumedStalePrWorkflowLanes: typeof settlePresumedStalePrWorkflowLanes;
14
15
  };
@@ -364,6 +364,7 @@ export declare const _internals: {
364
364
  };
365
365
  export declare const _test_exports: {
366
366
  validatePrReviewMicroDispatch: typeof validatePrReviewMicroDispatch;
367
+ resolveCollectExpectedWorkflowIdentity: typeof resolveCollectExpectedWorkflowIdentity;
367
368
  applyCommonPrompt: typeof applyCommonPrompt;
368
369
  applyExplorerFormatSuffix: typeof applyExplorerFormatSuffix;
369
370
  applyPrWorkflowPromptContract: typeof applyPrWorkflowPromptContract;
@@ -526,6 +527,34 @@ type LaneDiagnostics = Map<string, Set<string>>;
526
527
  */
527
528
  declare function assembleCollectionDiagnostics(hostTimeouts: ReadonlySet<string>, settleFailureLogs: LaneDiagnostics, collectionResourceFailures: LaneDiagnostics): string[];
528
529
  declare function addLaneDiagnostic(diagnostics: LaneDiagnostics, laneLabel: string, message: string): void;
530
+ /**
531
+ * Issue #2585 live-proof defect (found by AC11 case-01 against the real host,
532
+ * present byte-identically on main 3ea01cbc7): the collect-time discovery
533
+ * validation built its `expected` WITHOUT the workflow identity triple, so
534
+ * `validateExactStructuredReceiptCoverage` rejected EVERY child-submitted
535
+ * structured receipt with `missing live workflow instance/revision/base
536
+ * identity` — deterministic, prompt-insensitive, unrepairable from the
537
+ * orchestrator — and every base dimension settled as a contract failure
538
+ * (NO_COVERAGE → forced INCOMPLETE). The dispatch-side record carries the
539
+ * instance (jobId binding) and revision (workflowGeneration); the live gate
540
+ * state of the dispatching parent carries the merge-base. Derive the triple
541
+ * from those two authoritative sources instead of leaving it undefined.
542
+ *
543
+ * Pure: exported through `_test_exports` for the regression test. Returns
544
+ * undefined whenever any leg is missing — callers then keep the validator's
545
+ * explicit missing-identity rejection (today's behavior) rather than guessing.
546
+ */
547
+ /** Minimal structural slice of the PR_REVIEW gate state the identity needs. */
548
+ interface PrReviewCollectParentStateSlice {
549
+ mode?: string;
550
+ workflowInstanceId?: string;
551
+ prReviewBaseSha?: string;
552
+ }
553
+ export declare function resolveCollectExpectedWorkflowIdentity(record: BackgroundDelegationRecord, parentState: PrReviewCollectParentStateSlice | null): {
554
+ workflowInstanceId: string;
555
+ workflowRevision: number;
556
+ baseSha: string;
557
+ } | undefined;
529
558
  declare function consumePrReviewReceiptAppendFailureLog(loggedFailures: Set<string>, parentSessionId: string, correlationId: string): boolean;
530
559
  declare function startAsyncLanePrompt(args: {
531
560
  session: SessionOps;