@smthrs/plan 1.0.0-rc.7 → 1.0.0-rc.9
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 +3 -1
- package/dist/cjs/Effects.d.ts +29 -11
- package/dist/cjs/Effects.d.ts.map +1 -1
- package/dist/cjs/Effects.js.map +2 -2
- package/dist/cjs/FileSet.d.ts +121 -51
- package/dist/cjs/FileSet.d.ts.map +1 -1
- package/dist/cjs/FileSet.js.map +2 -2
- package/dist/cjs/GraphBuildError.d.ts +2 -4
- package/dist/cjs/GraphBuildError.d.ts.map +1 -1
- package/dist/cjs/GraphBuildError.js.map +2 -2
- package/dist/cjs/KeyMaterial.d.ts +13 -8
- package/dist/cjs/KeyMaterial.d.ts.map +1 -1
- package/dist/cjs/KeyMaterial.js.map +2 -2
- package/dist/cjs/Plan.d.ts +72 -23
- package/dist/cjs/Plan.d.ts.map +1 -1
- package/dist/cjs/Plan.js +3 -0
- package/dist/cjs/Plan.js.map +2 -2
- package/dist/cjs/PlanDiff.d.ts +26 -7
- package/dist/cjs/PlanDiff.d.ts.map +1 -1
- package/dist/cjs/PlanDiff.js +29 -4
- package/dist/cjs/PlanDiff.js.map +2 -2
- package/dist/cjs/StepKey.d.ts +38 -17
- package/dist/cjs/StepKey.d.ts.map +1 -1
- package/dist/cjs/StepKey.js +24 -22
- package/dist/cjs/StepKey.js.map +2 -2
- package/dist/cjs/internal/node.d.ts.map +1 -1
- package/dist/esm/Effects.d.ts +29 -11
- package/dist/esm/Effects.d.ts.map +1 -1
- package/dist/esm/Effects.js +18 -7
- package/dist/esm/Effects.js.map +1 -1
- package/dist/esm/FileSet.d.ts +121 -51
- package/dist/esm/FileSet.d.ts.map +1 -1
- package/dist/esm/FileSet.js +97 -35
- package/dist/esm/FileSet.js.map +1 -1
- package/dist/esm/GraphBuildError.d.ts +2 -4
- package/dist/esm/GraphBuildError.d.ts.map +1 -1
- package/dist/esm/GraphBuildError.js +2 -3
- package/dist/esm/GraphBuildError.js.map +1 -1
- package/dist/esm/KeyMaterial.d.ts +13 -8
- package/dist/esm/KeyMaterial.d.ts.map +1 -1
- package/dist/esm/KeyMaterial.js +11 -4
- package/dist/esm/KeyMaterial.js.map +1 -1
- package/dist/esm/Plan.d.ts +72 -23
- package/dist/esm/Plan.d.ts.map +1 -1
- package/dist/esm/Plan.js +61 -16
- package/dist/esm/Plan.js.map +1 -1
- package/dist/esm/PlanDiff.d.ts +26 -7
- package/dist/esm/PlanDiff.d.ts.map +1 -1
- package/dist/esm/PlanDiff.js +55 -9
- package/dist/esm/PlanDiff.js.map +1 -1
- package/dist/esm/StepKey.d.ts +38 -17
- package/dist/esm/StepKey.d.ts.map +1 -1
- package/dist/esm/StepKey.js +41 -16
- package/dist/esm/StepKey.js.map +1 -1
- package/dist/esm/internal/node.d.ts.map +1 -1
- package/docs/README.md +3 -1
- package/docs/api.md +1 -1
- package/docs/guides/diff-two-plans.md +138 -74
- package/docs/installation.md +5 -1
- package/docs/quickstart.md +1 -1
- package/package.json +4 -4
- package/src/Effects.ts +29 -11
- package/src/FileSet.ts +121 -51
- package/src/GraphBuildError.ts +2 -4
- package/src/KeyMaterial.ts +13 -8
- package/src/Plan.ts +66 -23
- package/src/PlanDiff.ts +56 -11
- package/src/StepKey.ts +66 -40
package/dist/esm/Plan.d.ts
CHANGED
|
@@ -25,11 +25,15 @@ import * as StepKey from "./StepKey.ts";
|
|
|
25
25
|
* What a node does to the world, declared. Paths only — measuring them is
|
|
26
26
|
* run-time work, so a digest here would break the no-I/O law.
|
|
27
27
|
*
|
|
28
|
+
* Decoding fails with a `SchemaError` when a path is not workspace-relative.
|
|
29
|
+
* {@link compile} also refuses a node whose `removes` overlaps its `writes`
|
|
30
|
+
* with an `invalid_effects` {@link PlanError}.
|
|
31
|
+
*
|
|
28
32
|
* @since 0.1.0
|
|
29
33
|
* @category schemas
|
|
30
|
-
* @slop
|
|
31
34
|
*/
|
|
32
35
|
export declare const NodeEffects: Schema.Struct<{
|
|
36
|
+
/** Paths the node reads. A read orders the node after every writer of an overlapping path. */
|
|
33
37
|
readonly reads: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
|
|
34
38
|
readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
35
39
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
@@ -40,6 +44,7 @@ export declare const NodeEffects: Schema.Struct<{
|
|
|
40
44
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
41
45
|
}>]>>;
|
|
42
46
|
}>]>>;
|
|
47
|
+
/** Paths the node writes. Two writers of an overlapping path form a conflict. */
|
|
43
48
|
readonly writes: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
|
|
44
49
|
readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
45
50
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
@@ -60,6 +65,7 @@ export declare const NodeEffects: Schema.Struct<{
|
|
|
60
65
|
* conflict pass and the reader-after-writer pass see them as one set.
|
|
61
66
|
*/
|
|
62
67
|
readonly removes: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
68
|
+
/** How strictly the sandbox enforces these declarations. */
|
|
63
69
|
readonly boundaryMode: Schema.Literals<readonly ["hard", "expected"]>;
|
|
64
70
|
}>;
|
|
65
71
|
/**
|
|
@@ -67,15 +73,17 @@ export declare const NodeEffects: Schema.Struct<{
|
|
|
67
73
|
*
|
|
68
74
|
* @since 0.1.0
|
|
69
75
|
* @category models
|
|
70
|
-
* @slop
|
|
71
76
|
*/
|
|
72
77
|
export type NodeEffects = typeof NodeEffects.Type;
|
|
73
78
|
/**
|
|
74
|
-
* The plan-time
|
|
79
|
+
* The plan-time verdict for two writers of an overlapping path:
|
|
80
|
+
* `serialize` gives the later writer an ordering edge, `lane` records a lane
|
|
81
|
+
* annotation on both writers and adds no edge, and `fail` refuses the plan
|
|
82
|
+
* with `overlap_forbidden`. For a pair, `fail` dominates `lane`, which
|
|
83
|
+
* dominates `serialize`. The same schema as `Effects.ConflictStrategy`.
|
|
75
84
|
*
|
|
76
85
|
* @since 0.1.0
|
|
77
86
|
* @category schemas
|
|
78
|
-
* @slop
|
|
79
87
|
*/
|
|
80
88
|
export declare const PairStrategy: Schema.Literals<readonly ["serialize", "lane", "fail"]>;
|
|
81
89
|
/**
|
|
@@ -83,17 +91,16 @@ export declare const PairStrategy: Schema.Literals<readonly ["serialize", "lane"
|
|
|
83
91
|
*
|
|
84
92
|
* @since 0.1.0
|
|
85
93
|
* @category models
|
|
86
|
-
* @slop
|
|
87
94
|
*/
|
|
88
95
|
export type PairStrategy = typeof PairStrategy.Type;
|
|
89
96
|
/**
|
|
90
97
|
* The runtime half of a conflict annotation: what the scheduler
|
|
91
98
|
* does when the overlap the plan predicted actually bites, or when a
|
|
92
|
-
* scheduled node's inputs are invalidated under it.
|
|
99
|
+
* scheduled node's inputs are invalidated under it. For a pair,
|
|
100
|
+
* `stop-merge` dominates `delay-rebase`.
|
|
93
101
|
*
|
|
94
102
|
* @since 0.1.0
|
|
95
103
|
* @category schemas
|
|
96
|
-
* @slop
|
|
97
104
|
*/
|
|
98
105
|
export declare const RuntimeStrategy: Schema.Literals<readonly ["delay-rebase", "stop-merge"]>;
|
|
99
106
|
/**
|
|
@@ -101,16 +108,17 @@ export declare const RuntimeStrategy: Schema.Literals<readonly ["delay-rebase",
|
|
|
101
108
|
*
|
|
102
109
|
* @since 0.1.0
|
|
103
110
|
* @category models
|
|
104
|
-
* @slop
|
|
105
111
|
*/
|
|
106
112
|
export type RuntimeStrategy = typeof RuntimeStrategy.Type;
|
|
107
113
|
/**
|
|
108
114
|
* One resolved overlap between two writers that no dependency path already
|
|
109
115
|
* orders. Conflict is a property of the PAIR, not of one declaration.
|
|
110
116
|
*
|
|
117
|
+
* `with` names the other node, `paths` lists the overlapping declarations,
|
|
118
|
+
* and `strategy` and `runtime` are the verdicts resolved for the pair.
|
|
119
|
+
*
|
|
111
120
|
* @since 0.1.0
|
|
112
121
|
* @category schemas
|
|
113
|
-
* @slop
|
|
114
122
|
*/
|
|
115
123
|
export declare const ConflictAnnotation: Schema.Struct<{
|
|
116
124
|
readonly with: Schema.NonEmptyString;
|
|
@@ -123,7 +131,6 @@ export declare const ConflictAnnotation: Schema.Struct<{
|
|
|
123
131
|
*
|
|
124
132
|
* @since 0.1.0
|
|
125
133
|
* @category models
|
|
126
|
-
* @slop
|
|
127
134
|
*/
|
|
128
135
|
export type ConflictAnnotation = typeof ConflictAnnotation.Type;
|
|
129
136
|
/**
|
|
@@ -140,9 +147,11 @@ export type ConflictAnnotation = typeof ConflictAnnotation.Type;
|
|
|
140
147
|
* a later elaboration can resolve a pair against them without re-reading the
|
|
141
148
|
* flow source.
|
|
142
149
|
*
|
|
150
|
+
* `generation` is 0 for nodes from {@link compile} and grows by one with each
|
|
151
|
+
* {@link append}.
|
|
152
|
+
*
|
|
143
153
|
* @since 0.1.0
|
|
144
154
|
* @category schemas
|
|
145
|
-
* @slop
|
|
146
155
|
*/
|
|
147
156
|
export declare const PlanNode: Schema.Struct<{
|
|
148
157
|
readonly id: Schema.NonEmptyString;
|
|
@@ -167,6 +176,7 @@ export declare const PlanNode: Schema.Struct<{
|
|
|
167
176
|
readonly placement: Schema.optional<Schema.Unknown>;
|
|
168
177
|
}>;
|
|
169
178
|
readonly effects: Schema.Struct<{
|
|
179
|
+
/** Paths the node reads. A read orders the node after every writer of an overlapping path. */
|
|
170
180
|
readonly reads: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
|
|
171
181
|
readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
172
182
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
@@ -177,6 +187,7 @@ export declare const PlanNode: Schema.Struct<{
|
|
|
177
187
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
178
188
|
}>]>>;
|
|
179
189
|
}>]>>;
|
|
190
|
+
/** Paths the node writes. Two writers of an overlapping path form a conflict. */
|
|
180
191
|
readonly writes: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
|
|
181
192
|
readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
182
193
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
@@ -197,6 +208,7 @@ export declare const PlanNode: Schema.Struct<{
|
|
|
197
208
|
* conflict pass and the reader-after-writer pass see them as one set.
|
|
198
209
|
*/
|
|
199
210
|
readonly removes: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
211
|
+
/** How strictly the sandbox enforces these declarations. */
|
|
200
212
|
readonly boundaryMode: Schema.Literals<readonly ["hard", "expected"]>;
|
|
201
213
|
}>;
|
|
202
214
|
readonly dependsOn: Schema.$Array<Schema.NonEmptyString>;
|
|
@@ -216,7 +228,6 @@ export declare const PlanNode: Schema.Struct<{
|
|
|
216
228
|
*
|
|
217
229
|
* @since 0.1.0
|
|
218
230
|
* @category models
|
|
219
|
-
* @slop
|
|
220
231
|
*/
|
|
221
232
|
export type PlanNode = typeof PlanNode.Type;
|
|
222
233
|
/**
|
|
@@ -229,9 +240,11 @@ export type PlanNode = typeof PlanNode.Type;
|
|
|
229
240
|
* `baseDigest` is the digest at generation 0: what a human approved and what
|
|
230
241
|
* a `RUNNING` run pins. `digest` advances with every appended elaboration.
|
|
231
242
|
*
|
|
243
|
+
* Decoding checks only the shape. Use {@link verify} to check that keys,
|
|
244
|
+
* edges, and digests match the declarations.
|
|
245
|
+
*
|
|
232
246
|
* @since 0.1.0
|
|
233
247
|
* @category schemas
|
|
234
|
-
* @slop
|
|
235
248
|
*/
|
|
236
249
|
export declare const Plan: Schema.Struct<{
|
|
237
250
|
readonly planId: Schema.NonEmptyString;
|
|
@@ -262,6 +275,7 @@ export declare const Plan: Schema.Struct<{
|
|
|
262
275
|
readonly placement: Schema.optional<Schema.Unknown>;
|
|
263
276
|
}>;
|
|
264
277
|
readonly effects: Schema.Struct<{
|
|
278
|
+
/** Paths the node reads. A read orders the node after every writer of an overlapping path. */
|
|
265
279
|
readonly reads: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
|
|
266
280
|
readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
267
281
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
@@ -272,6 +286,7 @@ export declare const Plan: Schema.Struct<{
|
|
|
272
286
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
273
287
|
}>]>>;
|
|
274
288
|
}>]>>;
|
|
289
|
+
/** Paths the node writes. Two writers of an overlapping path form a conflict. */
|
|
275
290
|
readonly writes: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
|
|
276
291
|
readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
277
292
|
readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
@@ -292,6 +307,7 @@ export declare const Plan: Schema.Struct<{
|
|
|
292
307
|
* conflict pass and the reader-after-writer pass see them as one set.
|
|
293
308
|
*/
|
|
294
309
|
readonly removes: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
|
|
310
|
+
/** How strictly the sandbox enforces these declarations. */
|
|
295
311
|
readonly boundaryMode: Schema.Literals<readonly ["hard", "expected"]>;
|
|
296
312
|
}>;
|
|
297
313
|
readonly dependsOn: Schema.$Array<Schema.NonEmptyString>;
|
|
@@ -312,7 +328,6 @@ export declare const Plan: Schema.Struct<{
|
|
|
312
328
|
*
|
|
313
329
|
* @since 0.1.0
|
|
314
330
|
* @category models
|
|
315
|
-
* @slop
|
|
316
331
|
*/
|
|
317
332
|
export type Plan = typeof Plan.Type;
|
|
318
333
|
/**
|
|
@@ -320,13 +335,17 @@ export type Plan = typeof Plan.Type;
|
|
|
320
335
|
*
|
|
321
336
|
* @since 0.1.0
|
|
322
337
|
* @category models
|
|
323
|
-
* @slop
|
|
324
338
|
*/
|
|
325
339
|
export interface NodeDraft {
|
|
340
|
+
/** A non-empty id, unique within the plan. */
|
|
326
341
|
readonly id: string;
|
|
342
|
+
/** The key inputs. Its `Ref` inputs name the node's material dependencies. */
|
|
327
343
|
readonly material: KeyMaterial.KeyMaterial;
|
|
344
|
+
/** The declared reads, writes, and removals. They replace `material.effects`. */
|
|
328
345
|
readonly effects: NodeEffects;
|
|
346
|
+
/** `step`, `agent`, or `merge`. Defaults to `step`. */
|
|
329
347
|
readonly kind?: PlanNode["kind"] | undefined;
|
|
348
|
+
/** A safe integer scheduling priority. Defaults to 0. */
|
|
330
349
|
readonly priority?: number | undefined;
|
|
331
350
|
/** This declaration's preferred plan-time verdict for a detected overlap. */
|
|
332
351
|
readonly conflictStrategy?: PairStrategy | undefined;
|
|
@@ -338,11 +357,22 @@ declare const PlanError_base: Schema.Class<PlanError, Schema.TaggedStruct<"@smth
|
|
|
338
357
|
readonly message: Schema.String;
|
|
339
358
|
}>, import("effect/Cause").YieldableError>;
|
|
340
359
|
/**
|
|
341
|
-
* A graph the compiler refuses.
|
|
360
|
+
* A graph the compiler refuses. `code` names the rule:
|
|
361
|
+
*
|
|
362
|
+
* - `cycle`: material or inferred edges form a cycle.
|
|
363
|
+
* - `unknown_dependency`: a `Ref` names a node that is not in the plan.
|
|
364
|
+
* - `duplicate_node`: two nodes share an id.
|
|
365
|
+
* - `overlap_forbidden`: two unordered writers overlap and the pair's
|
|
366
|
+
* strategy is `fail`.
|
|
367
|
+
* - `invalid_effects`: a node both writes and removes one path.
|
|
368
|
+
* - `invalid_node`: a draft field, the plan id, or the flow name is malformed.
|
|
369
|
+
* - `invalid_plan`: {@link verify} found a plan that does not match its
|
|
370
|
+
* declarations.
|
|
371
|
+
* - `graph_too_large`: the plan exceeds {@link maximumPlanNodes} or the
|
|
372
|
+
* effect-analysis work budget.
|
|
342
373
|
*
|
|
343
374
|
* @since 0.1.0
|
|
344
375
|
* @category errors
|
|
345
|
-
* @slop
|
|
346
376
|
*/
|
|
347
377
|
export declare class PlanError extends PlanError_base {
|
|
348
378
|
}
|
|
@@ -354,7 +384,6 @@ export declare class PlanError extends PlanError_base {
|
|
|
354
384
|
*
|
|
355
385
|
* @since 1.0.0
|
|
356
386
|
* @category limits
|
|
357
|
-
* @slop
|
|
358
387
|
*/
|
|
359
388
|
export declare const maximumPlanNodes = 10000;
|
|
360
389
|
/**
|
|
@@ -367,9 +396,15 @@ export declare const maximumPlanNodes = 10000;
|
|
|
367
396
|
* {@link maximumPlanNodes} and fail with `graph_too_large` above that limit
|
|
368
397
|
* or the effect-analysis work budget. Analysis yields periodically.
|
|
369
398
|
*
|
|
399
|
+
* The options and drafts are copied when `compile` is called, so later
|
|
400
|
+
* caller mutation does not reach the plan. The result is deeply frozen.
|
|
401
|
+
*
|
|
402
|
+
* @param options - `planId` and `flow` name the plan; `nodes` are the drafts.
|
|
403
|
+
* @returns The generation-0 plan, whose `baseDigest` equals its `digest`.
|
|
404
|
+
* Fails with {@link PlanError} for a refused graph, `KeyMaterialError` or
|
|
405
|
+
* `SchemaError` when a key cannot be derived.
|
|
370
406
|
* @since 0.1.0
|
|
371
407
|
* @category constructors
|
|
372
|
-
* @slop
|
|
373
408
|
*/
|
|
374
409
|
export declare const compile: (options: {
|
|
375
410
|
readonly planId: string;
|
|
@@ -386,9 +421,16 @@ export declare const compile: (options: {
|
|
|
386
421
|
* Re-ordering after a reconciliation happens by re-keying *future* steps,
|
|
387
422
|
* never by rewriting history.
|
|
388
423
|
*
|
|
424
|
+
* A plan not produced by this module is checked with {@link verify} first.
|
|
425
|
+
*
|
|
426
|
+
* @param plan - The plan to grow.
|
|
427
|
+
* @param drafts - At least one new node. Ids must not repeat existing ones;
|
|
428
|
+
* `Ref` inputs may name existing nodes.
|
|
429
|
+
* @returns The plan with one more generation and a new `digest`. Fails with
|
|
430
|
+
* {@link PlanError} (`invalid_node` for an empty `drafts`, `invalid_plan` for a
|
|
431
|
+
* plan that fails verification), `KeyMaterialError`, or `SchemaError`.
|
|
389
432
|
* @since 0.1.0
|
|
390
433
|
* @category constructors
|
|
391
|
-
* @slop
|
|
392
434
|
*/
|
|
393
435
|
export declare const append: (plan: Plan, drafts: ReadonlyArray<NodeDraft>) => Effect.Effect<Plan, PlanError | StepKey.KeyMaterialError | Schema.SchemaError, Crypto.Crypto>;
|
|
394
436
|
/**
|
|
@@ -409,9 +451,10 @@ export declare const verify: (input: unknown) => Effect.Effect<Plan, PlanError |
|
|
|
409
451
|
* The nodes added by the newest generation: what {@link module:PlanStore}
|
|
410
452
|
* appends and what the `subgraph-appended` journal record names.
|
|
411
453
|
*
|
|
454
|
+
* @param plan - A plan.
|
|
455
|
+
* @returns The nodes whose generation equals `plan.generation`, in order.
|
|
412
456
|
* @since 0.1.0
|
|
413
457
|
* @category accessors
|
|
414
|
-
* @slop
|
|
415
458
|
*/
|
|
416
459
|
export declare const generationNodes: (plan: Plan) => ReadonlyArray<PlanNode>;
|
|
417
460
|
/**
|
|
@@ -419,9 +462,11 @@ export declare const generationNodes: (plan: Plan) => ReadonlyArray<PlanNode>;
|
|
|
419
462
|
* {@link verify}: such values take verify's trusted fast path and need no
|
|
420
463
|
* second schema validation.
|
|
421
464
|
*
|
|
465
|
+
* @param input - Any value.
|
|
466
|
+
* @returns `true` only for a plan returned by {@link compile},
|
|
467
|
+
* {@link append}, or {@link verify}; a structurally equal copy returns `false`.
|
|
422
468
|
* @since 1.0.0
|
|
423
469
|
* @category guards
|
|
424
|
-
* @slop
|
|
425
470
|
*/
|
|
426
471
|
export declare const isVerified: (input: unknown) => input is Plan;
|
|
427
472
|
/**
|
|
@@ -431,9 +476,13 @@ export declare const isVerified: (input: unknown) => input is Plan;
|
|
|
431
476
|
* plan's integrity from the already-verified prefix instead of decoding and
|
|
432
477
|
* re-verifying every stored row.
|
|
433
478
|
*
|
|
479
|
+
* For a generation-0 plan no generation precedes the newest, so this is the
|
|
480
|
+
* digest of an empty node list.
|
|
481
|
+
*
|
|
482
|
+
* @param plan - A plan.
|
|
483
|
+
* @returns The approval digest of the nodes older than `plan.generation`.
|
|
434
484
|
* @since 1.0.0
|
|
435
485
|
* @category accessors
|
|
436
|
-
* @slop
|
|
437
486
|
*/
|
|
438
487
|
export declare const prefixDigest: (plan: Plan) => Effect.Effect<StepKey.StepKey, StepKey.KeyMaterialError | Schema.SchemaError, Crypto.Crypto>;
|
|
439
488
|
export {};
|
package/dist/esm/Plan.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Plan.d.ts","sourceRoot":"","sources":["../../src/Plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAMvC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC
|
|
1
|
+
{"version":3,"file":"Plan.d.ts","sourceRoot":"","sources":["../../src/Plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAMvC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW;IACtB,8FAA8F;;;;;;;;;;;IAE9F,iFAAiF;;;;;;;;;;;;;;;IAEjF;;;;OAIG;;IAEH,4DAA4D;;EAE5D,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,yDAA2B,CAAA;AAEpD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,0DAAkD,CAAA;AAE9E;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAKzD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB;;;;;EAK7B,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAA;AAE/D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;QA7GnB,8FAA8F;;;;;;;;;;;QAE9F,iFAAiF;;;;;;;;;;;;;;;QAEjF;;;;WAIG;;QAEH,4DAA4D;;;;;;;;;;;;;;EA+G5D,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAnJf,8FAA8F;;;;;;;;;;;YAE9F,iFAAiF;;;;;;;;;;;;;;;YAEjF;;;;eAIG;;YAEH,4DAA4D;;;;;;;;;;;;;;;EAgJ5D,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;AAEnC;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,WAAW,CAAA;IAC1C,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5C,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IACpD,qDAAqD;IACrD,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;CACvD;;;;;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAU,SAAQ,cAY7B;CAAG;AAEL;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAS,CAAA;AA8ZtC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;CACzC,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAmB/F,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,MAAM,GACjB,MAAM,IAAI,EACV,QAAQ,aAAa,CAAC,SAAS,CAAC,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CA2B9F,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,GACjB,OAAO,OAAO,KACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAiE3F,CAAA;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,IAAI,KAAG,aAAa,CAAC,QAAQ,CACD,CAAA;AAElE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,IAC0B,CAAA;AAE/E;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,IAAI,KACT,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CACI,CAAA"}
|
package/dist/esm/Plan.js
CHANGED
|
@@ -31,12 +31,17 @@ import * as StepKey from "./StepKey.js";
|
|
|
31
31
|
* What a node does to the world, declared. Paths only — measuring them is
|
|
32
32
|
* run-time work, so a digest here would break the no-I/O law.
|
|
33
33
|
*
|
|
34
|
+
* Decoding fails with a `SchemaError` when a path is not workspace-relative.
|
|
35
|
+
* {@link compile} also refuses a node whose `removes` overlaps its `writes`
|
|
36
|
+
* with an `invalid_effects` {@link PlanError}.
|
|
37
|
+
*
|
|
34
38
|
* @since 0.1.0
|
|
35
39
|
* @category schemas
|
|
36
|
-
* @slop
|
|
37
40
|
*/
|
|
38
41
|
export const NodeEffects = Schema.Struct({
|
|
42
|
+
/** Paths the node reads. A read orders the node after every writer of an overlapping path. */
|
|
39
43
|
reads: Schema.Array(FileSet.ReadDeclaration),
|
|
44
|
+
/** Paths the node writes. Two writers of an overlapping path form a conflict. */
|
|
40
45
|
writes: Schema.Array(FileSet.Declaration),
|
|
41
46
|
/**
|
|
42
47
|
* Paths the node declares it will DELETE. A removal mutates the world exactly
|
|
@@ -44,24 +49,28 @@ export const NodeEffects = Schema.Struct({
|
|
|
44
49
|
* conflict pass and the reader-after-writer pass see them as one set.
|
|
45
50
|
*/
|
|
46
51
|
removes: Schema.optional(Schema.Array(FileSet.Pattern)),
|
|
52
|
+
/** How strictly the sandbox enforces these declarations. */
|
|
47
53
|
boundaryMode: FileSet.BoundaryMode
|
|
48
54
|
});
|
|
49
55
|
/**
|
|
50
|
-
* The plan-time
|
|
56
|
+
* The plan-time verdict for two writers of an overlapping path:
|
|
57
|
+
* `serialize` gives the later writer an ordering edge, `lane` records a lane
|
|
58
|
+
* annotation on both writers and adds no edge, and `fail` refuses the plan
|
|
59
|
+
* with `overlap_forbidden`. For a pair, `fail` dominates `lane`, which
|
|
60
|
+
* dominates `serialize`. The same schema as `Effects.ConflictStrategy`.
|
|
51
61
|
*
|
|
52
62
|
* @since 0.1.0
|
|
53
63
|
* @category schemas
|
|
54
|
-
* @slop
|
|
55
64
|
*/
|
|
56
65
|
export const PairStrategy = Effects.ConflictStrategy;
|
|
57
66
|
/**
|
|
58
67
|
* The runtime half of a conflict annotation: what the scheduler
|
|
59
68
|
* does when the overlap the plan predicted actually bites, or when a
|
|
60
|
-
* scheduled node's inputs are invalidated under it.
|
|
69
|
+
* scheduled node's inputs are invalidated under it. For a pair,
|
|
70
|
+
* `stop-merge` dominates `delay-rebase`.
|
|
61
71
|
*
|
|
62
72
|
* @since 0.1.0
|
|
63
73
|
* @category schemas
|
|
64
|
-
* @slop
|
|
65
74
|
*/
|
|
66
75
|
export const RuntimeStrategy = Schema.Literals(["delay-rebase", "stop-merge"]);
|
|
67
76
|
/** @private */
|
|
@@ -70,9 +79,11 @@ const NodeKind = Schema.Literals(["step", "agent", "merge"]);
|
|
|
70
79
|
* One resolved overlap between two writers that no dependency path already
|
|
71
80
|
* orders. Conflict is a property of the PAIR, not of one declaration.
|
|
72
81
|
*
|
|
82
|
+
* `with` names the other node, `paths` lists the overlapping declarations,
|
|
83
|
+
* and `strategy` and `runtime` are the verdicts resolved for the pair.
|
|
84
|
+
*
|
|
73
85
|
* @since 0.1.0
|
|
74
86
|
* @category schemas
|
|
75
|
-
* @slop
|
|
76
87
|
*/
|
|
77
88
|
export const ConflictAnnotation = Schema.Struct({
|
|
78
89
|
with: Schema.NonEmptyString,
|
|
@@ -94,9 +105,11 @@ export const ConflictAnnotation = Schema.Struct({
|
|
|
94
105
|
* a later elaboration can resolve a pair against them without re-reading the
|
|
95
106
|
* flow source.
|
|
96
107
|
*
|
|
108
|
+
* `generation` is 0 for nodes from {@link compile} and grows by one with each
|
|
109
|
+
* {@link append}.
|
|
110
|
+
*
|
|
97
111
|
* @since 0.1.0
|
|
98
112
|
* @category schemas
|
|
99
|
-
* @slop
|
|
100
113
|
*/
|
|
101
114
|
export const PlanNode = Schema.Struct({
|
|
102
115
|
id: Schema.NonEmptyString,
|
|
@@ -121,9 +134,11 @@ export const PlanNode = Schema.Struct({
|
|
|
121
134
|
* `baseDigest` is the digest at generation 0: what a human approved and what
|
|
122
135
|
* a `RUNNING` run pins. `digest` advances with every appended elaboration.
|
|
123
136
|
*
|
|
137
|
+
* Decoding checks only the shape. Use {@link verify} to check that keys,
|
|
138
|
+
* edges, and digests match the declarations.
|
|
139
|
+
*
|
|
124
140
|
* @since 0.1.0
|
|
125
141
|
* @category schemas
|
|
126
|
-
* @slop
|
|
127
142
|
*/
|
|
128
143
|
export const Plan = Schema.Struct({
|
|
129
144
|
planId: Schema.NonEmptyString,
|
|
@@ -134,11 +149,22 @@ export const Plan = Schema.Struct({
|
|
|
134
149
|
nodes: Schema.Array(PlanNode)
|
|
135
150
|
});
|
|
136
151
|
/**
|
|
137
|
-
* A graph the compiler refuses.
|
|
152
|
+
* A graph the compiler refuses. `code` names the rule:
|
|
153
|
+
*
|
|
154
|
+
* - `cycle`: material or inferred edges form a cycle.
|
|
155
|
+
* - `unknown_dependency`: a `Ref` names a node that is not in the plan.
|
|
156
|
+
* - `duplicate_node`: two nodes share an id.
|
|
157
|
+
* - `overlap_forbidden`: two unordered writers overlap and the pair's
|
|
158
|
+
* strategy is `fail`.
|
|
159
|
+
* - `invalid_effects`: a node both writes and removes one path.
|
|
160
|
+
* - `invalid_node`: a draft field, the plan id, or the flow name is malformed.
|
|
161
|
+
* - `invalid_plan`: {@link verify} found a plan that does not match its
|
|
162
|
+
* declarations.
|
|
163
|
+
* - `graph_too_large`: the plan exceeds {@link maximumPlanNodes} or the
|
|
164
|
+
* effect-analysis work budget.
|
|
138
165
|
*
|
|
139
166
|
* @since 0.1.0
|
|
140
167
|
* @category errors
|
|
141
|
-
* @slop
|
|
142
168
|
*/
|
|
143
169
|
export class PlanError extends Schema.TaggedError()("@smthrs/plan/PlanError", {
|
|
144
170
|
code: Schema.Literals([
|
|
@@ -162,7 +188,6 @@ export class PlanError extends Schema.TaggedError()("@smthrs/plan/PlanError", {
|
|
|
162
188
|
*
|
|
163
189
|
* @since 1.0.0
|
|
164
190
|
* @category limits
|
|
165
|
-
* @slop
|
|
166
191
|
*/
|
|
167
192
|
export const maximumPlanNodes = 10_000;
|
|
168
193
|
/** @private */
|
|
@@ -502,9 +527,15 @@ const keyNodes = (drafts, existing, generation) => Effect.gen(function* () {
|
|
|
502
527
|
* {@link maximumPlanNodes} and fail with `graph_too_large` above that limit
|
|
503
528
|
* or the effect-analysis work budget. Analysis yields periodically.
|
|
504
529
|
*
|
|
530
|
+
* The options and drafts are copied when `compile` is called, so later
|
|
531
|
+
* caller mutation does not reach the plan. The result is deeply frozen.
|
|
532
|
+
*
|
|
533
|
+
* @param options - `planId` and `flow` name the plan; `nodes` are the drafts.
|
|
534
|
+
* @returns The generation-0 plan, whose `baseDigest` equals its `digest`.
|
|
535
|
+
* Fails with {@link PlanError} for a refused graph, `KeyMaterialError` or
|
|
536
|
+
* `SchemaError` when a key cannot be derived.
|
|
505
537
|
* @since 0.1.0
|
|
506
538
|
* @category constructors
|
|
507
|
-
* @slop
|
|
508
539
|
*/
|
|
509
540
|
export const compile = (options) => {
|
|
510
541
|
const captured = snapshot(options);
|
|
@@ -538,9 +569,16 @@ export const compile = (options) => {
|
|
|
538
569
|
* Re-ordering after a reconciliation happens by re-keying *future* steps,
|
|
539
570
|
* never by rewriting history.
|
|
540
571
|
*
|
|
572
|
+
* A plan not produced by this module is checked with {@link verify} first.
|
|
573
|
+
*
|
|
574
|
+
* @param plan - The plan to grow.
|
|
575
|
+
* @param drafts - At least one new node. Ids must not repeat existing ones;
|
|
576
|
+
* `Ref` inputs may name existing nodes.
|
|
577
|
+
* @returns The plan with one more generation and a new `digest`. Fails with
|
|
578
|
+
* {@link PlanError} (`invalid_node` for an empty `drafts`, `invalid_plan` for a
|
|
579
|
+
* plan that fails verification), `KeyMaterialError`, or `SchemaError`.
|
|
541
580
|
* @since 0.1.0
|
|
542
581
|
* @category constructors
|
|
543
|
-
* @slop
|
|
544
582
|
*/
|
|
545
583
|
export const append = (plan, drafts) => {
|
|
546
584
|
const candidate = frozenPlans.has(plan) ? plan : snapshot(plan);
|
|
@@ -643,9 +681,10 @@ export const verify = (input) => Effect.gen(function* () {
|
|
|
643
681
|
* The nodes added by the newest generation: what {@link module:PlanStore}
|
|
644
682
|
* appends and what the `subgraph-appended` journal record names.
|
|
645
683
|
*
|
|
684
|
+
* @param plan - A plan.
|
|
685
|
+
* @returns The nodes whose generation equals `plan.generation`, in order.
|
|
646
686
|
* @since 0.1.0
|
|
647
687
|
* @category accessors
|
|
648
|
-
* @slop
|
|
649
688
|
*/
|
|
650
689
|
export const generationNodes = (plan) => plan.nodes.filter((node) => node.generation === plan.generation);
|
|
651
690
|
/**
|
|
@@ -653,9 +692,11 @@ export const generationNodes = (plan) => plan.nodes.filter((node) => node.genera
|
|
|
653
692
|
* {@link verify}: such values take verify's trusted fast path and need no
|
|
654
693
|
* second schema validation.
|
|
655
694
|
*
|
|
695
|
+
* @param input - Any value.
|
|
696
|
+
* @returns `true` only for a plan returned by {@link compile},
|
|
697
|
+
* {@link append}, or {@link verify}; a structurally equal copy returns `false`.
|
|
656
698
|
* @since 1.0.0
|
|
657
699
|
* @category guards
|
|
658
|
-
* @slop
|
|
659
700
|
*/
|
|
660
701
|
export const isVerified = (input) => typeof input === "object" && input !== null && frozenPlans.has(input);
|
|
661
702
|
/**
|
|
@@ -665,9 +706,13 @@ export const isVerified = (input) => typeof input === "object" && input !== null
|
|
|
665
706
|
* plan's integrity from the already-verified prefix instead of decoding and
|
|
666
707
|
* re-verifying every stored row.
|
|
667
708
|
*
|
|
709
|
+
* For a generation-0 plan no generation precedes the newest, so this is the
|
|
710
|
+
* digest of an empty node list.
|
|
711
|
+
*
|
|
712
|
+
* @param plan - A plan.
|
|
713
|
+
* @returns The approval digest of the nodes older than `plan.generation`.
|
|
668
714
|
* @since 1.0.0
|
|
669
715
|
* @category accessors
|
|
670
|
-
* @slop
|
|
671
716
|
*/
|
|
672
717
|
export const prefixDigest = (plan) => digestOf(plan.planId, plan.flow, plan.nodes.filter((node) => node.generation < plan.generation));
|
|
673
718
|
//# sourceMappingURL=Plan.js.map
|