opencode-plugin-flow 5.0.0 → 5.1.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  One short entry per release, written for users deciding whether to upgrade.
4
4
 
5
+ ## [5.1.0] - 2026-07-18
6
+
7
+ Causal evidence and review truth lore makes long-running Flow work compact,
8
+ retry-safe, and auditable without putting raw evidence into model-visible state:
9
+
10
+ - Session v3 gains additive revision and snapshot identity, an authenticated
11
+ mutation ledger, and guarded idempotent operations. Existing sparse v3
12
+ sessions hydrate to the canonical revision-zero state without a migration.
13
+ - `flow_status` now separates compact routing, complete execution, bounded
14
+ detail, reviewer, and revision-delta projections. Mutations return receipts
15
+ instead of the full session; the checked-in six-feature fixture preserves all
16
+ transition decisions while reducing measured stateful response bytes by
17
+ 93.95%, with the unavailable historical same-corpus gate reported as such.
18
+ - Validation evidence is bound to a deterministic source digest. Optional raw
19
+ output lives in an owner-only, hash-addressed `.flow/evidence` store with
20
+ strict size, permission, symlink, integrity, and no-clobber checks; ordinary
21
+ state records only typed digest and length references, and concurrent
22
+ publishers converge on the same ignore policy across platforms.
23
+ - Review executions are durable independently of completion, with stable
24
+ attempt and logical-pass identity, typed finding fingerprints, append-only
25
+ failed-to-passed retry history, contradiction checks, and explicit final-
26
+ feature chronology. Malformed optional orchestration telemetry can no longer
27
+ erase valid core review evidence.
28
+ - A provider-neutral sanitized replay oracle derives terminal and retry truth
29
+ from event causality, rejects private or unsafe fixture content, and keeps
30
+ host facts, Flow-ledger claims, supplied observations, and replay-derived
31
+ facts distinct. New `replay:report` and `transport:report` commands expose the
32
+ reproducible local reports.
33
+ - Manager and reviewer guidance now routes from compact status to exact
34
+ execution context, records every observed review attempt, performs final
35
+ feature validation and reviews in economy order, and closes only from a
36
+ refreshed compact projection.
37
+
5
38
  ## [5.0.0] - 2026-07-18
6
39
 
7
40
  TypeScript 7 hard-cutover lore makes Flow 5 smaller, stricter, and easier to
package/README.md CHANGED
@@ -17,7 +17,7 @@ Full project documentation is available in the
17
17
  ## Quick start
18
18
 
19
19
  ```bash
20
- opencode plugin opencode-plugin-flow@5.0.0 --global --force
20
+ opencode plugin opencode-plugin-flow@5.1.0 --global --force
21
21
  ```
22
22
 
23
23
  Start or restart OpenCode, then give Flow a goal:
@@ -41,21 +41,34 @@ restart.
41
41
  features: rate-limit-middleware, per-route-config, docs-update
42
42
  (you approve the plan)
43
43
  flow_plan_approve plan locked — features are now immutable
44
- flow_run_start feature: rate-limit-middleware
44
+ flow_run_start mutation acknowledged
45
+ flow_status view: execution, feature: rate-limit-middleware
45
46
  ... implementation, tests ...
46
47
  flow_feature_complete
47
48
  validationRun: "bun test tests/middleware.test.ts" passed
48
49
  featureReviewDepth: standard
49
50
  featureReview: passed
50
- flow_run_start feature: per-route-config
51
+ flow_run_start mutation acknowledged
52
+ flow_status view: execution, feature: per-route-config
51
53
  ...
52
54
 
53
55
  > /flow-status
54
56
  status: ok
55
- workflowData.session.status: running, 1/3 features completed
56
- nextAction: complete the feature under workflowData.session.activeFeature
57
+ workflowData.projection.view: compact
58
+ workflowData.projection.status: running
59
+ workflowData.projection.progress: { completed: 1, total: 3, remaining: 2 }
60
+
61
+ > /flow-run
62
+ flow_status view: execution
63
+ workflowData.projection: full active-feature scope
57
64
  ```
58
65
 
66
+ `flow_status` returns workflow state under `workflowData.projection`: compact is
67
+ routing-only, execution is the full active-feature working scope, detail is
68
+ diagnostic, and reviewer is narrow assignment context. State-changing tools
69
+ return `workflowData.receipt` acknowledgements; a receipt never replaces a
70
+ fresh status projection.
71
+
59
72
  Interrupt at any point; `/flow-run` resumes the next approved feature. On the
60
73
  final feature Flow requires broad project-level validation and a final review
61
74
  whose depth matches the approved plan before the session can close as
@@ -154,8 +167,8 @@ For broad implementation, the manager records whether work stayed serial,
154
167
  used exact-path candidate workers, used isolated worktrees, ran a tournament, or
155
168
  skipped eligible candidates. Feature completion can carry bounded
156
169
  `orchestrationPasses` with candidate eligibility, decision, and structured
157
- factors; `flow_status` reports the aggregate under
158
- `workflowData.session.budget.orchestration`.
170
+ factors. Bounded projections report the relevant aggregate while full worker
171
+ handoffs remain outside `.flow/**`.
159
172
 
160
173
  ## Install details and legacy cleanup
161
174
 
@@ -169,7 +182,7 @@ or sync command is required. To preview recoverable migration of pristine v4
169
182
  global skill folders:
170
183
 
171
184
  ```bash
172
- npx -y opencode-plugin-flow@5.0.0 legacy-cleanup --dry-run
185
+ npx -y opencode-plugin-flow@5.1.0 legacy-cleanup --dry-run
173
186
  ```
174
187
 
175
188
  ## Development
@@ -1,19 +1,14 @@
1
1
  import { z } from "zod";
2
- import type { Feature, Session, SessionId } from "../domain/session.js";
3
- import { summarizeSession, type TransitionEnvironment } from "../domain/transitions.js";
2
+ import type { Session, SessionId } from "../domain/session.js";
3
+ import { mutationReceiptProjection, type TransitionEnvironment } from "../domain/transitions.js";
4
4
  import type { SessionRepository } from "./ports/session-repository.js";
5
- type StatusResponse = ReturnType<typeof summarizeSession>;
6
- type ActiveStatusResponse = Extract<StatusResponse, {
7
- workflowData: unknown;
8
- }>;
9
- type SessionWorkflowData = ActiveStatusResponse["workflowData"]["session"];
10
5
  type WorkflowData = {
11
- session?: SessionWorkflowData;
6
+ projection?: unknown;
7
+ receipt?: ReturnType<typeof mutationReceiptProjection>;
12
8
  failure?: {
13
9
  summary: string;
14
10
  recovery?: string;
15
11
  };
16
- startedFeature?: Feature;
17
12
  archive?: {
18
13
  sessionId: SessionId;
19
14
  closure: Session["closure"];
@@ -27,6 +22,7 @@ type ResponseContext = {
27
22
  statusSummary?: string;
28
23
  nextAction?: string;
29
24
  dataNote?: string;
25
+ warnings?: string[];
30
26
  workflowData?: WorkflowData;
31
27
  recovery?: string;
32
28
  };
@@ -35,7 +31,7 @@ export type FlowResponse = ResponseContext & {
35
31
  summary: string;
36
32
  };
37
33
  export type FlowService = {
38
- status(): Promise<FlowResponse>;
34
+ status(input?: unknown): Promise<FlowResponse>;
39
35
  planSave(input: unknown): Promise<FlowResponse>;
40
36
  planApprove(): Promise<FlowResponse>;
41
37
  runStart(input: unknown): Promise<FlowResponse>;
@@ -43,6 +39,31 @@ export type FlowService = {
43
39
  featureReset(input: unknown): Promise<FlowResponse>;
44
40
  sessionClose(input: unknown): Promise<FlowResponse>;
45
41
  };
42
+ export declare const FlowStatusSchema: z.ZodUnion<readonly [z.ZodDiscriminatedUnion<[z.ZodObject<{
43
+ view: z.ZodLiteral<"reviewer">;
44
+ featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
45
+ packetHash: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
46
+ evidenceRefs: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>>;
47
+ expectedRevision: z.ZodNumber;
48
+ expectedSnapshotId: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
49
+ reviewKind: z.ZodLiteral<"feature">;
50
+ }, z.core.$strict>, z.ZodObject<{
51
+ view: z.ZodLiteral<"reviewer">;
52
+ featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
53
+ packetHash: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
54
+ evidenceRefs: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>>;
55
+ expectedRevision: z.ZodNumber;
56
+ expectedSnapshotId: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
57
+ reviewKind: z.ZodLiteral<"final">;
58
+ }, z.core.$strict>], "reviewKind">, z.ZodObject<{
59
+ view: z.ZodLiteral<"execution">;
60
+ }, z.core.$strict>, z.ZodObject<{
61
+ view: z.ZodLiteral<"detail">;
62
+ sinceRevision: z.ZodOptional<z.ZodNumber>;
63
+ }, z.core.$strict>, z.ZodObject<{
64
+ view: z.ZodDefault<z.ZodLiteral<"compact">>;
65
+ sinceRevision: z.ZodOptional<z.ZodNumber>;
66
+ }, z.core.$strict>]>;
46
67
  export declare const FlowPlanSaveSchema: z.ZodObject<{
47
68
  goal: z.ZodOptional<z.ZodString>;
48
69
  plan: z.ZodOptional<z.ZodObject<{
@@ -79,9 +100,15 @@ export declare const FlowRunStartSchema: z.ZodObject<{
79
100
  featureId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>>;
80
101
  }, z.core.$strict>;
81
102
  export declare const FlowFeatureResetSchema: z.ZodObject<{
103
+ operationId: z.ZodString;
104
+ expectedRevision: z.ZodNumber;
105
+ expectedSnapshotId: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
82
106
  featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
83
107
  }, z.core.$strict>;
84
108
  export declare const FlowSessionCloseSchema: z.ZodObject<{
109
+ operationId: z.ZodString;
110
+ expectedRevision: z.ZodNumber;
111
+ expectedSnapshotId: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
85
112
  kind: z.ZodEnum<{
86
113
  abandoned: "abandoned";
87
114
  completed: "completed";
@@ -89,23 +116,136 @@ export declare const FlowSessionCloseSchema: z.ZodObject<{
89
116
  }>;
90
117
  summary: z.ZodOptional<z.ZodString>;
91
118
  }, z.core.$strict>;
92
- export declare const FlowFeatureCompleteToolSchema: z.ZodObject<{
93
- status: z.ZodEnum<{
94
- needs_input: "needs_input";
95
- ok: "ok";
96
- }>;
119
+ export declare const FlowFeatureCompleteToolSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
120
+ operationId: z.ZodString;
121
+ expectedRevision: z.ZodNumber;
122
+ expectedSnapshotId: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
97
123
  featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
98
124
  summary: z.ZodString;
99
- artifactsChanged: z.ZodOptional<z.ZodArray<z.ZodObject<{
125
+ status: z.ZodLiteral<"ok">;
126
+ artifactsChanged: z.ZodDefault<z.ZodArray<z.ZodObject<{
100
127
  path: z.ZodString;
101
128
  }, z.core.$strict>>>;
102
- validationRun: z.ZodOptional<z.ZodArray<z.ZodObject<{
129
+ validations: z.ZodArray<z.ZodObject<{
130
+ startedAt: z.ZodString;
131
+ completedAt: z.ZodString;
103
132
  command: z.ZodString;
133
+ summary: z.ZodString;
134
+ exitCode: z.ZodNumber;
135
+ outputDigest: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
136
+ artifactRef: z.ZodOptional<z.ZodObject<{
137
+ kind: z.ZodLiteral<"restricted_evidence_v1">;
138
+ digest: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
139
+ byteLength: z.ZodNumber;
140
+ }, z.core.$strict>>;
141
+ environmentKeys: z.ZodArray<z.ZodString>;
142
+ }, z.core.$strict>>;
143
+ validationScope: z.ZodEnum<{
144
+ broad: "broad";
145
+ targeted: "targeted";
146
+ }>;
147
+ featureReviewDepth: z.ZodEnum<{
148
+ detailed: "detailed";
149
+ quick: "quick";
150
+ standard: "standard";
151
+ }>;
152
+ featureReview: z.ZodObject<{
104
153
  status: z.ZodEnum<{
105
154
  failed: "failed";
106
155
  passed: "passed";
107
156
  }>;
108
157
  summary: z.ZodString;
158
+ blockingFindings: z.ZodDefault<z.ZodArray<z.ZodObject<{
159
+ summary: z.ZodString;
160
+ severity: z.ZodDefault<z.ZodEnum<{
161
+ advisory: "advisory";
162
+ blocking: "blocking";
163
+ }>>;
164
+ }, z.core.$strict>>>;
165
+ }, z.core.$strict>;
166
+ finalReview: z.ZodOptional<z.ZodObject<{
167
+ status: z.ZodEnum<{
168
+ failed: "failed";
169
+ passed: "passed";
170
+ }>;
171
+ summary: z.ZodString;
172
+ blockingFindings: z.ZodDefault<z.ZodArray<z.ZodObject<{
173
+ summary: z.ZodString;
174
+ severity: z.ZodDefault<z.ZodEnum<{
175
+ advisory: "advisory";
176
+ blocking: "blocking";
177
+ }>>;
178
+ }, z.core.$strict>>>;
179
+ reviewDepth: z.ZodEnum<{
180
+ broad: "broad";
181
+ detailed: "detailed";
182
+ }>;
183
+ }, z.core.$strict>>;
184
+ reviewExecutions: z.ZodArray<z.ZodObject<{
185
+ attemptId: z.ZodString;
186
+ logicalPassId: z.ZodString;
187
+ featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
188
+ reviewKind: z.ZodEnum<{
189
+ feature: "feature";
190
+ final: "final";
191
+ }>;
192
+ reviewSnapshotId: z.ZodPipe<z.ZodString, z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>>;
193
+ verdict: z.ZodEnum<{
194
+ failed: "failed";
195
+ passed: "passed";
196
+ }>;
197
+ startedAt: z.ZodString;
198
+ completedAt: z.ZodString;
199
+ terminalDisposition: z.ZodEnum<{
200
+ observed_unsubmitted: "observed_unsubmitted";
201
+ submitted: "submitted";
202
+ }>;
203
+ findings: z.ZodArray<z.ZodObject<{
204
+ taxonomy: z.ZodEnum<{
205
+ advisory: "advisory";
206
+ evidence_gap: "evidence_gap";
207
+ implementation_defect: "implementation_defect";
208
+ regression_coverage_gap: "regression_coverage_gap";
209
+ }>;
210
+ subject: z.ZodString;
211
+ requirementOrRisk: z.ZodString;
212
+ evidenceLocator: z.ZodString;
213
+ summary: z.ZodString;
214
+ severity: z.ZodEnum<{
215
+ advisory: "advisory";
216
+ blocking: "blocking";
217
+ }>;
218
+ }, z.core.$strict>>;
219
+ }, z.core.$strict>>;
220
+ outcome: z.ZodOptional<z.ZodObject<{
221
+ kind: z.ZodLiteral<"completed">;
222
+ summary: z.ZodOptional<z.ZodString>;
223
+ resolutionHint: z.ZodOptional<z.ZodString>;
224
+ }, z.core.$strict>>;
225
+ orchestrationPasses: z.ZodOptional<z.ZodUnknown>;
226
+ }, z.core.$strict>, z.ZodObject<{
227
+ operationId: z.ZodString;
228
+ expectedRevision: z.ZodNumber;
229
+ expectedSnapshotId: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
230
+ featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
231
+ summary: z.ZodString;
232
+ status: z.ZodLiteral<"needs_input">;
233
+ artifactsChanged: z.ZodDefault<z.ZodArray<z.ZodObject<{
234
+ path: z.ZodString;
235
+ }, z.core.$strict>>>;
236
+ validations: z.ZodDefault<z.ZodArray<z.ZodObject<{
237
+ startedAt: z.ZodString;
238
+ completedAt: z.ZodString;
239
+ command: z.ZodString;
240
+ summary: z.ZodString;
241
+ exitCode: z.ZodNumber;
242
+ outputDigest: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
243
+ artifactRef: z.ZodOptional<z.ZodObject<{
244
+ kind: z.ZodLiteral<"restricted_evidence_v1">;
245
+ digest: z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>;
246
+ byteLength: z.ZodNumber;
247
+ }, z.core.$strict>>;
248
+ environmentKeys: z.ZodArray<z.ZodString>;
109
249
  }, z.core.$strict>>>;
110
250
  validationScope: z.ZodOptional<z.ZodEnum<{
111
251
  broad: "broad";
@@ -148,11 +288,43 @@ export declare const FlowFeatureCompleteToolSchema: z.ZodObject<{
148
288
  detailed: "detailed";
149
289
  }>;
150
290
  }, z.core.$strict>>;
151
- outcome: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
152
- kind: z.ZodLiteral<"completed">;
153
- summary: z.ZodOptional<z.ZodString>;
154
- resolutionHint: z.ZodOptional<z.ZodString>;
155
- }, z.core.$strict>, z.ZodObject<{
291
+ reviewExecutions: z.ZodDefault<z.ZodArray<z.ZodObject<{
292
+ attemptId: z.ZodString;
293
+ logicalPassId: z.ZodString;
294
+ featureId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../domain/session.js").FeatureId, string>>;
295
+ reviewKind: z.ZodEnum<{
296
+ feature: "feature";
297
+ final: "final";
298
+ }>;
299
+ reviewSnapshotId: z.ZodPipe<z.ZodString, z.ZodPipe<z.ZodString, z.ZodTransform<`sha256:${string}`, string>>>;
300
+ verdict: z.ZodEnum<{
301
+ failed: "failed";
302
+ passed: "passed";
303
+ }>;
304
+ startedAt: z.ZodString;
305
+ completedAt: z.ZodString;
306
+ terminalDisposition: z.ZodEnum<{
307
+ observed_unsubmitted: "observed_unsubmitted";
308
+ submitted: "submitted";
309
+ }>;
310
+ findings: z.ZodArray<z.ZodObject<{
311
+ taxonomy: z.ZodEnum<{
312
+ advisory: "advisory";
313
+ evidence_gap: "evidence_gap";
314
+ implementation_defect: "implementation_defect";
315
+ regression_coverage_gap: "regression_coverage_gap";
316
+ }>;
317
+ subject: z.ZodString;
318
+ requirementOrRisk: z.ZodString;
319
+ evidenceLocator: z.ZodString;
320
+ summary: z.ZodString;
321
+ severity: z.ZodEnum<{
322
+ advisory: "advisory";
323
+ blocking: "blocking";
324
+ }>;
325
+ }, z.core.$strict>>;
326
+ }, z.core.$strict>>>;
327
+ outcome: z.ZodObject<{
156
328
  kind: z.ZodEnum<{
157
329
  blocked: "blocked";
158
330
  needs_input: "needs_input";
@@ -160,84 +332,8 @@ export declare const FlowFeatureCompleteToolSchema: z.ZodObject<{
160
332
  }>;
161
333
  summary: z.ZodString;
162
334
  resolutionHint: z.ZodOptional<z.ZodString>;
163
- }, z.core.$strict>], "kind">>;
164
- orchestrationPasses: z.ZodOptional<z.ZodArray<z.ZodObject<{
165
- id: z.ZodString;
166
- kind: z.ZodEnum<{
167
- audit: "audit";
168
- candidate: "candidate";
169
- discovery: "discovery";
170
- "implementation-decision": "implementation-decision";
171
- review: "review";
172
- validation: "validation";
173
- verification: "verification";
174
- }>;
175
- decision: z.ZodOptional<z.ZodEnum<{
176
- "candidate-exact-path": "candidate-exact-path";
177
- "candidate-worktree": "candidate-worktree";
178
- parallel: "parallel";
179
- serial: "serial";
180
- skipped: "skipped";
181
- tournament: "tournament";
182
- }>>;
183
- decisionReason: z.ZodOptional<z.ZodString>;
184
- candidateEligibility: z.ZodDefault<z.ZodEnum<{
185
- eligible: "eligible";
186
- not_eligible: "not_eligible";
187
- unknown: "unknown";
188
- }>>;
189
- candidateDecision: z.ZodOptional<z.ZodEnum<{
190
- serial_required: "serial_required";
191
- skipped: "skipped";
192
- used: "used";
193
- }>>;
194
- decisionFactors: z.ZodDefault<z.ZodArray<z.ZodEnum<{
195
- independent_surface: "independent_surface";
196
- needs_manager_judgment: "needs_manager_judgment";
197
- overlapping_files: "overlapping_files";
198
- shared_state: "shared_state";
199
- small_slice: "small_slice";
200
- validation_available: "validation_available";
201
- }>>>;
202
- modes: z.ZodDefault<z.ZodArray<z.ZodEnum<{
203
- audit: "audit";
204
- "candidate-implementation": "candidate-implementation";
205
- evidence: "evidence";
206
- review: "review";
207
- validation: "validation";
208
- verifier: "verifier";
209
- }>>>;
210
- workerCount: z.ZodDefault<z.ZodNumber>;
211
- candidateWorkerCount: z.ZodDefault<z.ZodNumber>;
212
- verifierWorkerCount: z.ZodDefault<z.ZodNumber>;
213
- sliceIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
214
- dependsOn: z.ZodDefault<z.ZodArray<z.ZodString>>;
215
- writeScope: z.ZodDefault<z.ZodEnum<{
216
- "exact-path": "exact-path";
217
- "isolated-worktree": "isolated-worktree";
218
- "manager-serial": "manager-serial";
219
- mixed: "mixed";
220
- none: "none";
221
- }>>;
222
- handoffRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
223
- verificationStatus: z.ZodDefault<z.ZodEnum<{
224
- downgraded: "downgraded";
225
- failed: "failed";
226
- mixed: "mixed";
227
- "not-needed": "not-needed";
228
- passed: "passed";
229
- pending: "pending";
230
- }>>;
231
- outcome: z.ZodDefault<z.ZodEnum<{
232
- accepted: "accepted";
233
- modified: "modified";
234
- "not-covered": "not-covered";
235
- partial: "partial";
236
- rejected: "rejected";
237
- superseded: "superseded";
238
- }>>;
239
- synthesisRef: z.ZodOptional<z.ZodString>;
240
- }, z.core.$strict>>>;
241
- }, z.core.$strict>;
335
+ }, z.core.$strict>;
336
+ orchestrationPasses: z.ZodOptional<z.ZodUnknown>;
337
+ }, z.core.$strict>], "status">;
242
338
  export declare function createFlowService(repository: SessionRepository, environment: TransitionEnvironment): FlowService;
243
339
  export {};
@@ -0,0 +1,28 @@
1
+ import type { EvidenceArtifactRef } from "../../domain/session.js";
2
+ export declare const MAX_EVIDENCE_ARTIFACT_BYTES: number;
3
+ export type EvidenceArtifactDigest = `sha256:${string}`;
4
+ export type { EvidenceArtifactRef } from "../../domain/session.js";
5
+ export interface EvidenceArtifactStore {
6
+ publishEvidenceArtifact(bytes: Uint8Array): Promise<EvidenceArtifactRef>;
7
+ readEvidenceArtifact(ref: EvidenceArtifactRef): Promise<Uint8Array>;
8
+ }
9
+ export declare class InvalidEvidenceArtifactReferenceError extends Error {
10
+ readonly code = "FLOW_EVIDENCE_INVALID_REFERENCE";
11
+ constructor(message: string, options?: ErrorOptions);
12
+ }
13
+ export declare class EvidenceArtifactNotFoundError extends Error {
14
+ readonly code = "FLOW_EVIDENCE_NOT_FOUND";
15
+ constructor(message: string, options?: ErrorOptions);
16
+ }
17
+ export declare class EvidenceArtifactIntegrityError extends Error {
18
+ readonly code = "FLOW_EVIDENCE_INTEGRITY";
19
+ constructor(message: string, options?: ErrorOptions);
20
+ }
21
+ export declare class EvidenceArtifactCollisionError extends Error {
22
+ readonly code = "FLOW_EVIDENCE_COLLISION";
23
+ constructor(message: string, options?: ErrorOptions);
24
+ }
25
+ export declare class EvidenceArtifactTooLargeError extends Error {
26
+ readonly code = "FLOW_EVIDENCE_TOO_LARGE";
27
+ constructor(message: string, options?: ErrorOptions);
28
+ }
@@ -1,6 +1,13 @@
1
1
  import type { Session } from "../../domain/session.js";
2
- export type SessionTransaction = {
2
+ import type { EvidenceArtifactStore } from "./evidence-artifact-store.js";
3
+ import type { SourceIdentityProvider } from "./source-identity.js";
4
+ export declare class ArchivedSessionLookupError extends Error {
5
+ readonly code = "FLOW_ARCHIVE_LOOKUP_FAILED";
6
+ constructor(message: string, options?: ErrorOptions);
7
+ }
8
+ export type SessionTransaction = EvidenceArtifactStore & SourceIdentityProvider & {
3
9
  load(): Promise<Session | null>;
10
+ findArchivedByOperationId(operationId: string): Promise<Session | null>;
4
11
  save(session: Session): Promise<Session>;
5
12
  archiveAndClear(session: Session): Promise<void>;
6
13
  quarantineUnreadable(): Promise<string | null>;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Application port for the authoritative source/worktree identity boundary.
3
+ *
4
+ * The provider derives a canonical, deterministic digest of the workspace
5
+ * source state (the "A1 canonical source digest"). It is the single trusted
6
+ * producer of source identity used by the transactional completion boundary.
7
+ * Callers never assert source identity; Flow recomputes it and binds evidence
8
+ * to it. The source-v2 manifest is materialization-sensitive:
9
+ * an indexed sparse-checkout path absent from disk is distinct from the same
10
+ * path materialized in a dense worktree.
11
+ */
12
+ export type SourceDigest = `sha256:${string}`;
13
+ export type SourceIdentity = {
14
+ /** Canonical lowercase SHA-256 digest of the source state. */
15
+ readonly digest: SourceDigest;
16
+ /** Whether the digest was derived from a Git manifest or a full-tree walk. */
17
+ readonly mode: "git" | "non-git";
18
+ /** Number of source entries that contributed to the digest. */
19
+ readonly entryCount: number;
20
+ };
21
+ export interface SourceIdentityProvider {
22
+ /**
23
+ * Compute the canonical source digest for the workspace. Implementations
24
+ * must fail closed on unsafe symlinks, unreadable entries, resource limits,
25
+ * or a workspace mutation observed while the source is being measured.
26
+ */
27
+ computeSourceIdentity(): Promise<SourceIdentity>;
28
+ }
29
+ /**
30
+ * Base class for source-identity failures. The message never carries absolute
31
+ * paths, file contents, or command output; only a bounded, safe reason.
32
+ */
33
+ export declare class SourceIdentityError extends Error {
34
+ readonly code: string;
35
+ constructor(message: string, options?: ErrorOptions);
36
+ }
37
+ /** A symlink whose target escapes the workspace root or is absolute. */
38
+ export declare class SourceIdentityUnsafeSymlinkError extends SourceIdentityError {
39
+ readonly code = "FLOW_SOURCE_IDENTITY_UNSAFE_SYMLINK";
40
+ constructor(message: string, options?: ErrorOptions);
41
+ }
42
+ /** An entry that could not be read; measurement never silently skips state. */
43
+ export declare class SourceIdentityUnreadableError extends SourceIdentityError {
44
+ readonly code = "FLOW_SOURCE_IDENTITY_UNREADABLE";
45
+ constructor(message: string, options?: ErrorOptions);
46
+ }
47
+ /** The source exceeded the bounded file-count or byte budget. */
48
+ export declare class SourceIdentityOverflowError extends SourceIdentityError {
49
+ readonly code = "FLOW_SOURCE_IDENTITY_OVERFLOW";
50
+ constructor(message: string, options?: ErrorOptions);
51
+ }
52
+ /** The workspace changed while it was being measured. */
53
+ export declare class SourceIdentityRaceError extends SourceIdentityError {
54
+ readonly code = "FLOW_SOURCE_IDENTITY_RACE";
55
+ constructor(message: string, options?: ErrorOptions);
56
+ }
57
+ /** Git enumeration failed for a Git workspace. */
58
+ export declare class SourceIdentityGitError extends SourceIdentityError {
59
+ readonly code = "FLOW_SOURCE_IDENTITY_GIT";
60
+ constructor(message: string, options?: ErrorOptions);
61
+ }
@@ -0,0 +1,7 @@
1
+ export type CanonicalJsonValue = null | boolean | number | string | readonly CanonicalJsonValue[] | {
2
+ readonly [key: string]: CanonicalJsonValue;
3
+ };
4
+ /** Stable, whitespace-free JSON with recursively sorted object keys. */
5
+ export declare function canonicalizeReplayJson(value: CanonicalJsonValue): string;
6
+ export declare const canonicalizeJson: typeof canonicalizeReplayJson;
7
+ export declare const canonicalReplayJson: typeof canonicalizeReplayJson;