@smthrs/plan 0.0.0-stage → 1.0.0-rc.13

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 (209) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/LICENSE +21 -0
  3. package/README.md +230 -2
  4. package/THIRD_PARTY_NOTICES.md +48 -0
  5. package/dist/cjs/CachePolicy.d.ts +131 -0
  6. package/dist/cjs/CachePolicy.d.ts.map +1 -0
  7. package/dist/cjs/CachePolicy.js +50 -0
  8. package/dist/cjs/CachePolicy.js.map +7 -0
  9. package/dist/cjs/Effects.d.ts +258 -0
  10. package/dist/cjs/Effects.d.ts.map +1 -0
  11. package/dist/cjs/Effects.js +76 -0
  12. package/dist/cjs/Effects.js.map +7 -0
  13. package/dist/cjs/FileSet.d.ts +366 -0
  14. package/dist/cjs/FileSet.d.ts.map +1 -0
  15. package/dist/cjs/FileSet.js +196 -0
  16. package/dist/cjs/FileSet.js.map +7 -0
  17. package/dist/cjs/GraphBuildError.d.ts +120 -0
  18. package/dist/cjs/GraphBuildError.d.ts.map +1 -0
  19. package/dist/cjs/GraphBuildError.js +71 -0
  20. package/dist/cjs/GraphBuildError.js.map +7 -0
  21. package/dist/cjs/KeyMaterial.d.ts +107 -0
  22. package/dist/cjs/KeyMaterial.d.ts.map +1 -0
  23. package/dist/cjs/KeyMaterial.js +64 -0
  24. package/dist/cjs/KeyMaterial.js.map +7 -0
  25. package/dist/cjs/Node.d.ts +685 -0
  26. package/dist/cjs/Node.d.ts.map +1 -0
  27. package/dist/cjs/Node.js +230 -0
  28. package/dist/cjs/Node.js.map +7 -0
  29. package/dist/cjs/Placement.d.ts +117 -0
  30. package/dist/cjs/Placement.d.ts.map +1 -0
  31. package/dist/cjs/Placement.js +46 -0
  32. package/dist/cjs/Placement.js.map +7 -0
  33. package/dist/cjs/Plan.d.ts +489 -0
  34. package/dist/cjs/Plan.d.ts.map +1 -0
  35. package/dist/cjs/Plan.js +511 -0
  36. package/dist/cjs/Plan.js.map +7 -0
  37. package/dist/cjs/PlanDiff.d.ts +77 -0
  38. package/dist/cjs/PlanDiff.d.ts.map +1 -0
  39. package/dist/cjs/PlanDiff.js +149 -0
  40. package/dist/cjs/PlanDiff.js.map +7 -0
  41. package/dist/cjs/Planned.d.ts +121 -0
  42. package/dist/cjs/Planned.d.ts.map +1 -0
  43. package/dist/cjs/Planned.js +72 -0
  44. package/dist/cjs/Planned.js.map +7 -0
  45. package/dist/cjs/Repetition.d.ts +31 -0
  46. package/dist/cjs/Repetition.d.ts.map +1 -0
  47. package/dist/cjs/Repetition.js +36 -0
  48. package/dist/cjs/Repetition.js.map +7 -0
  49. package/dist/cjs/Scheduling.d.ts +89 -0
  50. package/dist/cjs/Scheduling.d.ts.map +1 -0
  51. package/dist/cjs/Scheduling.js +76 -0
  52. package/dist/cjs/Scheduling.js.map +7 -0
  53. package/dist/cjs/StepKey.d.ts +354 -0
  54. package/dist/cjs/StepKey.d.ts.map +1 -0
  55. package/dist/cjs/StepKey.js +313 -0
  56. package/dist/cjs/StepKey.js.map +7 -0
  57. package/dist/cjs/index.d.ts +91 -0
  58. package/dist/cjs/index.d.ts.map +1 -0
  59. package/dist/cjs/index.js +59 -0
  60. package/dist/cjs/index.js.map +7 -0
  61. package/dist/cjs/internal/ConflictAnnotation.d.ts +59 -0
  62. package/dist/cjs/internal/ConflictAnnotation.d.ts.map +1 -0
  63. package/dist/cjs/internal/ConflictAnnotation.js +247 -0
  64. package/dist/cjs/internal/ConflictAnnotation.js.map +7 -0
  65. package/dist/cjs/internal/EffectCandidates.d.ts +19 -0
  66. package/dist/cjs/internal/EffectCandidates.d.ts.map +1 -0
  67. package/dist/cjs/internal/EffectCandidates.js +92 -0
  68. package/dist/cjs/internal/EffectCandidates.js.map +7 -0
  69. package/dist/cjs/internal/JsonMirror.d.ts +34 -0
  70. package/dist/cjs/internal/JsonMirror.d.ts.map +1 -0
  71. package/dist/cjs/internal/JsonMirror.js +195 -0
  72. package/dist/cjs/internal/JsonMirror.js.map +7 -0
  73. package/dist/cjs/internal/SchemaIdentity.d.ts +140 -0
  74. package/dist/cjs/internal/SchemaIdentity.d.ts.map +1 -0
  75. package/dist/cjs/internal/SchemaIdentity.js +718 -0
  76. package/dist/cjs/internal/SchemaIdentity.js.map +7 -0
  77. package/dist/cjs/internal/effects.d.ts +245 -0
  78. package/dist/cjs/internal/effects.d.ts.map +1 -0
  79. package/dist/cjs/internal/effects.js +290 -0
  80. package/dist/cjs/internal/effects.js.map +7 -0
  81. package/dist/cjs/internal/node.d.ts +526 -0
  82. package/dist/cjs/internal/node.d.ts.map +1 -0
  83. package/dist/cjs/internal/node.js +313 -0
  84. package/dist/cjs/internal/node.js.map +7 -0
  85. package/dist/cjs/package.json +1 -0
  86. package/dist/cjs/test/PlanFixtures.d.ts +127 -0
  87. package/dist/cjs/test/PlanFixtures.d.ts.map +1 -0
  88. package/dist/cjs/test/PlanFixtures.js +59 -0
  89. package/dist/cjs/test/PlanFixtures.js.map +7 -0
  90. package/dist/esm/CachePolicy.d.ts +131 -0
  91. package/dist/esm/CachePolicy.d.ts.map +1 -0
  92. package/dist/esm/CachePolicy.js +117 -0
  93. package/dist/esm/CachePolicy.js.map +1 -0
  94. package/dist/esm/Effects.d.ts +258 -0
  95. package/dist/esm/Effects.d.ts.map +1 -0
  96. package/dist/esm/Effects.js +178 -0
  97. package/dist/esm/Effects.js.map +1 -0
  98. package/dist/esm/FileSet.d.ts +366 -0
  99. package/dist/esm/FileSet.d.ts.map +1 -0
  100. package/dist/esm/FileSet.js +398 -0
  101. package/dist/esm/FileSet.js.map +1 -0
  102. package/dist/esm/GraphBuildError.d.ts +120 -0
  103. package/dist/esm/GraphBuildError.d.ts.map +1 -0
  104. package/dist/esm/GraphBuildError.js +145 -0
  105. package/dist/esm/GraphBuildError.js.map +1 -0
  106. package/dist/esm/KeyMaterial.d.ts +107 -0
  107. package/dist/esm/KeyMaterial.d.ts.map +1 -0
  108. package/dist/esm/KeyMaterial.js +92 -0
  109. package/dist/esm/KeyMaterial.js.map +1 -0
  110. package/dist/esm/Node.d.ts +685 -0
  111. package/dist/esm/Node.d.ts.map +1 -0
  112. package/dist/esm/Node.js +591 -0
  113. package/dist/esm/Node.js.map +1 -0
  114. package/dist/esm/Placement.d.ts +117 -0
  115. package/dist/esm/Placement.d.ts.map +1 -0
  116. package/dist/esm/Placement.js +65 -0
  117. package/dist/esm/Placement.js.map +1 -0
  118. package/dist/esm/Plan.d.ts +489 -0
  119. package/dist/esm/Plan.d.ts.map +1 -0
  120. package/dist/esm/Plan.js +718 -0
  121. package/dist/esm/Plan.js.map +1 -0
  122. package/dist/esm/PlanDiff.d.ts +77 -0
  123. package/dist/esm/PlanDiff.d.ts.map +1 -0
  124. package/dist/esm/PlanDiff.js +205 -0
  125. package/dist/esm/PlanDiff.js.map +1 -0
  126. package/dist/esm/Planned.d.ts +121 -0
  127. package/dist/esm/Planned.d.ts.map +1 -0
  128. package/dist/esm/Planned.js +147 -0
  129. package/dist/esm/Planned.js.map +1 -0
  130. package/dist/esm/Repetition.d.ts +31 -0
  131. package/dist/esm/Repetition.d.ts.map +1 -0
  132. package/dist/esm/Repetition.js +24 -0
  133. package/dist/esm/Repetition.js.map +1 -0
  134. package/dist/esm/Scheduling.d.ts +89 -0
  135. package/dist/esm/Scheduling.d.ts.map +1 -0
  136. package/dist/esm/Scheduling.js +82 -0
  137. package/dist/esm/Scheduling.js.map +1 -0
  138. package/dist/esm/StepKey.d.ts +354 -0
  139. package/dist/esm/StepKey.d.ts.map +1 -0
  140. package/dist/esm/StepKey.js +503 -0
  141. package/dist/esm/StepKey.js.map +1 -0
  142. package/dist/esm/index.d.ts +91 -0
  143. package/dist/esm/index.d.ts.map +1 -0
  144. package/dist/esm/index.js +91 -0
  145. package/dist/esm/index.js.map +1 -0
  146. package/dist/esm/internal/ConflictAnnotation.d.ts +59 -0
  147. package/dist/esm/internal/ConflictAnnotation.d.ts.map +1 -0
  148. package/dist/esm/internal/ConflictAnnotation.js +332 -0
  149. package/dist/esm/internal/ConflictAnnotation.js.map +1 -0
  150. package/dist/esm/internal/EffectCandidates.d.ts +19 -0
  151. package/dist/esm/internal/EffectCandidates.d.ts.map +1 -0
  152. package/dist/esm/internal/EffectCandidates.js +86 -0
  153. package/dist/esm/internal/EffectCandidates.js.map +1 -0
  154. package/dist/esm/internal/JsonMirror.d.ts +34 -0
  155. package/dist/esm/internal/JsonMirror.d.ts.map +1 -0
  156. package/dist/esm/internal/JsonMirror.js +204 -0
  157. package/dist/esm/internal/JsonMirror.js.map +1 -0
  158. package/dist/esm/internal/SchemaIdentity.d.ts +140 -0
  159. package/dist/esm/internal/SchemaIdentity.d.ts.map +1 -0
  160. package/dist/esm/internal/SchemaIdentity.js +1002 -0
  161. package/dist/esm/internal/SchemaIdentity.js.map +1 -0
  162. package/dist/esm/internal/effects.d.ts +245 -0
  163. package/dist/esm/internal/effects.d.ts.map +1 -0
  164. package/dist/esm/internal/effects.js +459 -0
  165. package/dist/esm/internal/effects.js.map +1 -0
  166. package/dist/esm/internal/node.d.ts +526 -0
  167. package/dist/esm/internal/node.d.ts.map +1 -0
  168. package/dist/esm/internal/node.js +565 -0
  169. package/dist/esm/internal/node.js.map +1 -0
  170. package/dist/esm/test/PlanFixtures.d.ts +127 -0
  171. package/dist/esm/test/PlanFixtures.d.ts.map +1 -0
  172. package/dist/esm/test/PlanFixtures.js +60 -0
  173. package/dist/esm/test/PlanFixtures.js.map +1 -0
  174. package/docs/README.md +167 -0
  175. package/docs/api.md +1485 -0
  176. package/docs/concepts/authoring-ast.md +204 -0
  177. package/docs/concepts/effects-and-conflicts.md +135 -0
  178. package/docs/concepts/plan-value.md +168 -0
  179. package/docs/concepts/step-keys.md +179 -0
  180. package/docs/guides/author-a-node-graph.md +182 -0
  181. package/docs/guides/compile-a-plan.md +146 -0
  182. package/docs/guides/declare-file-effects.md +143 -0
  183. package/docs/guides/diff-two-plans.md +310 -0
  184. package/docs/installation.md +75 -0
  185. package/docs/quickstart.md +128 -0
  186. package/docs/testing.md +73 -0
  187. package/docs/troubleshooting.md +314 -0
  188. package/package.json +255 -3
  189. package/src/CachePolicy.ts +143 -0
  190. package/src/Effects.ts +302 -0
  191. package/src/FileSet.ts +493 -0
  192. package/src/GraphBuildError.ts +156 -0
  193. package/src/KeyMaterial.ts +111 -0
  194. package/src/Node.ts +974 -0
  195. package/src/Placement.ts +99 -0
  196. package/src/Plan.ts +911 -0
  197. package/src/PlanDiff.ts +244 -0
  198. package/src/Planned.ts +208 -0
  199. package/src/Repetition.ts +33 -0
  200. package/src/Scheduling.ts +154 -0
  201. package/src/StepKey.ts +736 -0
  202. package/src/index.ts +103 -0
  203. package/src/internal/ConflictAnnotation.ts +374 -0
  204. package/src/internal/EffectCandidates.ts +89 -0
  205. package/src/internal/JsonMirror.ts +255 -0
  206. package/src/internal/SchemaIdentity.ts +1096 -0
  207. package/src/internal/effects.ts +543 -0
  208. package/src/internal/node.ts +859 -0
  209. package/src/test/PlanFixtures.ts +76 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,189 @@
1
+ # @smthrs/plan
2
+
3
+ ## Unreleased
4
+
5
+ ### Added
6
+
7
+ - `Node.maximumArmDepth` exposes the existing eager branch construction limit so bounded patterns can reject unsupported declarations before planning. The limit and refusal behavior are unchanged. ([#4103](https://github.com/smithersai/smithers/issues/4103)).
8
+
9
+ ### Fixed
10
+
11
+ - `Node.representationIdentity` writes the representation a sealed action's step key hashes as `effect@4.0.0-rc.115` wrote it, with the six built-in check ids `effect@4.0.4` renamed written back. A schema with `Schema.brand` re-keys once, because the brand is no longer part of the AST. ([#3839](https://github.com/smithersai/smithers/issues/3839)).
12
+ - A schema's identity no longer depends on the installed `effect` release. `Node.schemaIdentity` prints the document a call or a `catch` filter contributes to a step key, as `effect@4.0.0-rc.115` printed it, so moving to `effect@4.0.4` or later does not re-key recorded steps. A declaration that uses one identified or recursive schema both with and without `Schema.brand` re-keys once. ([#3839](https://github.com/smithersai/smithers/issues/3839)).
13
+ - Keep live executable bindings and planned-reference ownership across compatible package copies; serialized ASTs remain inert. ([#1991](https://github.com/smithersai/smithers/issues/1991)).
14
+
15
+ ## [Unreleased]
16
+
17
+ ### Added
18
+
19
+ - `Scheduling.make` exposes the pure ready-work priority, aging and capacity
20
+ policy used by the durable plan scheduler. Its exact integer comparison does
21
+ not round away priority differences after aging. Conditional readiness and
22
+ effect execution remain the coordinator's responsibilities.
23
+
24
+ ### Fixed
25
+
26
+ - `StepKey.EnvironmentIdentity` now also supplies the runtime schema. Identity
27
+ constructors reject malformed/unknown environment fields with typed errors.
28
+ `StepKey.environmentIdentity` fingerprints a runtime environment for durable
29
+ recovery binding, using content-key normalization in a separate namespace.
30
+ Existing valid content and dispatch keys are unchanged.
31
+
32
+ - Explicit `Ref`/`Pending` read-before-write sequences compile and verify,
33
+ including transitive paths and appended generations. Conflicting inferred
34
+ producer/serialize orders still fail with `cycle`.
35
+
36
+ - `Plan.compile`, `append`, and `verify` accept compensable and irreversible
37
+ declarations. New `StepKey.planIdentity` separates their approval fingerprints
38
+ from cache eligibility. Existing sealed keys are unchanged;
39
+ `fromKeyMaterial` and `dispatchIdentity` remain sealed-only.
40
+
41
+ ## [1.0.0-rc.0] - 2026-08-31
42
+
43
+ ### Added
44
+
45
+ - The persisted plan: `Plan` (compile, append, conflict annotation),
46
+ `PlanStore` (append-only SQL, migration block `4000`), `PlanDiff`, and the
47
+ `KeyMaterial` to `StepKey` compiler revived from the deleted
48
+ `packages/smithers/flows/keys` modules, now producing `@smthrs/keys` `Key`
49
+ values rather than a second digest format.
50
+ - Added `Node.priority`, which attaches a scheduling priority to a node, and
51
+ `Node.declaredPriority`, which reads one back. The value is a plain JSON
52
+ field on the AST rather than a `Context` annotation, so a stored plan keeps
53
+ it. `Plan.compile` copies it from `NodeDraft.priority` onto the plan node and
54
+ folds it into the plan digest a human approves; it never enters a node's key
55
+ material, so raising a priority reorders work without re-keying a step. A
56
+ priority that is not a safe integer is a `GraphBuildError` with the new
57
+ `invalid_priority` code.
58
+ - Added package-owned documentation. `packages/plan/docs` and the public JSDoc
59
+ in `src` are the single source for the published API page.
60
+
61
+ ### Breaking Changes
62
+
63
+ - Bumped key material to `flows/key-material/v2` and captured-function
64
+ identity to `sha256-source-captures/v4`. Existing persisted step keys are
65
+ intentionally invalidated rather than being reused across changed identity
66
+ semantics.
67
+
68
+ - Plan approval digests now include each node's conflict and runtime
69
+ strategies. This moves plan digests without moving step keys. A running run
70
+ pinned to the old digest needs a new approval before it can use the changed
71
+ plan.
72
+ - A node payload is now cloned as its JSON mirror, so a payload carrying a
73
+ `toJSON`, such as a `Date` or a `URL`, keys as the value it serializes to
74
+ rather than as an empty object. Payloads of that shape re-key once.
75
+ - A flow call's `KeyMaterial.body` no longer has a body-less shape. `Flow.make`
76
+ requires `body`, so `@smthrs/flow` never records `declaration.body:
77
+ undefined` for a call whose declaration survived beside its AST.
78
+ `StepKey.content` therefore folds a body digest into every such node, and the
79
+ keys `Plan.compile` derives for the flow calls that previously carried none
80
+ move with it.
81
+ - The raw migration steps moved beneath `src/internal/migrations`, so
82
+ `@smthrs/plan/migrations/0001_initial` and its siblings no longer resolve.
83
+ `Migrations.set` is the supported surface; a step imported on its own ran
84
+ outside the namespaced ordering `Migrator` relies on.
85
+ - `Node.isNode` no longer accepts the public `TypeId` marker on its own. It
86
+ recognizes a node this package built by registration at construction, and a
87
+ rehydrated node, an object sharing the node prototype whose own `ast` is a
88
+ well-formed AST, by that shape, which is what `@smthrs/flow` hands back for
89
+ an AST that crossed a serialization boundary. `Node.all`, `andThen`,
90
+ `branch`, and `catch` therefore refuse a forged object carrying the marker,
91
+ one inheriting it from a node, and one whose `ast` is missing, malformed, or
92
+ cyclic with their usual `GraphBuildError` instead of storing an `ast` the
93
+ package never built.
94
+ - `StepKey.EnvironmentIdentity` is now a discriminated union. A declared
95
+ environment may not carry a `runScope` and an undeclared one must, which
96
+ `StepKey.dispatchIdentity` also enforces at run time with the new
97
+ `invalid_environment` code.
98
+ - A plan may no longer contain an unbounded number of nodes. `Plan.compile` and
99
+ `Plan.append` refuse a plan above `Plan.maximumPlanNodes` with the new
100
+ `graph_too_large` code, before any pair comparison runs. The conflict pass
101
+ compares node pairs and adds a reachability walk per overlapping pair, so an
102
+ unbounded plan had an unbounded planning cost; a graph larger than the bound
103
+ now has to be split.
104
+ - `NodeDraft.effects` is now the single derivation point for effect identity.
105
+ `Plan.compile` and `Plan.append` fold the decoded declaration into the hashed
106
+ material, replacing any `material.effects` a caller supplied. Every plan
107
+ re-keys once, and editing `reads`, `writes`, `removes`, or `boundaryMode`
108
+ now re-keys the node and is attributed by `PlanDiff` as `effects`. Before
109
+ this, the two channels were independent: a draft could change what a node
110
+ writes without moving its key, and `PlanDiff` reported it `unchanged`.
111
+ - Compiled material is stored as its deeply frozen JSON mirror. A `Date`, a
112
+ `URL`, or any value with a data-valued callable `toJSON` is stored as the
113
+ value it serializes to, which is what its key already covered. A material
114
+ accessor or a prototype with no JSON representation is now refused with
115
+ `invalid_node` rather than passed through by reference; the message names the
116
+ node and the payload path and never the value.
117
+ - A payload whose `toJSON` returns its own receiver now fails with the
118
+ `cyclic_payload` `GraphBuildError` instead of being silently omitted from the
119
+ clone. The clone and the input now agree: canonical serialization refused
120
+ that shape all along, while the clone quietly keyed as `{}`.
121
+
122
+ ### Fixed
123
+
124
+ - The migration steps under `internal/migrations` are named exports, and
125
+ `Migrations` imports them by name. The CommonJS build compiled each
126
+ `export default` step to `exports.default`, and Node's default-import interop
127
+ then handed the importer the whole exports object instead of the Effect, so
128
+ `require("@smthrs/plan/Migrations")` produced a set whose entries had no
129
+ `pipe`.
130
+ - Plan payload capture now refuses accessors and unsupported prototypes with
131
+ `invalid_payload` instead of executing getters or collapsing `Map`, `Set`,
132
+ `RegExp`, and class instances onto the same `{}` identity.
133
+ - `StepKey.content` and `dispatchIdentity` now share one environment validator;
134
+ undeclared environments require a non-empty run scope on both paths.
135
+
136
+ - `PlanStore.append` now advances the stored plan row with a compare-and-swap
137
+ on the previous generation, so appending a skipped generation is refused
138
+ instead of persisting node rows whose dependencies are missing and which the
139
+ append-only triggers then forbid removing. Node ordinals are derived from the
140
+ store rather than from the caller's array, `PlanStore.record` refuses
141
+ anything that is not generation 0, and an append with no new nodes is
142
+ refused rather than advancing the generation for nothing.
143
+ - A node payload no longer keeps live functions, and different `Date`, `URL`
144
+ or other `toJSON` payloads no longer share one step key.
145
+ - `StepKey.fromKeyMaterial` resolves dependency digests as own properties, so a
146
+ dependency named `toString` or `constructor` is a `missing_dependency`
147
+ refusal rather than a colliding key.
148
+ - A `StepKey.DigestMemo` waiter no longer inherits the leader's interruption;
149
+ it recomputes its own digest instead.
150
+ - `StepKey.project` resolves only own data properties, so a projection path
151
+ through `toString`, `constructor` or `__proto__` yields `undefined` as
152
+ documented and no getter runs during key derivation.
153
+ - The conflict pass now decides orderedness against the live edge set, so a
154
+ writer pair a dependency path already orders is neither annotated, nor given
155
+ a redundant edge, nor refused with `overlap_forbidden`.
156
+ - `Plan.compile` now fails with `cycle` when a reader-after-writer edge would
157
+ close a cycle, because a declared dependency or a `serialize` edge already
158
+ orders the producer behind its reader. The edge was dropped before, which
159
+ left the reader ahead of its producer to measure and cache pre-producer
160
+ bytes as a legitimate execution. The message names the reader, the producer,
161
+ the overlapping paths, and the dependency chain.
162
+ - `Plan.compile` no longer recurses per dependency edge and no longer
163
+ materializes a transitive closure, so a large graph compiles in bounded
164
+ memory instead of raising an untyped `RangeError`.
165
+ - `Plan.compile` and `Plan.append` validate drafts before keying, with the new
166
+ `invalid_node` code, so an empty plan id, an unsafe-integer priority, or a
167
+ key material version this release does not know is refused at the plan rather
168
+ than at the store.
169
+ - `PlanDiff` attributes a key move caused by `nondeterministic` or `placement`,
170
+ and `Node.capture` refuses a capture nested past its documented limit with a
171
+ path-bearing error rather than overflowing the stack.
172
+ - `Plan.compile` and `Plan.append` decode `NodeDraft.effects` through
173
+ `NodeEffects` before keying, so a malformed declaration is a typed
174
+ `invalid_node` naming the node and the failing path instead of an untyped
175
+ defect. A filesystem declaration containing C0 controls or DEL, or one that is
176
+ not workspace-relative, is refused there rather than reaching a host
177
+ filesystem, and path comparison is Unicode NFC normalized, so two spellings of
178
+ one name are detected as an overlap. `invalid_effects` is now reserved for the
179
+ cross-field rule that one path cannot be both a write and a removal.
180
+ - `Planned.reference` validates the reference shape, so a forged carrier can no
181
+ longer inject a fabricated projection path into a payload.
182
+ - Compiled and appended plans now keep the exact material and filesystem
183
+ authority that their keys and approval digest cover, even if caller-owned
184
+ draft objects are later mutated.
185
+ - Persisted plans can no longer be deleted or have their plan id, flow, or
186
+ creation time rewritten, and node order is now unique and deterministic within
187
+ each plan. Migration `4003` adds the plan-id pin the forward-only trigger was
188
+ missing, which a rename could otherwise use to strand a plan's immortal node
189
+ rows under an id nothing can record again.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 William Cory and the Smithers Flows contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,231 @@
1
- # Temporary Holding Version
1
+ # @smthrs/plan
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Release candidate scope, host requirements and compatibility review are defined in the [library support policy](https://github.com/smithersai/smithers/blob/main/RELEASE_SUPPORT.md).
4
+
5
+ This package declares `effect` as an exact `4.0.5` peer dependency. Install one
6
+ `effect` release at that version so all Smithers packages share one Effect
7
+ runtime.
8
+
9
+ **Documentation:** https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan/docs
10
+
11
+ The persisted plan: a keyed action graph, its append-only store, its diff, and
12
+ the step-key compiler that gives every node its identity.
13
+
14
+ `@smthrs/plan` turns a description of work into one durable value. It compiles
15
+ declared steps into a graph in which every node carries a content key derived
16
+ from what that node declares, records that graph in a SQLite store that only
17
+ ever grows, and compares two graphs to say exactly what changed. It runs
18
+ nothing itself: it performs no I/O beyond the database, and driving a compiled
19
+ plan is a scheduler's job, such as
20
+ [`@smthrs/engine-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/engine-store/docs)'s `PlanScheduler`.
21
+
22
+ Reach for it when you are building a scheduler, a cache, or an approval flow
23
+ over declared work and you need step identity, declared file effects, and an
24
+ auditable history as values you can hold, hash, and store.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ npm install @smthrs/plan@next effect
30
+ ```
31
+
32
+ Compiling asks Effect for its `Crypto` service, which a platform package
33
+ supplies:
34
+
35
+ ```bash
36
+ pnpm add @effect/platform-node @effect/platform-node-shared
37
+ ```
38
+
39
+ Node.js 26.4.0 or later, and `effect` `4.0.5` as a peer. Recording a plan
40
+ is [`@smthrs/plan-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan-store/docs), which owns the SQL
41
+ and brings [`@smthrs/database`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/database/docs) with it.
42
+
43
+ ## Compile a plan
44
+
45
+ Two steps, where the second consumes the first's result and reads the file the
46
+ first writes:
47
+
48
+ ```ts
49
+ import * as NodeCrypto from "@effect/platform-node/NodeCrypto"
50
+ import * as KeyMaterial from "@smthrs/plan/KeyMaterial"
51
+ import * as Plan from "@smthrs/plan/Plan"
52
+ import * as Effect from "effect/Effect"
53
+
54
+ /** Everything hashed about one node. `sealed` is work whose result may be reused across runs. */
55
+ const sealed = (body: unknown, inputs: ReadonlyArray<KeyMaterial.InputRef> = []): KeyMaterial.KeyMaterial => ({
56
+ version: KeyMaterial.version,
57
+ kind: "sealed",
58
+ body,
59
+ inputs,
60
+ layers: [],
61
+ capabilities: []
62
+ })
63
+
64
+ const drafts: ReadonlyArray<Plan.NodeDraft> = [
65
+ {
66
+ id: "run-tests",
67
+ material: sealed({ action: "run-tests" }, [{ _tag: "Ref", from: "read-pr", path: [] }]),
68
+ effects: { reads: ["pr.json"], writes: ["report.json"], boundaryMode: "hard" }
69
+ },
70
+ {
71
+ id: "read-pr",
72
+ material: sealed({ action: "read-pr", pr: 4821 }),
73
+ effects: { reads: [], writes: ["pr.json"], boundaryMode: "hard" }
74
+ }
75
+ ]
76
+
77
+ const plan = await Effect.runPromise(
78
+ Plan.compile({ planId: "review-4821", flow: "example/Review", nodes: drafts }).pipe(
79
+ Effect.provide(NodeCrypto.layer),
80
+ Effect.orDie
81
+ )
82
+ )
83
+
84
+ console.log(plan.digest)
85
+ for (const node of plan.nodes) console.log(node.id, node.key, node.dependsOn)
86
+ ```
87
+
88
+ The digests on your machine match these, because a plan is a pure function of
89
+ its declarations. Compiling reads no file, no clock, and no network:
90
+
91
+ ```text
92
+ key1_61edccc875ff69b798e0c3874d167f65ff0a250b9fe67d27558b854fa2832302
93
+ read-pr key1_6353326ab2a03804d6acfe916debc4f04f09f9deb8f0e93c1ebea3cdd983db18 []
94
+ run-tests key1_e58229e3be2f6abf6f818baf8577fe7045edba6f5e88097b633898478da93985 [ 'read-pr' ]
95
+ ```
96
+
97
+ The drafts went in out of order and came back topologically sorted.
98
+ `run-tests` names `read-pr` once, in its key material, and that single
99
+ declaration became both the hashed dependency and the graph edge, so an edge
100
+ and a key can never disagree about what a node consumes. Change `pr: 4821` to
101
+ another number and both keys move; rename `read-pr` to `fetch-pr` and neither
102
+ does.
103
+
104
+ Recording that plan is
105
+ [`@smthrs/plan-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan-store/docs), whose
106
+ [quickstart](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan-store/docs/quickstart.md) builds the whole
107
+ composition against an in-memory database.
108
+
109
+ ## What is in here
110
+
111
+ | Module | Role |
112
+ | ----------------- | --------------------------------------------------------------------------------------------------- |
113
+ | `Node` | The pure, pipeable authoring AST: `succeed`, `all`, `map`, `andThen`, `branch`, `catch`, `priority` |
114
+ | `Planned` | The strict placeholder a body sees where a step result will be, and the reference it records |
115
+ | `GraphBuildError` | The refusals a plan-time build raises instead of producing a wrong plan |
116
+ | `FileSet` | The static filesystem declaration vocabulary: patterns, globs, tree artifacts, filegroups, overlap |
117
+ | `KeyMaterial` | What a planner declares about a node: body, tagged input references, layers, capabilities, effects |
118
+ | `StepKey` | The compiler that turns material plus resolved dependency digests into a `@smthrs/keys` `Key` |
119
+ | `Plan` | `compile`, `append`, the node/edge/conflict schemas, and the digest an approval binds to |
120
+ | `PlanDiff` | A comparison of two plans as a value: added, removed, re-keyed with attribution, unchanged |
121
+ | `Placement` | Where a node runs: the four directives, their host-selection detail, and the annotation key |
122
+
123
+ Every module is its own entry point, so
124
+ `import * as Plan from "@smthrs/plan/Plan"` keeps a bundle to what you reach
125
+ for. The root entry re-exports all of them as namespaces.
126
+
127
+ ## The four rules this package exists to keep
128
+
129
+ **Planning demands nothing.** A `Node` carries Effect's requirement channel,
130
+ `R`, and carries it as a phantom: no combinator here reads it, and the AST, the
131
+ graph, the key material, and every digest are identical whatever it says.
132
+ Building a plan therefore asks for no service at all. What fills the channel is
133
+ a call to something whose code lives elsewhere, an action, so a plan's type
134
+ states which implementations running it will need, and the place that runs it
135
+ is where the compiler asks for them. Each combinator unions its parts: `all`
136
+ over its members, `map` and `andThen` along the chain, `branch` over BOTH arms
137
+ and `catch` over its failure arm, because both arms of a decision are topology
138
+ the plan carries and a run has to be able to take either.
139
+
140
+ **Planning performs no I/O.** Nothing here reads a file, a clock, or a network.
141
+ A node's declared `effects` carry read and write _paths_, never digests, since
142
+ measuring them is the scheduler's run-time job.
143
+
144
+ **Invalidation is re-keying.** A node's key is a function of what it consumes,
145
+ so an edited declaration re-keys that node and its dependent cone and nothing
146
+ else. There is deliberately **no reverse-dependency index and no invalidating
147
+ node visitor**: content addressing subsumes both.
148
+
149
+ **A plan grows; it is never rewritten.** `append` adds a pre-keyed subgraph at
150
+ the next generation. Recorded nodes keep their id, key, edges, and generation
151
+ byte for byte, and the SQL raises rather than letting a caller update or delete
152
+ one. Re-ordering after a reconciliation happens by re-keying _future_ steps.
153
+ Appending to a plan that was never recorded, or over a skipped generation, is a
154
+ `constraint` refusal, because the alternative is node rows for a plan that does
155
+ not exist and that the append-only triggers then forbid removing.
156
+
157
+ ## Conflict annotations
158
+
159
+ Declared write sets make overlap detectable at plan time. `compile` annotates
160
+ both members of every overlapping pair that no dependency path already orders:
161
+ `serialize` is the default and gives the later writer an ordering edge that is
162
+ deliberately not key material, so a serialized node keeps its cache hit; `lane`
163
+ gives both writers lane annotations and no edge; `fail` refuses the compile,
164
+ for flows that promise disjointness. Each annotation also carries the runtime
165
+ strategy, `delay-rebase` or `stop-merge`, and both strategies are folded into
166
+ the plan digest a human approves.
167
+
168
+ A node that reads a path another node writes is not a conflict but a missing
169
+ edge: `compile` puts the reader behind its producer by growing `dependsOn`, and
170
+ fails with `cycle` when no edge set can satisfy both that and the declared
171
+ order.
172
+
173
+ [Declared effects and conflicts](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/concepts/effects-and-conflicts.md)
174
+ covers both passes in full.
175
+
176
+ ## When it refuses
177
+
178
+ `Plan.compile` and `Plan.append` fail with a `PlanError` carrying one of seven
179
+ stable codes: `cycle`, `unknown_dependency`, `duplicate_node`,
180
+ `overlap_forbidden`, `invalid_effects`, `invalid_node`, and `graph_too_large`.
181
+ `Plan.verify`, which every store read and write runs, adds an eighth,
182
+ `invalid_plan`: the plan decoded but its generations, approval digest, keys,
183
+ effects, or ordering do not match its content. A plan-time build refuses
184
+ through `GraphBuildError`, whose closed code set names the site and the fix;
185
+ `unstable_callback` in that set is raised by `@smthrs/flow` when a stable build
186
+ meets a callback without a `Node.capture` declaration. Persistence has its own
187
+ refusals, all of them
188
+ [`@smthrs/plan-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan-store/docs)'s.
189
+
190
+ [Troubleshooting](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/troubleshooting.md) lists every code
191
+ with the change that clears it.
192
+
193
+ ## Paths, payloads, and immutability
194
+
195
+ Declared paths are workspace-relative and compared in one spelling:
196
+ `FileSet.canonical` rewrites every separator to `/` and normalizes to Unicode
197
+ NFC, and `FileSet.workspaceRelative` refuses absolute paths, drive letters,
198
+ `..` and `.` segments, empty segments, the C0 control range, and DEL.
199
+
200
+ A node payload is stored as its inert JSON mirror, so a data-valued `toJSON` is
201
+ honoured while an accessor or an unsupported prototype fails with
202
+ `invalid_payload` rather than executing author code or collapsing distinct
203
+ values onto `{}`. That mirror is identity material: it is hashed into the step
204
+ key and persisted verbatim as plaintext in `node_json` and in the approval card,
205
+ and this package never redacts it. Keep credentials out of payloads. A secret
206
+ belongs in a layer, a capability, or the environment, resolved at dispatch. `Node.succeed(input)` returns `Node<Succeed<typeof input>>`:
207
+ the success type describes that projection. Dates become `string | null`, URLs
208
+ become strings, and callable object members disappear. Planned references
209
+ resolve to their result types. Reconstruct domain objects explicitly in
210
+ `Node.map` when needed. A compiled plan is deep-frozen: mutating the draft objects
211
+ you passed in cannot change the plan, its keys, or its digest.
212
+
213
+ `Plan.maximumPlanNodes` bounds compilation. The conflict and
214
+ reader-after-writer passes compare node pairs, so a plan above that bound is
215
+ refused with `graph_too_large` before any pair is compared.
216
+
217
+ ## Browser support
218
+
219
+ Browser-safe: the package resolves no `node:` built-in and binds no database,
220
+ so compiling, diffing, and building node graphs all work in a browser.
221
+ Persistence is a separate package, which is where a platform choice enters.
222
+
223
+ ## Links
224
+
225
+ - [Documentation](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan/docs)
226
+ - [API reference](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/api.md)
227
+ - [`@smthrs/plan-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan-store/docs), the append-only store
228
+ a compiled plan is recorded in
229
+ - [`@smthrs/flows`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/docs), the whole engine as a single
230
+ dependency, which re-exports this package as its `Plan` namespace
231
+ - [License: MIT](./LICENSE)
@@ -0,0 +1,48 @@
1
+ # Third-party notices
2
+
3
+ This distribution contains third-party software. The notice below is
4
+ reproduced to satisfy the terms of the license that component is distributed
5
+ under. It is in addition to, and does not replace, the project's own `LICENSE`.
6
+
7
+ ## Effect (`Effect-TS/effect`)
8
+
9
+ `@smthrs/plan` prints a schema's identity with an adapted copy of the JSON
10
+ Schema emitter of one Effect release, so that the identity does not change
11
+ with the Effect release an application installs. `src/internal/SchemaIdentity.ts`
12
+ contains substantial portions of that source and records how it was changed:
13
+
14
+ - Upstream repository: `Effect-TS/effect`
15
+ - Upstream package: `effect@4.0.0-rc.115`
16
+ - Upstream sources: `src/internal/schema/toJsonSchemaDocument.ts`,
17
+ `src/JsonSchema.ts` (`rewriteRefs`), `src/JsonPointer.ts`, and
18
+ `src/SchemaAST.ts` (`isJson`)
19
+
20
+ Effect is distributed under the MIT License. Its copyright and permission
21
+ notice is reproduced here verbatim:
22
+
23
+ ```
24
+ MIT License
25
+
26
+ Copyright (c) 2023 Effectful Technologies Inc
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining a copy
29
+ of this software and associated documentation files (the "Software"), to deal
30
+ in the Software without restriction, including without limitation the rights
31
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32
+ copies of the Software, and to permit persons to whom the Software is
33
+ furnished to do so, subject to the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be included in all
36
+ copies or substantial portions of the Software.
37
+
38
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44
+ SOFTWARE.
45
+ ```
46
+
47
+ `@smthrs/plan` also depends on Effect at runtime, so the notice above applies
48
+ to that dependency as well as to the adapted source.
@@ -0,0 +1,131 @@
1
+ /**
2
+ * The caller-declared cache policy: how far a recorded sealed result may
3
+ * travel, and how long it stays servable.
4
+ *
5
+ * This is the ONE cache-policy model. `@smthrs/flow` publishes it as
6
+ * `CacheEnvironment.CachePolicy` and the engine reads it off a dispatched
7
+ * action; `@smthrs/patterns` declares it over a flow as `WithCache.Policy`. It
8
+ * used to be two declarations in those two packages, tied together by nothing
9
+ * but a re-typed identifier string, so a field added on one side was invisible
10
+ * to the other. It lives here because `@smthrs/plan` is the package both
11
+ * already depend on.
12
+ *
13
+ * The annotation key still reads `"@smthrs/flow/Action/CachePolicy"`.
14
+ * `@smthrs/engine-store`'s `ActionPersistence` reads the policy off stored and
15
+ * dispatched actions by that identifier, so retagging it would make every
16
+ * policy already written invisible at dispatch. The identifier is a wire
17
+ * value, not a location.
18
+ *
19
+ * @since 1.0.0-rc.0
20
+ */
21
+ import * as Context from "effect/Context";
22
+ import * as Schema from "effect/Schema";
23
+ /**
24
+ * How far a recorded sealed result may travel.
25
+ *
26
+ * `shared` is the content-addressed default: the key names the inputs and the
27
+ * environment, so any run on any host that would have produced the same bytes
28
+ * may reuse the row. `run` and `flow` narrow that on purpose — a step whose
29
+ * result is only meaningful inside one execution, or inside one flow, folds
30
+ * that identity into its key so a sibling never reads it.
31
+ *
32
+ * The old scope vocabulary was `run | workflow | global`; `flow` and `shared`
33
+ * are the same three levels named after the current concepts.
34
+ *
35
+ * @category models
36
+ * @since 1.0.0-rc.0
37
+ */
38
+ export declare const CacheScope: Schema.Literals<readonly ["run", "flow", "shared"]>;
39
+ /**
40
+ * The value form of {@link CacheScope}.
41
+ *
42
+ * @category models
43
+ * @since 1.0.0-rc.0
44
+ */
45
+ export type CacheScope = typeof CacheScope.Type;
46
+ /**
47
+ * The caller's declaration about the decay and the reach of a sealed result.
48
+ *
49
+ * `ttlMs` bounds the age of a row the engine may serve: past it the dispatch
50
+ * executes again and journals `cache-expired`, so the refusal is durable
51
+ * evidence a replay reads rather than a fresh clock reading. `scope` decides
52
+ * what the key names besides the inputs.
53
+ *
54
+ * Both fields are optional and both defaults are the pre-policy behavior: no
55
+ * age bound, and the reach the composition's cache environment already
56
+ * granted.
57
+ *
58
+ * @category schemas
59
+ * @since 1.0.0-rc.0
60
+ */
61
+ export declare const CachePolicy: Schema.Struct<{
62
+ readonly ttlMs: Schema.optionalKey<Schema.Int>;
63
+ readonly scope: Schema.optionalKey<Schema.Literals<readonly ["run", "flow", "shared"]>>;
64
+ }>;
65
+ /**
66
+ * The value form of {@link CachePolicy}.
67
+ *
68
+ * @category models
69
+ * @since 1.0.0-rc.0
70
+ */
71
+ export type CachePolicy = typeof CachePolicy.Type;
72
+ /**
73
+ * Annotation key carrying a declaration's {@link CachePolicy}.
74
+ *
75
+ * It is an annotation, not a field on the declaration, for the same reason
76
+ * placement and effects are: the policy is data that travels with the
77
+ * declaration and is read by whoever executes it, and adding it changes no
78
+ * existing call site.
79
+ *
80
+ * @category annotations
81
+ * @since 1.0.0-rc.0
82
+ */
83
+ export declare const CachePolicyAnnotation: Context.Service<{
84
+ readonly ttlMs?: number;
85
+ readonly scope?: "run" | "flow" | "shared";
86
+ }, {
87
+ readonly ttlMs?: number;
88
+ readonly scope?: "run" | "flow" | "shared";
89
+ }>;
90
+ /**
91
+ * Reads the cache policy an annotation bag carries, or `undefined` when it
92
+ * carries none.
93
+ *
94
+ * @category getters
95
+ * @since 1.0.0-rc.0
96
+ */
97
+ export declare const cachePolicyOf: (annotations: Context.Context<never>) => CachePolicy | undefined;
98
+ /**
99
+ * Attaches a cache policy to a declaration that can carry annotations.
100
+ *
101
+ * The declaration is not mutated: `annotate` answers a new one carrying the
102
+ * policy, which is what a plan captures. It is written against the `annotate`
103
+ * method rather than against an action or a flow type so the one declaration
104
+ * serves both, which is what `@smthrs/flow` publishes as
105
+ * `CacheEnvironment.withCache`.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * import { CachePolicy } from "@smthrs/plan"
110
+ * import { Action } from "@smthrs/flow"
111
+ * import * as Effect from "effect/Effect"
112
+ * import * as Schema from "effect/Schema"
113
+ *
114
+ * const compile = CachePolicy.annotate(
115
+ * Action.make({
116
+ * name: "build/compile",
117
+ * success: Schema.String,
118
+ * tier: "sealed",
119
+ * execute: Effect.succeed("dist/server.js")
120
+ * }),
121
+ * { ttlMs: 60_000, scope: "shared" }
122
+ * )
123
+ * ```
124
+ *
125
+ * @category combinators
126
+ * @since 1.0.0-rc.0
127
+ */
128
+ export declare const annotate: <A extends {
129
+ annotate: (key: typeof CachePolicyAnnotation, value: CachePolicy) => A;
130
+ }>(declaration: A, policy: CachePolicy) => A;
131
+ //# sourceMappingURL=CachePolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CachePolicy.d.ts","sourceRoot":"","sources":["../../src/CachePolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU,qDAA6C,CAAA;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAU/C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW;;;EAGtB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB;;;;;;EAAkE,CAAA;AAEpG;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,aAAa,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAG,WAAW,GAAG,SACJ,CAAA;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS;IAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,qBAAqB,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC,CAAA;CAAE,EAC3G,aAAa,CAAC,EACd,QAAQ,WAAW,KAClB,CAAwD,CAAA"}