@smthrs/plan 1.0.0-rc.6 → 1.0.0-rc.8

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 CHANGED
@@ -6,7 +6,7 @@ This package declares `effect` as a `^4.0.4` peer dependency. Install one
6
6
  `effect` release in that range so all Smithers packages share one Effect
7
7
  runtime.
8
8
 
9
- **Documentation:** https://plan.smithers.sh
9
+ **Documentation:** https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan/docs
10
10
 
11
11
  The persisted plan: a keyed action graph, its append-only store, its diff, and
12
12
  the step-key compiler that gives every node its identity.
@@ -17,7 +17,7 @@ from what that node declares, records that graph in a SQLite store that only
17
17
  ever grows, and compares two graphs to say exactly what changed. It runs
18
18
  nothing itself: it performs no I/O beyond the database, and driving a compiled
19
19
  plan is a scheduler's job, such as
20
- [`@smthrs/engine-store`](https://engine-store.smithers.sh)'s `PlanScheduler`.
20
+ [`@smthrs/engine-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/engine-store/docs)'s `PlanScheduler`.
21
21
 
22
22
  Reach for it when you are building a scheduler, a cache, or an approval flow
23
23
  over declared work and you need step identity, declared file effects, and an
@@ -25,7 +25,9 @@ auditable history as values you can hold, hash, and store.
25
25
 
26
26
  ## Install
27
27
 
28
- Not on npm yet; see [Installation](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/flow/docs/installation.md#use-the-libraries).
28
+ ```bash
29
+ npm install @smthrs/plan@next effect
30
+ ```
29
31
 
30
32
  Compiling asks Effect for its `Crypto` service, which a platform package
31
33
  supplies:
@@ -35,8 +37,8 @@ pnpm add @effect/platform-node @effect/platform-node-shared
35
37
  ```
36
38
 
37
39
  Node.js 26.4.0 or later, and `effect` `^4.0.4` as a peer. Recording a plan
38
- is [`@smthrs/plan-store`](https://plan-store.smithers.sh), which owns the SQL
39
- and brings [`@smthrs/database`](https://database.smithers.sh) with it.
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.
40
42
 
41
43
  ## Compile a plan
42
44
 
@@ -100,8 +102,8 @@ another number and both keys move; rename `read-pr` to `fetch-pr` and neither
100
102
  does.
101
103
 
102
104
  Recording that plan is
103
- [`@smthrs/plan-store`](https://plan-store.smithers.sh), whose
104
- [quickstart](https://plan-store.smithers.sh/quickstart/) builds the whole
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
105
107
  composition against an in-memory database.
106
108
 
107
109
  ## What is in here
@@ -168,7 +170,7 @@ edge: `compile` puts the reader behind its producer by growing `dependsOn`, and
168
170
  fails with `cycle` when no edge set can satisfy both that and the declared
169
171
  order.
170
172
 
171
- [Declared effects and conflicts](https://plan.smithers.sh/concepts/effects-and-conflicts/)
173
+ [Declared effects and conflicts](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/concepts/effects-and-conflicts.md)
172
174
  covers both passes in full.
173
175
 
174
176
  ## When it refuses
@@ -183,9 +185,9 @@ through `GraphBuildError`, whose closed code set names the site and the fix;
183
185
  `unstable_callback` in that set is raised by `@smthrs/flow` when a stable build
184
186
  meets a callback without a `Node.capture` declaration. Persistence has its own
185
187
  refusals, all of them
186
- [`@smthrs/plan-store`](https://plan-store.smithers.sh)'s.
188
+ [`@smthrs/plan-store`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/plan-store/docs)'s.
187
189
 
188
- [Troubleshooting](https://plan.smithers.sh/troubleshooting/) lists every code
190
+ [Troubleshooting](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/troubleshooting.md) lists every code
189
191
  with the change that clears it.
190
192
 
191
193
  ## Paths, payloads, and immutability
@@ -220,10 +222,10 @@ Persistence is a separate package, which is where a platform choice enters.
220
222
 
221
223
  ## Links
222
224
 
223
- - [Documentation](https://plan.smithers.sh)
224
- - [API reference](https://plan.smithers.sh/reference/api/)
225
- - [`@smthrs/plan-store`](https://plan-store.smithers.sh), the append-only store
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
226
228
  a compiled plan is recorded in
227
- - [`@smthrs/flows`](https://flows.smithers.sh), the whole engine as a single
229
+ - [`@smthrs/flows`](https://github.com/smithersai/smithers/tree/main/packages/smithers/flows/docs), the whole engine as a single
228
230
  dependency, which re-exports this package as its `Plan` namespace
229
231
  - [License: MIT](./LICENSE)
@@ -6,10 +6,10 @@
6
6
  * 'what is different about this run' is a set comparison, not archaeology."
7
7
  * This module is the set comparison.
8
8
  *
9
- * The **verdict** is the key: two nodes with the same id and the same key are
10
- * the same step and nothing else needs saying. The **attribution** —
11
- * `changed: ["input[1]"]` — is a report for a human, derived by comparing the
12
- * declarations field by field. It is deliberately not part of any digest.
9
+ * The **verdict** is the key: two nodes with the same key are the same step,
10
+ * under the same id or a moved one, and nothing else needs saying. The
11
+ * **attribution** — `changed: ["input[1]"]` — is a report for a human, derived
12
+ * by comparing the declarations field by field. It is deliberately not part of any digest.
13
13
  *
14
14
  * @since 0.1.0
15
15
  */
@@ -50,6 +50,21 @@ export interface PlanDiff {
50
50
  /**
51
51
  * Compares a plan against the last plan for the same flow.
52
52
  *
53
+ * Nodes pair in three passes, each over the nodes no earlier pass paired:
54
+ * the same id with the same key, then the same key under any id, then the
55
+ * same id with a different key. The second pass exists because flow node ids
56
+ * can be positional: inserting a step shifts the ids after it while their
57
+ * keys stay equal, and that is one added step, not a re-key of every later
58
+ * one (#3905).
59
+ *
60
+ * `added`, `rekeyed`, and `unchanged` name nodes by their id in `next`;
61
+ * `removed` names nodes by their id in `previous`. A moved id can therefore
62
+ * appear once in `removed` or `added` and once in `unchanged`.
63
+ *
64
+ * @param previous - The last plan recorded for the flow.
65
+ * @param next - The plan to compare against it.
66
+ * @returns The added, removed, re-keyed, and unchanged node ids, each in its
67
+ * plan's node order.
53
68
  * @since 0.1.0
54
69
  * @category constructors
55
70
  * @slop
@@ -1 +1 @@
1
- {"version":3,"file":"PlanDiff.d.ts","sourceRoot":"","sources":["../../src/PlanDiff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAA;AAGtC;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IACxC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAC1C;AAuGD;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GAAI,UAAU,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,KAAG,QAmC3D,CAAA"}
1
+ {"version":3,"file":"PlanDiff.d.ts","sourceRoot":"","sources":["../../src/PlanDiff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAA;AAGtC;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IACxC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAC1C;AAuGD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,IAAI,GAAI,UAAU,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,KAAG,QA6D3D,CAAA"}
@@ -86,19 +86,44 @@ const changedFields = (previous, next, rekeyedDependencies, sameField) => {
86
86
  return changed;
87
87
  };
88
88
  const diff = (previous, next) => {
89
+ const pairs = /* @__PURE__ */ new Map();
90
+ const paired = /* @__PURE__ */ new Set();
91
+ const pair = (node, original) => {
92
+ pairs.set(node, original);
93
+ paired.add(original);
94
+ };
89
95
  const before = new Map(previous.nodes.map((node) => [node.id, node]));
90
- const after = new Map(next.nodes.map((node) => [node.id, node]));
96
+ for (const node of next.nodes) {
97
+ const original = before.get(node.id);
98
+ if (original !== void 0 && original.key === node.key) pair(node, original);
99
+ }
100
+ const byKey = /* @__PURE__ */ new Map();
101
+ for (const node of previous.nodes) {
102
+ if (paired.has(node)) continue;
103
+ const same = byKey.get(node.key);
104
+ if (same === void 0) byKey.set(node.key, [node]);
105
+ else same.push(node);
106
+ }
107
+ for (const node of next.nodes) {
108
+ if (pairs.has(node)) continue;
109
+ const original = byKey.get(node.key)?.shift();
110
+ if (original !== void 0) pair(node, original);
111
+ }
91
112
  const rekeyedIds = /* @__PURE__ */ new Set();
92
113
  for (const node of next.nodes) {
114
+ if (pairs.has(node)) continue;
93
115
  const original = before.get(node.id);
94
- if (original !== void 0 && original.key !== node.key) rekeyedIds.add(node.id);
116
+ if (original !== void 0 && !paired.has(original)) {
117
+ pair(node, original);
118
+ rekeyedIds.add(node.id);
119
+ }
95
120
  }
96
121
  const added = [];
97
122
  const rekeyed = [];
98
123
  const unchanged = [];
99
124
  const sameField = fieldComparison();
100
125
  for (const node of next.nodes) {
101
- const original = before.get(node.id);
126
+ const original = pairs.get(node);
102
127
  if (original === void 0) {
103
128
  added.push(node.id);
104
129
  continue;
@@ -116,7 +141,7 @@ const diff = (previous, next) => {
116
141
  }
117
142
  return {
118
143
  added,
119
- removed: previous.nodes.filter((node) => !after.has(node.id)).map((node) => node.id),
144
+ removed: previous.nodes.filter((node) => !paired.has(node)).map((node) => node.id),
120
145
  rekeyed,
121
146
  unchanged
122
147
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/PlanDiff.ts"],
4
- "sourcesContent": ["/**\n * A plan comparison, as a value.\n *\n * A plan diff answers \"which steps changed key (and _which input_\n * changed them), what entered the envelope, what joined the release set \u2014\n * 'what is different about this run' is a set comparison, not archaeology.\"\n * This module is the set comparison.\n *\n * The **verdict** is the key: two nodes with the same id and the same key are\n * the same step and nothing else needs saying. The **attribution** \u2014\n * `changed: [\"input[1]\"]` \u2014 is a report for a human, derived by comparing the\n * declarations field by field. It is deliberately not part of any digest.\n *\n * @since 0.1.0\n */\n\nimport { jsonMirror } from \"./internal/JsonMirror.ts\"\nimport type * as Plan from \"./Plan.ts\"\nimport type * as Planned from \"./Planned.ts\"\n\n/**\n * A node whose key moved, with the fields that moved it.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface Rekeyed {\n readonly id: string\n readonly from: string\n readonly to: string\n /**\n * Field labels such as `\"kind\"`, `\"body\"`, `\"layers\"`, `\"capabilities\"`,\n * `\"effects\"`, and `\"input[0]\"` whose declaration differs. `\"kind\"` is the\n * effect tier (`sealed`, `compensable`, or `irreversible`). A\n * `Pending`-referenced upstream re-key is attributed to that input position\n * too. `changed` is empty only when none of the compared fields moved.\n */\n readonly changed: ReadonlyArray<string>\n}\n\n/**\n * What changed between two plans of the same flow.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface PlanDiff {\n readonly added: ReadonlyArray<string>\n readonly removed: ReadonlyArray<string>\n readonly rekeyed: ReadonlyArray<Rekeyed>\n readonly unchanged: ReadonlyArray<string>\n}\n\n/**\n * Order-insensitive structural comparison for the attribution report only.\n * Digests go through RFC 8785 canonical JSON; this does not have to, and\n * saying so keeps the two from being confused.\n *\n * @private\n */\nconst stable = (value: unknown): string => {\n if (typeof value === \"bigint\") return `${value}n`\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"undefined\"\n if (Array.isArray(value)) return `[${value.map(stable).join(\",\")}]`\n const entries = Object.entries(value as Record<string, unknown>).sort(([left], [right]) => left < right ? -1 : 1)\n return `{${entries.map(([name, entry]) => `${JSON.stringify(name)}:${stable(entry)}`).join(\",\")}}`\n}\n\n/**\n * A planned value compares as the reference an AST stores for it, so the same\n * reference at the same place is unchanged.\n *\n * @private\n */\nconst plannedReference = (_value: unknown, reference: Planned.Reference) => ({\n _tag: \"PlannedReference\",\n node: reference.node,\n path: reference.path\n})\n\n/** @private */\ntype ComparisonToken = string | symbol\n\n/**\n * Projects compared fields through the key's JSON semantics. A refused value\n * receives an identity token scoped to its node and field, so the same value\n * remains equal to itself without equating two distinct refused values.\n *\n * @private\n */\nconst fieldComparison = () => {\n const refused = new Map<unknown, Map<string, symbol>>()\n const token = (input: unknown, nodeId: string, field: string): ComparisonToken => {\n try {\n return stable(jsonMirror(input, plannedReference))\n } catch {\n const address = JSON.stringify([nodeId, field])\n let fields = refused.get(input)\n if (fields === undefined) {\n fields = new Map()\n refused.set(input, fields)\n }\n let sentinel = fields.get(address)\n if (sentinel === undefined) {\n sentinel = Symbol(address)\n fields.set(address, sentinel)\n }\n return sentinel\n }\n }\n return (previous: unknown, next: unknown, nodeId: string, field: string): boolean =>\n token(previous, nodeId, field) === token(next, nodeId, field)\n}\n\n/** @private */\nconst changedFields = (\n previous: Plan.PlanNode,\n next: Plan.PlanNode,\n rekeyedDependencies: ReadonlySet<string>,\n sameField: ReturnType<typeof fieldComparison>\n): ReadonlyArray<string> => {\n const changed: Array<string> = []\n // StepKey.materialBody is the identity list this attribution must mirror.\n // Inputs, layers, and capabilities complete fromKeyMaterial's hashed value,\n // and material.kind selects the key namespace (content versus tier-bearing\n // plan declaration), so a tier-only move still re-keys and is blamed here.\n if (!sameField(previous.material.version, next.material.version, next.id, \"version\")) changed.push(\"version\")\n if (previous.material.kind !== next.material.kind) changed.push(\"kind\")\n if (!sameField(previous.material.body, next.material.body, next.id, \"body\")) changed.push(\"body\")\n if (!sameField(previous.material.nondeterministic, next.material.nondeterministic, next.id, \"nondeterministic\")) {\n changed.push(\"nondeterministic\")\n }\n if (!sameField(previous.material.effects, next.material.effects, next.id, \"effects\")) changed.push(\"effects\")\n if (!sameField(previous.material.placement, next.material.placement, next.id, \"placement\")) {\n changed.push(\"placement\")\n }\n const width = Math.max(previous.material.inputs.length, next.material.inputs.length)\n for (let index = 0; index < width; index++) {\n const before = previous.material.inputs[index]\n const after = next.material.inputs[index]\n const field = `input[${index}]`\n if (before === undefined || after === undefined || !sameField(before, after, next.id, field)) {\n changed.push(field)\n continue\n }\n if (after._tag !== \"Literal\" && rekeyedDependencies.has(after.from)) changed.push(field)\n }\n if (!sameField(previous.material.layers, next.material.layers, next.id, \"layers\")) changed.push(\"layers\")\n if (!sameField(previous.material.capabilities, next.material.capabilities, next.id, \"capabilities\")) {\n changed.push(\"capabilities\")\n }\n return changed\n}\n\n/**\n * Compares a plan against the last plan for the same flow.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const diff = (previous: Plan.Plan, next: Plan.Plan): PlanDiff => {\n const before = new Map(previous.nodes.map((node) => [node.id, node]))\n const after = new Map(next.nodes.map((node) => [node.id, node]))\n const rekeyedIds = new Set<string>()\n for (const node of next.nodes) {\n const original = before.get(node.id)\n if (original !== undefined && original.key !== node.key) rekeyedIds.add(node.id)\n }\n const added: Array<string> = []\n const rekeyed: Array<Rekeyed> = []\n const unchanged: Array<string> = []\n const sameField = fieldComparison()\n for (const node of next.nodes) {\n const original = before.get(node.id)\n if (original === undefined) {\n added.push(node.id)\n continue\n }\n if (original.key === node.key) {\n unchanged.push(node.id)\n continue\n }\n rekeyed.push({\n id: node.id,\n from: original.key,\n to: node.key,\n changed: changedFields(original, node, rekeyedIds, sameField)\n })\n }\n return {\n added,\n removed: previous.nodes.filter((node) => !after.has(node.id)).map((node) => node.id),\n rekeyed,\n unchanged\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,wBAA2B;AA8C3B,MAAM,SAAS,CAAC,UAA2B;AACzC,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,KAAK;AAC9C,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK,KAAK;AACjF,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,MAAM,EAAE,KAAK,GAAG,CAAC;AAChE,QAAM,UAAU,OAAO,QAAQ,KAAgC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,OAAO,QAAQ,KAAK,CAAC;AAChH,SAAO,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,GAAG,KAAK,UAAU,IAAI,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC;AACjG;AAQA,MAAM,mBAAmB,CAAC,QAAiB,eAAkC;AAAA,EAC3E,MAAM;AAAA,EACN,MAAM,UAAU;AAAA,EAChB,MAAM,UAAU;AAClB;AAYA,MAAM,kBAAkB,MAAM;AAC5B,QAAM,UAAU,oBAAI,IAAkC;AACtD,QAAM,QAAQ,CAAC,OAAgB,QAAgB,UAAmC;AAChF,QAAI;AACF,aAAO,WAAO,8BAAW,OAAO,gBAAgB,CAAC;AAAA,IACnD,QAAQ;AACN,YAAM,UAAU,KAAK,UAAU,CAAC,QAAQ,KAAK,CAAC;AAC9C,UAAI,SAAS,QAAQ,IAAI,KAAK;AAC9B,UAAI,WAAW,QAAW;AACxB,iBAAS,oBAAI,IAAI;AACjB,gBAAQ,IAAI,OAAO,MAAM;AAAA,MAC3B;AACA,UAAI,WAAW,OAAO,IAAI,OAAO;AACjC,UAAI,aAAa,QAAW;AAC1B,mBAAW,OAAO,OAAO;AACzB,eAAO,IAAI,SAAS,QAAQ;AAAA,MAC9B;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,CAAC,UAAmB,MAAe,QAAgB,UACxD,MAAM,UAAU,QAAQ,KAAK,MAAM,MAAM,MAAM,QAAQ,KAAK;AAChE;AAGA,MAAM,gBAAgB,CACpB,UACA,MACA,qBACA,cAC0B;AAC1B,QAAM,UAAyB,CAAC;AAKhC,MAAI,CAAC,UAAU,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK,IAAI,SAAS,EAAG,SAAQ,KAAK,SAAS;AAC5G,MAAI,SAAS,SAAS,SAAS,KAAK,SAAS,KAAM,SAAQ,KAAK,MAAM;AACtE,MAAI,CAAC,UAAU,SAAS,SAAS,MAAM,KAAK,SAAS,MAAM,KAAK,IAAI,MAAM,EAAG,SAAQ,KAAK,MAAM;AAChG,MAAI,CAAC,UAAU,SAAS,SAAS,kBAAkB,KAAK,SAAS,kBAAkB,KAAK,IAAI,kBAAkB,GAAG;AAC/G,YAAQ,KAAK,kBAAkB;AAAA,EACjC;AACA,MAAI,CAAC,UAAU,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK,IAAI,SAAS,EAAG,SAAQ,KAAK,SAAS;AAC5G,MAAI,CAAC,UAAU,SAAS,SAAS,WAAW,KAAK,SAAS,WAAW,KAAK,IAAI,WAAW,GAAG;AAC1F,YAAQ,KAAK,WAAW;AAAA,EAC1B;AACA,QAAM,QAAQ,KAAK,IAAI,SAAS,SAAS,OAAO,QAAQ,KAAK,SAAS,OAAO,MAAM;AACnF,WAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS;AAC1C,UAAM,SAAS,SAAS,SAAS,OAAO,KAAK;AAC7C,UAAM,QAAQ,KAAK,SAAS,OAAO,KAAK;AACxC,UAAM,QAAQ,SAAS,KAAK;AAC5B,QAAI,WAAW,UAAa,UAAU,UAAa,CAAC,UAAU,QAAQ,OAAO,KAAK,IAAI,KAAK,GAAG;AAC5F,cAAQ,KAAK,KAAK;AAClB;AAAA,IACF;AACA,QAAI,MAAM,SAAS,aAAa,oBAAoB,IAAI,MAAM,IAAI,EAAG,SAAQ,KAAK,KAAK;AAAA,EACzF;AACA,MAAI,CAAC,UAAU,SAAS,SAAS,QAAQ,KAAK,SAAS,QAAQ,KAAK,IAAI,QAAQ,EAAG,SAAQ,KAAK,QAAQ;AACxG,MAAI,CAAC,UAAU,SAAS,SAAS,cAAc,KAAK,SAAS,cAAc,KAAK,IAAI,cAAc,GAAG;AACnG,YAAQ,KAAK,cAAc;AAAA,EAC7B;AACA,SAAO;AACT;AASO,MAAM,OAAO,CAAC,UAAqB,SAA8B;AACtE,QAAM,SAAS,IAAI,IAAI,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACpE,QAAM,QAAQ,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC/D,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,QAAQ,KAAK,OAAO;AAC7B,UAAM,WAAW,OAAO,IAAI,KAAK,EAAE;AACnC,QAAI,aAAa,UAAa,SAAS,QAAQ,KAAK,IAAK,YAAW,IAAI,KAAK,EAAE;AAAA,EACjF;AACA,QAAM,QAAuB,CAAC;AAC9B,QAAM,UAA0B,CAAC;AACjC,QAAM,YAA2B,CAAC;AAClC,QAAM,YAAY,gBAAgB;AAClC,aAAW,QAAQ,KAAK,OAAO;AAC7B,UAAM,WAAW,OAAO,IAAI,KAAK,EAAE;AACnC,QAAI,aAAa,QAAW;AAC1B,YAAM,KAAK,KAAK,EAAE;AAClB;AAAA,IACF;AACA,QAAI,SAAS,QAAQ,KAAK,KAAK;AAC7B,gBAAU,KAAK,KAAK,EAAE;AACtB;AAAA,IACF;AACA,YAAQ,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,MAAM,SAAS;AAAA,MACf,IAAI,KAAK;AAAA,MACT,SAAS,cAAc,UAAU,MAAM,YAAY,SAAS;AAAA,IAC9D,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,IACnF;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * A plan comparison, as a value.\n *\n * A plan diff answers \"which steps changed key (and _which input_\n * changed them), what entered the envelope, what joined the release set \u2014\n * 'what is different about this run' is a set comparison, not archaeology.\"\n * This module is the set comparison.\n *\n * The **verdict** is the key: two nodes with the same key are the same step,\n * under the same id or a moved one, and nothing else needs saying. The\n * **attribution** \u2014 `changed: [\"input[1]\"]` \u2014 is a report for a human, derived\n * by comparing the declarations field by field. It is deliberately not part of any digest.\n *\n * @since 0.1.0\n */\n\nimport { jsonMirror } from \"./internal/JsonMirror.ts\"\nimport type * as Plan from \"./Plan.ts\"\nimport type * as Planned from \"./Planned.ts\"\n\n/**\n * A node whose key moved, with the fields that moved it.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface Rekeyed {\n readonly id: string\n readonly from: string\n readonly to: string\n /**\n * Field labels such as `\"kind\"`, `\"body\"`, `\"layers\"`, `\"capabilities\"`,\n * `\"effects\"`, and `\"input[0]\"` whose declaration differs. `\"kind\"` is the\n * effect tier (`sealed`, `compensable`, or `irreversible`). A\n * `Pending`-referenced upstream re-key is attributed to that input position\n * too. `changed` is empty only when none of the compared fields moved.\n */\n readonly changed: ReadonlyArray<string>\n}\n\n/**\n * What changed between two plans of the same flow.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface PlanDiff {\n readonly added: ReadonlyArray<string>\n readonly removed: ReadonlyArray<string>\n readonly rekeyed: ReadonlyArray<Rekeyed>\n readonly unchanged: ReadonlyArray<string>\n}\n\n/**\n * Order-insensitive structural comparison for the attribution report only.\n * Digests go through RFC 8785 canonical JSON; this does not have to, and\n * saying so keeps the two from being confused.\n *\n * @private\n */\nconst stable = (value: unknown): string => {\n if (typeof value === \"bigint\") return `${value}n`\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"undefined\"\n if (Array.isArray(value)) return `[${value.map(stable).join(\",\")}]`\n const entries = Object.entries(value as Record<string, unknown>).sort(([left], [right]) => left < right ? -1 : 1)\n return `{${entries.map(([name, entry]) => `${JSON.stringify(name)}:${stable(entry)}`).join(\",\")}}`\n}\n\n/**\n * A planned value compares as the reference an AST stores for it, so the same\n * reference at the same place is unchanged.\n *\n * @private\n */\nconst plannedReference = (_value: unknown, reference: Planned.Reference) => ({\n _tag: \"PlannedReference\",\n node: reference.node,\n path: reference.path\n})\n\n/** @private */\ntype ComparisonToken = string | symbol\n\n/**\n * Projects compared fields through the key's JSON semantics. A refused value\n * receives an identity token scoped to its node and field, so the same value\n * remains equal to itself without equating two distinct refused values.\n *\n * @private\n */\nconst fieldComparison = () => {\n const refused = new Map<unknown, Map<string, symbol>>()\n const token = (input: unknown, nodeId: string, field: string): ComparisonToken => {\n try {\n return stable(jsonMirror(input, plannedReference))\n } catch {\n const address = JSON.stringify([nodeId, field])\n let fields = refused.get(input)\n if (fields === undefined) {\n fields = new Map()\n refused.set(input, fields)\n }\n let sentinel = fields.get(address)\n if (sentinel === undefined) {\n sentinel = Symbol(address)\n fields.set(address, sentinel)\n }\n return sentinel\n }\n }\n return (previous: unknown, next: unknown, nodeId: string, field: string): boolean =>\n token(previous, nodeId, field) === token(next, nodeId, field)\n}\n\n/** @private */\nconst changedFields = (\n previous: Plan.PlanNode,\n next: Plan.PlanNode,\n rekeyedDependencies: ReadonlySet<string>,\n sameField: ReturnType<typeof fieldComparison>\n): ReadonlyArray<string> => {\n const changed: Array<string> = []\n // StepKey.materialBody is the identity list this attribution must mirror.\n // Inputs, layers, and capabilities complete fromKeyMaterial's hashed value,\n // and material.kind selects the key namespace (content versus tier-bearing\n // plan declaration), so a tier-only move still re-keys and is blamed here.\n if (!sameField(previous.material.version, next.material.version, next.id, \"version\")) changed.push(\"version\")\n if (previous.material.kind !== next.material.kind) changed.push(\"kind\")\n if (!sameField(previous.material.body, next.material.body, next.id, \"body\")) changed.push(\"body\")\n if (!sameField(previous.material.nondeterministic, next.material.nondeterministic, next.id, \"nondeterministic\")) {\n changed.push(\"nondeterministic\")\n }\n if (!sameField(previous.material.effects, next.material.effects, next.id, \"effects\")) changed.push(\"effects\")\n if (!sameField(previous.material.placement, next.material.placement, next.id, \"placement\")) {\n changed.push(\"placement\")\n }\n const width = Math.max(previous.material.inputs.length, next.material.inputs.length)\n for (let index = 0; index < width; index++) {\n const before = previous.material.inputs[index]\n const after = next.material.inputs[index]\n const field = `input[${index}]`\n if (before === undefined || after === undefined || !sameField(before, after, next.id, field)) {\n changed.push(field)\n continue\n }\n if (after._tag !== \"Literal\" && rekeyedDependencies.has(after.from)) changed.push(field)\n }\n if (!sameField(previous.material.layers, next.material.layers, next.id, \"layers\")) changed.push(\"layers\")\n if (!sameField(previous.material.capabilities, next.material.capabilities, next.id, \"capabilities\")) {\n changed.push(\"capabilities\")\n }\n return changed\n}\n\n/**\n * Compares a plan against the last plan for the same flow.\n *\n * Nodes pair in three passes, each over the nodes no earlier pass paired:\n * the same id with the same key, then the same key under any id, then the\n * same id with a different key. The second pass exists because flow node ids\n * can be positional: inserting a step shifts the ids after it while their\n * keys stay equal, and that is one added step, not a re-key of every later\n * one (#3905).\n *\n * `added`, `rekeyed`, and `unchanged` name nodes by their id in `next`;\n * `removed` names nodes by their id in `previous`. A moved id can therefore\n * appear once in `removed` or `added` and once in `unchanged`.\n *\n * @param previous - The last plan recorded for the flow.\n * @param next - The plan to compare against it.\n * @returns The added, removed, re-keyed, and unchanged node ids, each in its\n * plan's node order.\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const diff = (previous: Plan.Plan, next: Plan.Plan): PlanDiff => {\n // pairs maps a next node to the previous node it is the same step as.\n const pairs = new Map<Plan.PlanNode, Plan.PlanNode>()\n const paired = new Set<Plan.PlanNode>()\n const pair = (node: Plan.PlanNode, original: Plan.PlanNode) => {\n pairs.set(node, original)\n paired.add(original)\n }\n const before = new Map(previous.nodes.map((node) => [node.id, node]))\n for (const node of next.nodes) {\n const original = before.get(node.id)\n if (original !== undefined && original.key === node.key) pair(node, original)\n }\n const byKey = new Map<string, Array<Plan.PlanNode>>()\n for (const node of previous.nodes) {\n if (paired.has(node)) continue\n const same = byKey.get(node.key)\n if (same === undefined) byKey.set(node.key, [node])\n else same.push(node)\n }\n for (const node of next.nodes) {\n if (pairs.has(node)) continue\n const original = byKey.get(node.key)?.shift()\n if (original !== undefined) pair(node, original)\n }\n const rekeyedIds = new Set<string>()\n for (const node of next.nodes) {\n if (pairs.has(node)) continue\n const original = before.get(node.id)\n if (original !== undefined && !paired.has(original)) {\n pair(node, original)\n rekeyedIds.add(node.id)\n }\n }\n const added: Array<string> = []\n const rekeyed: Array<Rekeyed> = []\n const unchanged: Array<string> = []\n const sameField = fieldComparison()\n for (const node of next.nodes) {\n const original = pairs.get(node)\n if (original === undefined) {\n added.push(node.id)\n continue\n }\n if (original.key === node.key) {\n unchanged.push(node.id)\n continue\n }\n rekeyed.push({\n id: node.id,\n from: original.key,\n to: node.key,\n changed: changedFields(original, node, rekeyedIds, sameField)\n })\n }\n return {\n added,\n removed: previous.nodes.filter((node) => !paired.has(node)).map((node) => node.id),\n rekeyed,\n unchanged\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,wBAA2B;AA8C3B,MAAM,SAAS,CAAC,UAA2B;AACzC,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,KAAK;AAC9C,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK,KAAK;AACjF,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,MAAM,EAAE,KAAK,GAAG,CAAC;AAChE,QAAM,UAAU,OAAO,QAAQ,KAAgC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,OAAO,QAAQ,KAAK,CAAC;AAChH,SAAO,IAAI,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,GAAG,KAAK,UAAU,IAAI,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC;AACjG;AAQA,MAAM,mBAAmB,CAAC,QAAiB,eAAkC;AAAA,EAC3E,MAAM;AAAA,EACN,MAAM,UAAU;AAAA,EAChB,MAAM,UAAU;AAClB;AAYA,MAAM,kBAAkB,MAAM;AAC5B,QAAM,UAAU,oBAAI,IAAkC;AACtD,QAAM,QAAQ,CAAC,OAAgB,QAAgB,UAAmC;AAChF,QAAI;AACF,aAAO,WAAO,8BAAW,OAAO,gBAAgB,CAAC;AAAA,IACnD,QAAQ;AACN,YAAM,UAAU,KAAK,UAAU,CAAC,QAAQ,KAAK,CAAC;AAC9C,UAAI,SAAS,QAAQ,IAAI,KAAK;AAC9B,UAAI,WAAW,QAAW;AACxB,iBAAS,oBAAI,IAAI;AACjB,gBAAQ,IAAI,OAAO,MAAM;AAAA,MAC3B;AACA,UAAI,WAAW,OAAO,IAAI,OAAO;AACjC,UAAI,aAAa,QAAW;AAC1B,mBAAW,OAAO,OAAO;AACzB,eAAO,IAAI,SAAS,QAAQ;AAAA,MAC9B;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,CAAC,UAAmB,MAAe,QAAgB,UACxD,MAAM,UAAU,QAAQ,KAAK,MAAM,MAAM,MAAM,QAAQ,KAAK;AAChE;AAGA,MAAM,gBAAgB,CACpB,UACA,MACA,qBACA,cAC0B;AAC1B,QAAM,UAAyB,CAAC;AAKhC,MAAI,CAAC,UAAU,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK,IAAI,SAAS,EAAG,SAAQ,KAAK,SAAS;AAC5G,MAAI,SAAS,SAAS,SAAS,KAAK,SAAS,KAAM,SAAQ,KAAK,MAAM;AACtE,MAAI,CAAC,UAAU,SAAS,SAAS,MAAM,KAAK,SAAS,MAAM,KAAK,IAAI,MAAM,EAAG,SAAQ,KAAK,MAAM;AAChG,MAAI,CAAC,UAAU,SAAS,SAAS,kBAAkB,KAAK,SAAS,kBAAkB,KAAK,IAAI,kBAAkB,GAAG;AAC/G,YAAQ,KAAK,kBAAkB;AAAA,EACjC;AACA,MAAI,CAAC,UAAU,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK,IAAI,SAAS,EAAG,SAAQ,KAAK,SAAS;AAC5G,MAAI,CAAC,UAAU,SAAS,SAAS,WAAW,KAAK,SAAS,WAAW,KAAK,IAAI,WAAW,GAAG;AAC1F,YAAQ,KAAK,WAAW;AAAA,EAC1B;AACA,QAAM,QAAQ,KAAK,IAAI,SAAS,SAAS,OAAO,QAAQ,KAAK,SAAS,OAAO,MAAM;AACnF,WAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS;AAC1C,UAAM,SAAS,SAAS,SAAS,OAAO,KAAK;AAC7C,UAAM,QAAQ,KAAK,SAAS,OAAO,KAAK;AACxC,UAAM,QAAQ,SAAS,KAAK;AAC5B,QAAI,WAAW,UAAa,UAAU,UAAa,CAAC,UAAU,QAAQ,OAAO,KAAK,IAAI,KAAK,GAAG;AAC5F,cAAQ,KAAK,KAAK;AAClB;AAAA,IACF;AACA,QAAI,MAAM,SAAS,aAAa,oBAAoB,IAAI,MAAM,IAAI,EAAG,SAAQ,KAAK,KAAK;AAAA,EACzF;AACA,MAAI,CAAC,UAAU,SAAS,SAAS,QAAQ,KAAK,SAAS,QAAQ,KAAK,IAAI,QAAQ,EAAG,SAAQ,KAAK,QAAQ;AACxG,MAAI,CAAC,UAAU,SAAS,SAAS,cAAc,KAAK,SAAS,cAAc,KAAK,IAAI,cAAc,GAAG;AACnG,YAAQ,KAAK,cAAc;AAAA,EAC7B;AACA,SAAO;AACT;AAwBO,MAAM,OAAO,CAAC,UAAqB,SAA8B;AAEtE,QAAM,QAAQ,oBAAI,IAAkC;AACpD,QAAM,SAAS,oBAAI,IAAmB;AACtC,QAAM,OAAO,CAAC,MAAqB,aAA4B;AAC7D,UAAM,IAAI,MAAM,QAAQ;AACxB,WAAO,IAAI,QAAQ;AAAA,EACrB;AACA,QAAM,SAAS,IAAI,IAAI,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACpE,aAAW,QAAQ,KAAK,OAAO;AAC7B,UAAM,WAAW,OAAO,IAAI,KAAK,EAAE;AACnC,QAAI,aAAa,UAAa,SAAS,QAAQ,KAAK,IAAK,MAAK,MAAM,QAAQ;AAAA,EAC9E;AACA,QAAM,QAAQ,oBAAI,IAAkC;AACpD,aAAW,QAAQ,SAAS,OAAO;AACjC,QAAI,OAAO,IAAI,IAAI,EAAG;AACtB,UAAM,OAAO,MAAM,IAAI,KAAK,GAAG;AAC/B,QAAI,SAAS,OAAW,OAAM,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC;AAAA,QAC7C,MAAK,KAAK,IAAI;AAAA,EACrB;AACA,aAAW,QAAQ,KAAK,OAAO;AAC7B,QAAI,MAAM,IAAI,IAAI,EAAG;AACrB,UAAM,WAAW,MAAM,IAAI,KAAK,GAAG,GAAG,MAAM;AAC5C,QAAI,aAAa,OAAW,MAAK,MAAM,QAAQ;AAAA,EACjD;AACA,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,QAAQ,KAAK,OAAO;AAC7B,QAAI,MAAM,IAAI,IAAI,EAAG;AACrB,UAAM,WAAW,OAAO,IAAI,KAAK,EAAE;AACnC,QAAI,aAAa,UAAa,CAAC,OAAO,IAAI,QAAQ,GAAG;AACnD,WAAK,MAAM,QAAQ;AACnB,iBAAW,IAAI,KAAK,EAAE;AAAA,IACxB;AAAA,EACF;AACA,QAAM,QAAuB,CAAC;AAC9B,QAAM,UAA0B,CAAC;AACjC,QAAM,YAA2B,CAAC;AAClC,QAAM,YAAY,gBAAgB;AAClC,aAAW,QAAQ,KAAK,OAAO;AAC7B,UAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,QAAI,aAAa,QAAW;AAC1B,YAAM,KAAK,KAAK,EAAE;AAClB;AAAA,IACF;AACA,QAAI,SAAS,QAAQ,KAAK,KAAK;AAC7B,gBAAU,KAAK,KAAK,EAAE;AACtB;AAAA,IACF;AACA,YAAQ,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,MAAM,SAAS;AAAA,MACf,IAAI,KAAK;AAAA,MACT,SAAS,cAAc,UAAU,MAAM,YAAY,SAAS;AAAA,IAC9D,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,IACjF;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StepKey.d.ts","sourceRoot":"","sources":["../../src/StepKey.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StepKey.d.ts","sourceRoot":"","sources":["../../src/StepKey.ts"],"names":[],"mappings":"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"}
@@ -72,28 +72,30 @@ const EnvironmentIdentity = Schema.Union([
72
72
  ]);
73
73
  const makeDigestMemo = () => {
74
74
  const entries = /* @__PURE__ */ new Map();
75
- const digest = (from, path, compute) => Effect.suspend(() => {
76
- const address = JSON.stringify([from, path]);
77
- const existing = entries.get(address);
78
- if (existing !== void 0) {
79
- return Effect.flatMap(Effect.exit(Deferred.await(existing)), (exit) => {
80
- if (Exit.isSuccess(exit)) return Effect.succeed(exit.value);
81
- return Cause.hasInterrupts(exit.cause) ? digest(from, path, compute) : Effect.failCause(exit.cause);
82
- });
83
- }
84
- const pending = Deferred.makeUnsafe();
85
- entries.set(address, pending);
86
- return compute.pipe(
87
- Effect.onExit(
88
- (exit) => Effect.gen(function* () {
89
- if (Exit.isFailure(exit) && entries.get(address) === pending) {
90
- entries.delete(address);
91
- }
92
- yield* Deferred.done(pending, exit);
93
- })
94
- )
95
- );
96
- });
75
+ const digest = (from, path, compute) => Effect.uninterruptibleMask(
76
+ (restore) => Effect.suspend(() => {
77
+ const address = JSON.stringify([from, path]);
78
+ const existing = entries.get(address);
79
+ if (existing !== void 0) {
80
+ return restore(Effect.flatMap(Effect.exit(Deferred.await(existing)), (exit) => {
81
+ if (Exit.isSuccess(exit)) return Effect.succeed(exit.value);
82
+ return Cause.hasInterrupts(exit.cause) ? digest(from, path, compute) : Effect.failCause(exit.cause);
83
+ }));
84
+ }
85
+ const pending = Deferred.makeUnsafe();
86
+ entries.set(address, pending);
87
+ return restore(compute).pipe(
88
+ Effect.onExit(
89
+ (exit) => Effect.gen(function* () {
90
+ if (Exit.isFailure(exit) && entries.get(address) === pending) {
91
+ entries.delete(address);
92
+ }
93
+ yield* Deferred.done(pending, exit);
94
+ })
95
+ )
96
+ );
97
+ })
98
+ );
97
99
  return { digest };
98
100
  };
99
101
  class KeyMaterialError extends Schema.TaggedError()("@smthrs/plan/KeyMaterialError", {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/StepKey.ts"],
4
- "sourcesContent": ["/**\n * The KeyMaterial \u2192 step-key compiler.\n *\n * Revived from the deleted `packages/smithers/flows/keys/src/StepKey.ts`. Two\n * deliberate deviations from the original:\n *\n * 1. **It lives here, not in `@smthrs/keys`.** That package owns generic\n * derivation and stored-key validation; a compiler that understands plan\n * material belongs above it.\n * 2. **It produces `@smthrs/keys` `StoredKey` values, not a second `sk1_` digest\n * format.** The original minted its own prefix over a private `Digest`\n * module. The engine dispatches under `StoredKey` (`FlowEngine/ActionKey.ts`),\n * so a plan whose node keys were a *different* string format could never be\n * the thing the cache is consulted against, and that is the whole point of\n * a `Plan`. One key format, one hashing\n * chokepoint (canonical JSON + injected `Crypto`), one namespace field\n * (`kind`) distinguishing content keys from ordinal ones.\n *\n * Everything the original earned is kept: nominally branded digest inputs (a\n * literal that merely *looks* like `{digest}` hashes as a literal), set\n * normalization, the separate environment namespace, per-variant tagging of\n * resolved references, and the hashed `version`.\n *\n * Governing contract: the step-key rules at\n * https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/concepts/step-keys.md.\n *\n * @since 0.1.0\n */\n\nimport { DerivedKey, type StoredKey } from \"@smthrs/keys\"\nimport * as Cause from \"effect/Cause\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as Deferred from \"effect/Deferred\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport * as Schema from \"effect/Schema\"\nimport type * as FileSet from \"./FileSet.ts\"\nimport type * as KeyMaterial from \"./KeyMaterial.ts\"\n\n/**\n * A computed step key. Identical in representation to any other flow key \u2014\n * `key1_` plus a SHA-256 digest of the canonical serialization of the material.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport type StepKey = StoredKey\n\n/**\n * The nominal brand carried by every {@link DigestInput}. Kept private: the\n * only way to produce a value bearing it is {@link digestInput}, so a plain\n * value that merely happens to look like `{ digest: \"...\" }` \u2014 actions pass\n * content hashes around as ordinary data \u2014 can never be mistaken for a genuine\n * upstream-result digest reference. This closes a step-key collision where\n * shape-sniffing (`\"digest\" in value`) hashed the two identically.\n *\n * @since 0.1.0\n * @category symbols\n */\nconst DigestInputTypeId: unique symbol = Symbol.for(\"@smthrs/plan/StepKey/DigestInput\")\n\n/**\n * Which kind of graph reference a {@link DigestInput} stands for. Declared\n * once here so the field on `DigestInput` and the parameter of\n * {@link digestInput} name one set and cannot drift apart.\n */\ntype GraphReference = \"ref\" | \"pending\" | \"ref-projected\"\n\n/**\n * A precomputed digest supplied as a step input rather than a literal value.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface DigestInput {\n readonly [DigestInputTypeId]: typeof DigestInputTypeId\n readonly digest: string\n /**\n * Which kind of graph reference resolved to this digest.\n *\n * Carrying the discriminator on the digest input keeps `normalizeInputs` the\n * single normalizer: it wraps every variant once, and the variants stay\n * mutually distinct because they differ in this field rather than in a\n * hand-built object a second wrap would hide.\n */\n readonly reference?: GraphReference\n /** The projection applied to the referenced result, for `ref-projected`. */\n readonly path?: ReadonlyArray<string>\n}\n\n/**\n * Nominally tags a precomputed digest so it is hashed as a digest reference\n * rather than a literal value.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const digestInput = (\n digest: string,\n reference?: {\n readonly reference: GraphReference\n readonly path?: ReadonlyArray<string>\n }\n): DigestInput => ({\n [DigestInputTypeId]: DigestInputTypeId,\n digest,\n ...(reference === undefined ? {} : { reference: reference.reference }),\n ...(reference?.path === undefined ? {} : { path: reference.path })\n})\n\n/**\n * Type guard for values produced by {@link digestInput}.\n *\n * @since 0.1.0\n * @category guards\n * @slop\n */\nexport const isDigestInput = (value: unknown): value is DigestInput =>\n typeof value === \"object\" && value !== null && DigestInputTypeId in value &&\n (value as Record<PropertyKey, unknown>)[DigestInputTypeId] === DigestInputTypeId\n\n/**\n * The engine-resolved execution environment a content key is computed under,\n * hashed in its OWN namespace rather than merged into the caller's `layers`\n * and `capabilities`.\n *\n * Three properties matter and none survives a merge:\n *\n * 1. **Non-aliasing.** Concatenating environment material onto the caller's\n * made `caller{fs:[\"a\"]} + env{fs:[\"b\"]}` hash identically to\n * `caller{fs:[\"a\",\"b\"]} + env{}` \u2014 a cross-run collision in the very\n * material whose purpose is preventing one.\n * 2. **Declared vs undeclared.** `declared: false` is not the same value as\n * `declared: true` with empty sets.\n * 3. **Composition order.** Environment layers retain declaration order,\n * because plugin and service composition order can change behavior. The\n * caller-owned `ContentIdentity.layers` stays set-normalized.\n *\n * `runScope` is set only when `declared` is `false`: it pins the key to one\n * run, so a step whose environment identity is unknown can never serve a\n * cross-run hit. The union enforces this for typed callers; both\n * {@link content} and {@link dispatchIdentity} validate it at run time.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport type EnvironmentIdentity = typeof EnvironmentIdentity.Type\n\n/**\n * Validated, copyable runtime environment identity. Layer order matters;\n * capability patterns are set-like. Unknown fields are not identity material.\n * @since 1.0.0\n * @category schemas\n */\nexport const EnvironmentIdentity = Schema.Union([\n Schema.Struct({\n declared: Schema.Literal(true),\n layers: Schema.Array(Schema.String),\n capabilities: Schema.Record(Schema.String, Schema.Array(Schema.String)),\n runScope: Schema.optionalKey(Schema.Undefined)\n }),\n Schema.Struct({\n declared: Schema.Literal(false),\n layers: Schema.Array(Schema.String),\n capabilities: Schema.Record(Schema.String, Schema.Array(Schema.String)),\n runScope: Schema.NonEmptyString\n })\n])\n\n/**\n * Caller-owned memoization context for projected dependency-value digests.\n *\n * This is the flows counterpart of Bazel's `ActionKeyContext`: one context is\n * passed through related key computations so shared input material is hashed\n * once. Concurrent requests for the same projection share the in-flight\n * digest. Entries are sound only while each settled `from` value is immutable;\n * callers must create a fresh memo when those values can change.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface DigestMemo {\n readonly digest: (\n from: string,\n path: ReadonlyArray<string>,\n compute: Effect.Effect<StepKey, Schema.SchemaError, Crypto.Crypto>\n ) => Effect.Effect<StepKey, Schema.SchemaError, Crypto.Crypto>\n}\n\n/**\n * Creates an empty projected-value digest memo. Projection addresses are\n * JSON-encoded `[from, path]` tuples so segment boundaries are unambiguous.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const makeDigestMemo = (): DigestMemo => {\n const entries = new Map<string, Deferred.Deferred<StepKey, Schema.SchemaError>>()\n const digest: DigestMemo[\"digest\"] = (from, path, compute) =>\n Effect.suspend(() => {\n const address = JSON.stringify([from, path])\n const existing = entries.get(address)\n if (existing !== undefined) {\n return Effect.flatMap(Effect.exit(Deferred.await(existing)), (exit) => {\n if (Exit.isSuccess(exit)) return Effect.succeed(exit.value)\n // A waiter did not request the leader's cancellation. It competes to\n // become the replacement leader instead of inheriting that interrupt.\n return Cause.hasInterrupts(exit.cause) ? digest(from, path, compute) : Effect.failCause(exit.cause)\n })\n }\n const pending = Deferred.makeUnsafe<StepKey, Schema.SchemaError>()\n entries.set(address, pending)\n return compute.pipe(\n Effect.onExit((exit) =>\n Effect.gen(function*() {\n if (Exit.isFailure(exit) && entries.get(address) === pending) {\n entries.delete(address)\n }\n yield* Deferred.done(pending, exit)\n })\n )\n )\n })\n return { digest }\n}\n\n/**\n * Material describing a sealed or hermetic content-addressed step.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface ContentIdentity {\n readonly body: unknown\n readonly inputs: Readonly<Record<string, unknown | DigestInput>>\n readonly layers: ReadonlyArray<string>\n readonly capabilities: Readonly<Record<string, ReadonlyArray<string>>>\n readonly environment?: EnvironmentIdentity | undefined\n readonly hermetic?: {\n readonly readSet: ReadonlyArray<{ readonly path: string; readonly digest: string }>\n readonly writeSet: ReadonlyArray<FileSet.Entry>\n readonly removes?: ReadonlyArray<string> | undefined\n readonly boundaryMode: FileSet.BoundaryMode\n } | undefined\n}\n\n/**\n * Material describing the run-local identity of a non-cacheable step.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface OrdinalIdentity {\n readonly runId: string\n readonly parentScope?: string | undefined\n readonly ordinal: number\n readonly tier: \"compensable\" | \"irreversible\" | \"unsealed\"\n}\n\n/**\n * Stable failures while resolving graph-local dependency references.\n *\n * @since 0.1.0\n * @category errors\n * @slop\n */\nexport class KeyMaterialError extends Schema.TaggedError<KeyMaterialError>()(\"@smthrs/plan/KeyMaterialError\", {\n code: Schema.Literals([\"invalid_environment\", \"missing_dependency\", \"non_content_material\"]),\n message: Schema.String\n}) {}\n\nconst validateEnvironment = (environment: EnvironmentIdentity): KeyMaterialError | undefined => {\n const candidate = environment as { readonly declared?: unknown; readonly runScope?: unknown }\n if (candidate.declared === false) {\n if (typeof candidate.runScope !== \"string\" || candidate.runScope.length === 0) {\n return new KeyMaterialError({\n code: \"invalid_environment\",\n message: \"Undeclared environment identity requires a non-empty runScope\"\n })\n }\n return undefined\n }\n if (candidate.declared === true) {\n return candidate.runScope === undefined\n ? undefined\n : new KeyMaterialError({\n code: \"invalid_environment\",\n message: \"Declared environment identity must not include runScope\"\n })\n }\n return new KeyMaterialError({\n code: \"invalid_environment\",\n message: \"Environment identity requires a boolean declared field\"\n })\n}\n\nconst decodeEnvironment = (environment: EnvironmentIdentity) =>\n Effect.try({\n try: () => {\n const invalid = validateEnvironment(environment)\n if (invalid !== undefined) throw invalid\n return Schema.decodeUnknownSync(EnvironmentIdentity)(environment, { onExcessProperty: \"error\" })\n },\n catch: (cause) =>\n cause instanceof KeyMaterialError ? cause : new KeyMaterialError({\n code: \"invalid_environment\",\n message:\n \"Environment identity must contain only its declared fields, string layers, and string capability patterns\"\n })\n })\n\nconst sortStrings = (values: ReadonlyArray<string>): Array<string> =>\n [...new Set(values.map((value) => value.normalize(\"NFC\")))].sort()\n\nconst normalizeInputs = (inputs: ContentIdentity[\"inputs\"]): Record<string, unknown> =>\n Object.fromEntries(\n Object.entries(inputs).map(([name, value]) => [\n name,\n isDigestInput(value)\n ? {\n kind: \"digest\",\n digest: value.digest,\n ...(value.reference === undefined ? {} : { reference: value.reference }),\n ...(value.path === undefined ? {} : { path: value.path })\n }\n : { kind: \"literal\", value }\n ])\n )\n\nconst normalizeCapabilities = (capabilities: ContentIdentity[\"capabilities\"]): Record<string, Array<string>> =>\n Object.fromEntries(Object.entries(capabilities).map(([group, patterns]) => [group, sortStrings(patterns)]))\n\nconst normalizeEnvironment = (environment: EnvironmentIdentity) => ({\n declared: environment.declared,\n layers: environment.layers.map((layer) => layer.normalize(\"NFC\")),\n capabilities: normalizeCapabilities(environment.capabilities),\n ...(environment.runScope === undefined ? {} : { runScope: environment.runScope })\n})\n\nconst compareCodeUnits = (left: string, right: string): number => left < right ? -1 : 1\n\ntype NormalizedWriteEntry =\n | string\n | { readonly _tag: \"TreeArtifact\"; readonly path: string }\n | {\n readonly _tag: \"Glob\"\n readonly include: ReadonlyArray<string>\n readonly exclude?: ReadonlyArray<string> | undefined\n }\n\nconst writeEntryKey = (entry: NormalizedWriteEntry): string =>\n typeof entry === \"string\"\n ? JSON.stringify([\"Path\", entry])\n : entry._tag === \"TreeArtifact\"\n ? JSON.stringify([entry._tag, entry.path])\n : JSON.stringify([entry._tag, entry.include, entry.exclude ?? null])\n\nconst normalizeHermetic = (hermetic: NonNullable<ContentIdentity[\"hermetic\"]>) => {\n const readSet = [...hermetic.readSet]\n .map((entry) => ({ path: entry.path.normalize(\"NFC\"), digest: entry.digest }))\n .sort((left, right) => {\n if (left.path !== right.path) return left.path < right.path ? -1 : 1\n return left.digest < right.digest ? -1 : left.digest > right.digest ? 1 : 0\n })\n .filter((entry, index, entries) =>\n index === 0 || entry.path !== entries[index - 1]!.path || entry.digest !== entries[index - 1]!.digest\n )\n const normalizedWrites = [...hermetic.writeSet].map((entry) => {\n if (typeof entry === \"string\") return entry.normalize(\"NFC\")\n if (entry._tag === \"TreeArtifact\") return { ...entry, path: entry.path.normalize(\"NFC\") }\n return {\n ...entry,\n include: sortStrings(entry.include),\n ...(entry.exclude === undefined ? {} : { exclude: sortStrings(entry.exclude) })\n }\n })\n const writeSet = [...new Map(normalizedWrites.map((entry) => [writeEntryKey(entry), entry])).entries()]\n .sort(([left], [right]) => compareCodeUnits(left, right))\n .map(([, entry]) => entry)\n return {\n readSet,\n writeSet,\n ...(hermetic.removes === undefined ? {} : { removes: sortStrings(hermetic.removes) }),\n boundaryMode: hermetic.boundaryMode\n }\n}\n\nconst decodeKey = Schema.decodeUnknownEffect(DerivedKey)\n\n/**\n * Fingerprint for binding one execution to its runtime environment, not an\n * action dispatch key. Uses the same normalization as content/dispatch keys.\n * An omitted environment is distinct from declared-empty and run-scoped ones.\n * @since 1.0.0\n * @category constructors\n */\nexport const environmentIdentity = (\n environment?: EnvironmentIdentity\n): Effect.Effect<StoredKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n Effect.gen(function*() {\n const captured = environment === undefined ? undefined : yield* decodeEnvironment(environment)\n return yield* decodeKey({\n kind: \"execution-environment/v1\",\n environment: captured === undefined ? null : normalizeEnvironment(captured)\n })\n })\n\n/**\n * Produces a cross-run reusable key for a sealed or hermetic step. Set-like\n * declarations are normalized before serialization; write declarations remain\n * part of the identity even when the step writes nothing.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const content = (\n identity: ContentIdentity\n): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n Effect.gen(function*() {\n const environment = identity.environment === undefined ? undefined : yield* decodeEnvironment(identity.environment)\n return yield* decodeKey({\n kind: \"content\",\n body: identity.body,\n inputs: normalizeInputs(identity.inputs),\n layers: sortStrings(identity.layers),\n capabilities: normalizeCapabilities(identity.capabilities),\n ...(environment === undefined ? {} : { environment: normalizeEnvironment(environment) }),\n ...(identity.hermetic === undefined ? {} : { hermetic: normalizeHermetic(identity.hermetic) })\n })\n })\n\n/**\n * Produces a run-local ordinal key for compensable, irreversible, or unsealed\n * work. These keys intentionally cannot be reused across runs.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const ordinal = (\n identity: OrdinalIdentity\n): Effect.Effect<StepKey, Schema.SchemaError, Crypto.Crypto> => decodeKey({ kind: \"ordinal\", ...identity })\n\n/**\n * Resolves graph-local references to dependency digests and constructs a\n * sealed content key. Use {@link planIdentity} to compile any effect tier.\n *\n * This is the handoff the Flow Builder Brief describes: the planner hands over\n * a topologically ordered sequence of `{ nodeId, material }`, and for each one\n * the compiler substitutes every `Ref`/`Pending` with the *already computed\n * key of the referenced node*. Structural node ids are lookup addresses only\n * and never enter the hashed value \u2014 rename a node and nothing re-keys; change\n * what a node consumes and everything downstream of it does.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const fromKeyMaterial = (\n material: KeyMaterial.KeyMaterial,\n dependencyDigests: Readonly<Record<string, string>>\n): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> => {\n if (material.kind !== \"sealed\") {\n return Effect.fail(\n new KeyMaterialError({\n code: \"non_content_material\",\n message: `Cannot create a content key for ${material.kind} material`\n })\n )\n }\n return materialIdentity(material, dependencyDigests).pipe(Effect.flatMap(content))\n}\n\n/**\n * Identifies a declaration in a plan, independently of whether its execution\n * can be cached. Sealed material retains its existing content-key format;\n * compensable and irreversible material use a distinct, tier-bearing plan\n * namespace. These fingerprints bind approvals, not cross-run result reuse.\n * Dispatch non-cacheable work under a run-local {@link ordinal} instead.\n *\n * @since 1.0.0\n * @category constructors\n */\nexport const planIdentity = (\n material: KeyMaterial.KeyMaterial,\n dependencyDigests: Readonly<Record<string, string>>\n): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n material.kind === \"sealed\" ?\n fromKeyMaterial(material, dependencyDigests) :\n materialIdentity(material, dependencyDigests).pipe(Effect.flatMap((identity) =>\n decodeKey({\n kind: \"plan-declaration\",\n tier: material.kind,\n body: identity.body,\n inputs: normalizeInputs(identity.inputs),\n layers: sortStrings(identity.layers),\n capabilities: normalizeCapabilities(identity.capabilities)\n })\n ))\n\n/**\n * Reads the entry a graph reference names. Only an own data property counts:\n * an absent name or an accessor is a missing dependency, and no getter runs.\n * `label` names what the record holds, as each refusal says it.\n *\n * @private\n */\nconst ownDataProperty = (\n record: Readonly<Record<string, unknown>>,\n from: string,\n label: \"Digest\" | \"Settled result\"\n): Effect.Effect<unknown, KeyMaterialError> => {\n const descriptor = Object.getOwnPropertyDescriptor(record, from)\n if (descriptor === undefined) {\n return Effect.fail(\n new KeyMaterialError({\n code: \"missing_dependency\",\n message: `Missing ${label.toLowerCase()} for graph dependency ${from}`\n })\n )\n }\n if (!(\"value\" in descriptor)) {\n return Effect.fail(\n new KeyMaterialError({\n code: \"missing_dependency\",\n message: `${label} for graph dependency ${from} must be a data property`\n })\n )\n }\n return Effect.succeed(descriptor.value)\n}\n\n/**\n * The positional inputs both identities hash. A `Literal` contributes its raw\n * value, so `normalizeInputs` applies the one literal wrap; `resolve` supplies\n * the digest for each `Ref` and `Pending`, tagged with the reference variant.\n *\n * @private\n */\nconst resolveInputs = <E, R>(\n material: KeyMaterial.KeyMaterial,\n resolve: (reference: Exclude<KeyMaterial.InputRef, { readonly _tag: \"Literal\" }>) => Effect.Effect<string, E, R>\n): Effect.Effect<Record<string, unknown>, E, R> =>\n Effect.gen(function*() {\n const inputs: Record<string, unknown> = {}\n for (let index = 0; index < material.inputs.length; index++) {\n const input = material.inputs[index]!\n if (input._tag === \"Literal\") {\n inputs[String(index)] = input.value\n continue\n }\n const digest = yield* resolve(input)\n inputs[String(index)] = input._tag === \"Pending\"\n ? digestInput(digest, { reference: \"pending\" })\n : input.path.length > 0\n ? digestInput(digest, { reference: \"ref-projected\", path: input.path })\n : digestInput(digest, { reference: \"ref\" })\n }\n return inputs\n })\n\n/** Resolves plan references once for both content and non-cacheable declarations. */\nconst materialIdentity = (\n material: KeyMaterial.KeyMaterial,\n dependencyDigests: Readonly<Record<string, string>>\n): Effect.Effect<ContentIdentity, KeyMaterialError> =>\n resolveInputs(\n material,\n (reference) =>\n Effect.flatMap(ownDataProperty(dependencyDigests, reference.from, \"Digest\"), (digest) =>\n typeof digest === \"string\" ? Effect.succeed(digest) : Effect.fail(\n new KeyMaterialError({\n code: \"missing_dependency\",\n message: `Digest for graph dependency ${reference.from} must be a string`\n })\n ))\n ).pipe(Effect.map((inputs) => ({\n body: materialBody(material),\n inputs,\n layers: material.layers,\n capabilities: { declared: material.capabilities }\n })))\n\n/**\n * The node's own declaration, hashed. Shared by {@link planIdentity},\n * {@link fromKeyMaterial}, and {@link dispatchIdentity} so derivations cannot drift about what\n * \"the node itself\" means.\n *\n * @private\n */\nconst materialBody = (material: KeyMaterial.KeyMaterial) => ({\n version: material.version,\n declaration: material.body,\n ...(material.nondeterministic === undefined ? {} : { nondeterministic: material.nondeterministic }),\n ...(material.effects === undefined ? {} : { effects: material.effects }),\n ...(material.placement === undefined ? {} : { placement: material.placement })\n})\n\n/**\n * The digest a `Pending` input contributes to a dispatch key. It is a\n * constant, and that is the point: `Pending` is an ordering reference, and\n * ordering does not change what a node consumes, so it must not change what\n * the node caches under. The string is self-describing, so a reader of a\n * hashed payload can see that no upstream value was folded.\n *\n * @private\n */\nconst orderingOnly = \"ordering-only\"\n\n/**\n * Projects a settled result along a `Ref` path. Only own data properties\n * resolve, so a missing, inherited, or accessor segment yields `undefined`\n * without invoking a getter. This is a stable, distinct value: a projection that\n * walks off the end of a result is a fact about the graph, not a failure.\n * `undefined` drops out of the canonical form, so it hashes distinctly from\n * every JSON value including `null`.\n *\n * Exported because it is the ONE projection semantics for the value channel:\n * {@link dispatchIdentity} digests what this returns, so every consumer that\n * resolves a `Ref` at execution time must resolve it the same way, or two\n * inputs that key identically could be consumed differently \u2014 a stale-hit\n * vector.\n *\n * @since 0.1.0\n * @category utilities\n * @slop\n */\nexport const project = (value: unknown, path: ReadonlyArray<string>): unknown => {\n let current = value\n for (const segment of path) {\n if (typeof current !== \"object\" || current === null) return undefined\n const descriptor = Object.getOwnPropertyDescriptor(current, segment)\n if (descriptor === undefined || !(\"value\" in descriptor)) return undefined\n current = descriptor.value\n }\n return current\n}\n\n/**\n * The key a dispatch is *cached* under, as distinct from the plan key a node\n * is *identified* by.\n *\n * A plan key folds the resolved keys of every upstream node, transitively, so\n * an edit anywhere upstream re-keys everything below it \u2014 even when the edited\n * node's output value is byte for byte what it was before. Bazel does not work\n * that way: `ActionCacheChecker` keys an action by the *content* of its\n * inputs, so an unchanged output stops invalidation dead. The file channel in\n * flows already had that property through the measured boundary digests; the\n * JSON value channel did not, and this is what gives it one.\n *\n * The derivation folds the node's OWN material \u2014 body, version, effects,\n * placement, layers, capabilities \u2014 and never an upstream key. Each material\n * input contributes content instead: a `Literal` its value, a `Ref` the digest\n * of the settled result of `from` projected along `path`, and a `Pending`\n * nothing beyond its tag. The measured hermetic boundary is folded unchanged.\n *\n * `results` must hold every dependency the material names. The scheduler's\n * halt rule guarantees it: a dependent of failed or skipped work never\n * dispatches, so a `Ref` always resolves against a success.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const dispatchIdentity = (options: {\n readonly material: KeyMaterial.KeyMaterial\n /** The settled output value of each dependency, by node id. */\n readonly results: Readonly<Record<string, unknown>>\n readonly hermetic: NonNullable<ContentIdentity[\"hermetic\"]>\n /** The engine-resolved execution environment this dispatch runs under. */\n readonly environment?: EnvironmentIdentity | undefined\n /** Reuses projected-value digests while the corresponding settled values remain immutable. */\n readonly digestMemo?: DigestMemo | undefined\n}): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n Effect.gen(function*() {\n const material = options.material\n if (material.kind !== \"sealed\") {\n return yield* new KeyMaterialError({\n code: \"non_content_material\",\n message: `Cannot create a dispatch key for ${material.kind} material`\n })\n }\n const environment = options.environment === undefined ? undefined : yield* decodeEnvironment(options.environment)\n const inputs = yield* resolveInputs(material, (reference) =>\n reference._tag === \"Pending\"\n ? Effect.succeed(orderingOnly)\n : Effect.flatMap(ownDataProperty(options.results, reference.from, \"Settled result\"), (settled) => {\n const compute = decodeKey({ kind: \"input-value\", value: project(settled, reference.path) })\n return options.digestMemo === undefined\n ? compute\n : options.digestMemo.digest(reference.from, reference.path, compute)\n }))\n return yield* content({\n body: materialBody(material),\n inputs,\n layers: material.layers,\n capabilities: { declared: material.capabilities },\n environment,\n hermetic: options.hermetic\n })\n })\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * The KeyMaterial \u2192 step-key compiler.\n *\n * Revived from the deleted `packages/smithers/flows/keys/src/StepKey.ts`. Two\n * deliberate deviations from the original:\n *\n * 1. **It lives here, not in `@smthrs/keys`.** That package owns generic\n * derivation and stored-key validation; a compiler that understands plan\n * material belongs above it.\n * 2. **It produces `@smthrs/keys` `StoredKey` values, not a second `sk1_` digest\n * format.** The original minted its own prefix over a private `Digest`\n * module. The engine dispatches under `StoredKey` (`FlowEngine/ActionKey.ts`),\n * so a plan whose node keys were a *different* string format could never be\n * the thing the cache is consulted against, and that is the whole point of\n * a `Plan`. One key format, one hashing\n * chokepoint (canonical JSON + injected `Crypto`), one namespace field\n * (`kind`) distinguishing content keys from ordinal ones.\n *\n * Everything the original earned is kept: nominally branded digest inputs (a\n * literal that merely *looks* like `{digest}` hashes as a literal), set\n * normalization, the separate environment namespace, per-variant tagging of\n * resolved references, and the hashed `version`.\n *\n * Governing contract: the step-key rules at\n * https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/concepts/step-keys.md.\n *\n * @since 0.1.0\n */\n\nimport { DerivedKey, type StoredKey } from \"@smthrs/keys\"\nimport * as Cause from \"effect/Cause\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as Deferred from \"effect/Deferred\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport * as Schema from \"effect/Schema\"\nimport type * as FileSet from \"./FileSet.ts\"\nimport type * as KeyMaterial from \"./KeyMaterial.ts\"\n\n/**\n * A computed step key. Identical in representation to any other flow key \u2014\n * `key1_` plus a SHA-256 digest of the canonical serialization of the material.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport type StepKey = StoredKey\n\n/**\n * The nominal brand carried by every {@link DigestInput}. Kept private: the\n * only way to produce a value bearing it is {@link digestInput}, so a plain\n * value that merely happens to look like `{ digest: \"...\" }` \u2014 actions pass\n * content hashes around as ordinary data \u2014 can never be mistaken for a genuine\n * upstream-result digest reference. This closes a step-key collision where\n * shape-sniffing (`\"digest\" in value`) hashed the two identically.\n *\n * @since 0.1.0\n * @category symbols\n */\nconst DigestInputTypeId: unique symbol = Symbol.for(\"@smthrs/plan/StepKey/DigestInput\")\n\n/**\n * Which kind of graph reference a {@link DigestInput} stands for. Declared\n * once here so the field on `DigestInput` and the parameter of\n * {@link digestInput} name one set and cannot drift apart.\n */\ntype GraphReference = \"ref\" | \"pending\" | \"ref-projected\"\n\n/**\n * A precomputed digest supplied as a step input rather than a literal value.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface DigestInput {\n readonly [DigestInputTypeId]: typeof DigestInputTypeId\n readonly digest: string\n /**\n * Which kind of graph reference resolved to this digest.\n *\n * Carrying the discriminator on the digest input keeps `normalizeInputs` the\n * single normalizer: it wraps every variant once, and the variants stay\n * mutually distinct because they differ in this field rather than in a\n * hand-built object a second wrap would hide.\n */\n readonly reference?: GraphReference\n /** The projection applied to the referenced result, for `ref-projected`. */\n readonly path?: ReadonlyArray<string>\n}\n\n/**\n * Nominally tags a precomputed digest so it is hashed as a digest reference\n * rather than a literal value.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const digestInput = (\n digest: string,\n reference?: {\n readonly reference: GraphReference\n readonly path?: ReadonlyArray<string>\n }\n): DigestInput => ({\n [DigestInputTypeId]: DigestInputTypeId,\n digest,\n ...(reference === undefined ? {} : { reference: reference.reference }),\n ...(reference?.path === undefined ? {} : { path: reference.path })\n})\n\n/**\n * Type guard for values produced by {@link digestInput}.\n *\n * @since 0.1.0\n * @category guards\n * @slop\n */\nexport const isDigestInput = (value: unknown): value is DigestInput =>\n typeof value === \"object\" && value !== null && DigestInputTypeId in value &&\n (value as Record<PropertyKey, unknown>)[DigestInputTypeId] === DigestInputTypeId\n\n/**\n * The engine-resolved execution environment a content key is computed under,\n * hashed in its OWN namespace rather than merged into the caller's `layers`\n * and `capabilities`.\n *\n * Three properties matter and none survives a merge:\n *\n * 1. **Non-aliasing.** Concatenating environment material onto the caller's\n * made `caller{fs:[\"a\"]} + env{fs:[\"b\"]}` hash identically to\n * `caller{fs:[\"a\",\"b\"]} + env{}` \u2014 a cross-run collision in the very\n * material whose purpose is preventing one.\n * 2. **Declared vs undeclared.** `declared: false` is not the same value as\n * `declared: true` with empty sets.\n * 3. **Composition order.** Environment layers retain declaration order,\n * because plugin and service composition order can change behavior. The\n * caller-owned `ContentIdentity.layers` stays set-normalized.\n *\n * `runScope` is set only when `declared` is `false`: it pins the key to one\n * run, so a step whose environment identity is unknown can never serve a\n * cross-run hit. The union enforces this for typed callers; both\n * {@link content} and {@link dispatchIdentity} validate it at run time.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport type EnvironmentIdentity = typeof EnvironmentIdentity.Type\n\n/**\n * Validated, copyable runtime environment identity. Layer order matters;\n * capability patterns are set-like. Unknown fields are not identity material.\n * @since 1.0.0\n * @category schemas\n */\nexport const EnvironmentIdentity = Schema.Union([\n Schema.Struct({\n declared: Schema.Literal(true),\n layers: Schema.Array(Schema.String),\n capabilities: Schema.Record(Schema.String, Schema.Array(Schema.String)),\n runScope: Schema.optionalKey(Schema.Undefined)\n }),\n Schema.Struct({\n declared: Schema.Literal(false),\n layers: Schema.Array(Schema.String),\n capabilities: Schema.Record(Schema.String, Schema.Array(Schema.String)),\n runScope: Schema.NonEmptyString\n })\n])\n\n/**\n * Caller-owned memoization context for projected dependency-value digests.\n *\n * This is the flows counterpart of Bazel's `ActionKeyContext`: one context is\n * passed through related key computations so shared input material is hashed\n * once. Concurrent requests for the same projection share the in-flight\n * digest. Entries are sound only while each settled `from` value is immutable;\n * callers must create a fresh memo when those values can change.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface DigestMemo {\n readonly digest: (\n from: string,\n path: ReadonlyArray<string>,\n compute: Effect.Effect<StepKey, Schema.SchemaError, Crypto.Crypto>\n ) => Effect.Effect<StepKey, Schema.SchemaError, Crypto.Crypto>\n}\n\n/**\n * Creates an empty projected-value digest memo. Projection addresses are\n * JSON-encoded `[from, path]` tuples so segment boundaries are unambiguous.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const makeDigestMemo = (): DigestMemo => {\n const entries = new Map<string, Deferred.Deferred<StepKey, Schema.SchemaError>>()\n // Registering the entry and installing its exit handler run uninterruptibly,\n // so an interrupt can never land between them and strand a Deferred that no\n // fiber will complete. The wait and the computation stay interruptible.\n const digest: DigestMemo[\"digest\"] = (from, path, compute) =>\n Effect.uninterruptibleMask((restore) =>\n Effect.suspend(() => {\n const address = JSON.stringify([from, path])\n const existing = entries.get(address)\n if (existing !== undefined) {\n return restore(Effect.flatMap(Effect.exit(Deferred.await(existing)), (exit) => {\n if (Exit.isSuccess(exit)) return Effect.succeed(exit.value)\n // A waiter did not request the leader's cancellation. It competes to\n // become the replacement leader instead of inheriting that interrupt.\n return Cause.hasInterrupts(exit.cause) ? digest(from, path, compute) : Effect.failCause(exit.cause)\n }))\n }\n const pending = Deferred.makeUnsafe<StepKey, Schema.SchemaError>()\n entries.set(address, pending)\n return restore(compute).pipe(\n Effect.onExit((exit) =>\n Effect.gen(function*() {\n if (Exit.isFailure(exit) && entries.get(address) === pending) {\n entries.delete(address)\n }\n yield* Deferred.done(pending, exit)\n })\n )\n )\n })\n )\n return { digest }\n}\n\n/**\n * Material describing a sealed or hermetic content-addressed step.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface ContentIdentity {\n readonly body: unknown\n readonly inputs: Readonly<Record<string, unknown | DigestInput>>\n readonly layers: ReadonlyArray<string>\n readonly capabilities: Readonly<Record<string, ReadonlyArray<string>>>\n readonly environment?: EnvironmentIdentity | undefined\n readonly hermetic?: {\n readonly readSet: ReadonlyArray<{ readonly path: string; readonly digest: string }>\n readonly writeSet: ReadonlyArray<FileSet.Entry>\n readonly removes?: ReadonlyArray<string> | undefined\n readonly boundaryMode: FileSet.BoundaryMode\n } | undefined\n}\n\n/**\n * Material describing the run-local identity of a non-cacheable step.\n *\n * @since 0.1.0\n * @category models\n * @slop\n */\nexport interface OrdinalIdentity {\n readonly runId: string\n readonly parentScope?: string | undefined\n readonly ordinal: number\n readonly tier: \"compensable\" | \"irreversible\" | \"unsealed\"\n}\n\n/**\n * Stable failures while resolving graph-local dependency references.\n *\n * @since 0.1.0\n * @category errors\n * @slop\n */\nexport class KeyMaterialError extends Schema.TaggedError<KeyMaterialError>()(\"@smthrs/plan/KeyMaterialError\", {\n code: Schema.Literals([\"invalid_environment\", \"missing_dependency\", \"non_content_material\"]),\n message: Schema.String\n}) {}\n\nconst validateEnvironment = (environment: EnvironmentIdentity): KeyMaterialError | undefined => {\n const candidate = environment as { readonly declared?: unknown; readonly runScope?: unknown }\n if (candidate.declared === false) {\n if (typeof candidate.runScope !== \"string\" || candidate.runScope.length === 0) {\n return new KeyMaterialError({\n code: \"invalid_environment\",\n message: \"Undeclared environment identity requires a non-empty runScope\"\n })\n }\n return undefined\n }\n if (candidate.declared === true) {\n return candidate.runScope === undefined\n ? undefined\n : new KeyMaterialError({\n code: \"invalid_environment\",\n message: \"Declared environment identity must not include runScope\"\n })\n }\n return new KeyMaterialError({\n code: \"invalid_environment\",\n message: \"Environment identity requires a boolean declared field\"\n })\n}\n\nconst decodeEnvironment = (environment: EnvironmentIdentity) =>\n Effect.try({\n try: () => {\n const invalid = validateEnvironment(environment)\n if (invalid !== undefined) throw invalid\n return Schema.decodeUnknownSync(EnvironmentIdentity)(environment, { onExcessProperty: \"error\" })\n },\n catch: (cause) =>\n cause instanceof KeyMaterialError ? cause : new KeyMaterialError({\n code: \"invalid_environment\",\n message:\n \"Environment identity must contain only its declared fields, string layers, and string capability patterns\"\n })\n })\n\nconst sortStrings = (values: ReadonlyArray<string>): Array<string> =>\n [...new Set(values.map((value) => value.normalize(\"NFC\")))].sort()\n\nconst normalizeInputs = (inputs: ContentIdentity[\"inputs\"]): Record<string, unknown> =>\n Object.fromEntries(\n Object.entries(inputs).map(([name, value]) => [\n name,\n isDigestInput(value)\n ? {\n kind: \"digest\",\n digest: value.digest,\n ...(value.reference === undefined ? {} : { reference: value.reference }),\n ...(value.path === undefined ? {} : { path: value.path })\n }\n : { kind: \"literal\", value }\n ])\n )\n\nconst normalizeCapabilities = (capabilities: ContentIdentity[\"capabilities\"]): Record<string, Array<string>> =>\n Object.fromEntries(Object.entries(capabilities).map(([group, patterns]) => [group, sortStrings(patterns)]))\n\nconst normalizeEnvironment = (environment: EnvironmentIdentity) => ({\n declared: environment.declared,\n layers: environment.layers.map((layer) => layer.normalize(\"NFC\")),\n capabilities: normalizeCapabilities(environment.capabilities),\n ...(environment.runScope === undefined ? {} : { runScope: environment.runScope })\n})\n\nconst compareCodeUnits = (left: string, right: string): number => left < right ? -1 : 1\n\ntype NormalizedWriteEntry =\n | string\n | { readonly _tag: \"TreeArtifact\"; readonly path: string }\n | {\n readonly _tag: \"Glob\"\n readonly include: ReadonlyArray<string>\n readonly exclude?: ReadonlyArray<string> | undefined\n }\n\nconst writeEntryKey = (entry: NormalizedWriteEntry): string =>\n typeof entry === \"string\"\n ? JSON.stringify([\"Path\", entry])\n : entry._tag === \"TreeArtifact\"\n ? JSON.stringify([entry._tag, entry.path])\n : JSON.stringify([entry._tag, entry.include, entry.exclude ?? null])\n\nconst normalizeHermetic = (hermetic: NonNullable<ContentIdentity[\"hermetic\"]>) => {\n const readSet = [...hermetic.readSet]\n .map((entry) => ({ path: entry.path.normalize(\"NFC\"), digest: entry.digest }))\n .sort((left, right) => {\n if (left.path !== right.path) return left.path < right.path ? -1 : 1\n return left.digest < right.digest ? -1 : left.digest > right.digest ? 1 : 0\n })\n .filter((entry, index, entries) =>\n index === 0 || entry.path !== entries[index - 1]!.path || entry.digest !== entries[index - 1]!.digest\n )\n const normalizedWrites = [...hermetic.writeSet].map((entry) => {\n if (typeof entry === \"string\") return entry.normalize(\"NFC\")\n if (entry._tag === \"TreeArtifact\") return { ...entry, path: entry.path.normalize(\"NFC\") }\n return {\n ...entry,\n include: sortStrings(entry.include),\n ...(entry.exclude === undefined ? {} : { exclude: sortStrings(entry.exclude) })\n }\n })\n const writeSet = [...new Map(normalizedWrites.map((entry) => [writeEntryKey(entry), entry])).entries()]\n .sort(([left], [right]) => compareCodeUnits(left, right))\n .map(([, entry]) => entry)\n return {\n readSet,\n writeSet,\n ...(hermetic.removes === undefined ? {} : { removes: sortStrings(hermetic.removes) }),\n boundaryMode: hermetic.boundaryMode\n }\n}\n\nconst decodeKey = Schema.decodeUnknownEffect(DerivedKey)\n\n/**\n * Fingerprint for binding one execution to its runtime environment, not an\n * action dispatch key. Uses the same normalization as content/dispatch keys.\n * An omitted environment is distinct from declared-empty and run-scoped ones.\n * @since 1.0.0\n * @category constructors\n */\nexport const environmentIdentity = (\n environment?: EnvironmentIdentity\n): Effect.Effect<StoredKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n Effect.gen(function*() {\n const captured = environment === undefined ? undefined : yield* decodeEnvironment(environment)\n return yield* decodeKey({\n kind: \"execution-environment/v1\",\n environment: captured === undefined ? null : normalizeEnvironment(captured)\n })\n })\n\n/**\n * Produces a cross-run reusable key for a sealed or hermetic step. Set-like\n * declarations are normalized before serialization; write declarations remain\n * part of the identity even when the step writes nothing.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const content = (\n identity: ContentIdentity\n): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n Effect.gen(function*() {\n const environment = identity.environment === undefined ? undefined : yield* decodeEnvironment(identity.environment)\n return yield* decodeKey({\n kind: \"content\",\n body: identity.body,\n inputs: normalizeInputs(identity.inputs),\n layers: sortStrings(identity.layers),\n capabilities: normalizeCapabilities(identity.capabilities),\n ...(environment === undefined ? {} : { environment: normalizeEnvironment(environment) }),\n ...(identity.hermetic === undefined ? {} : { hermetic: normalizeHermetic(identity.hermetic) })\n })\n })\n\n/**\n * Produces a run-local ordinal key for compensable, irreversible, or unsealed\n * work. These keys intentionally cannot be reused across runs.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const ordinal = (\n identity: OrdinalIdentity\n): Effect.Effect<StepKey, Schema.SchemaError, Crypto.Crypto> => decodeKey({ kind: \"ordinal\", ...identity })\n\n/**\n * Resolves graph-local references to dependency digests and constructs a\n * sealed content key. Use {@link planIdentity} to compile any effect tier.\n *\n * This is the handoff the Flow Builder Brief describes: the planner hands over\n * a topologically ordered sequence of `{ nodeId, material }`, and for each one\n * the compiler substitutes every `Ref`/`Pending` with the *already computed\n * key of the referenced node*. Structural node ids are lookup addresses only\n * and never enter the hashed value \u2014 rename a node and nothing re-keys; change\n * what a node consumes and everything downstream of it does.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const fromKeyMaterial = (\n material: KeyMaterial.KeyMaterial,\n dependencyDigests: Readonly<Record<string, string>>\n): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> => {\n if (material.kind !== \"sealed\") {\n return Effect.fail(\n new KeyMaterialError({\n code: \"non_content_material\",\n message: `Cannot create a content key for ${material.kind} material`\n })\n )\n }\n return materialIdentity(material, dependencyDigests).pipe(Effect.flatMap(content))\n}\n\n/**\n * Identifies a declaration in a plan, independently of whether its execution\n * can be cached. Sealed material retains its existing content-key format;\n * compensable and irreversible material use a distinct, tier-bearing plan\n * namespace. These fingerprints bind approvals, not cross-run result reuse.\n * Dispatch non-cacheable work under a run-local {@link ordinal} instead.\n *\n * @since 1.0.0\n * @category constructors\n */\nexport const planIdentity = (\n material: KeyMaterial.KeyMaterial,\n dependencyDigests: Readonly<Record<string, string>>\n): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n material.kind === \"sealed\" ?\n fromKeyMaterial(material, dependencyDigests) :\n materialIdentity(material, dependencyDigests).pipe(Effect.flatMap((identity) =>\n decodeKey({\n kind: \"plan-declaration\",\n tier: material.kind,\n body: identity.body,\n inputs: normalizeInputs(identity.inputs),\n layers: sortStrings(identity.layers),\n capabilities: normalizeCapabilities(identity.capabilities)\n })\n ))\n\n/**\n * Reads the entry a graph reference names. Only an own data property counts:\n * an absent name or an accessor is a missing dependency, and no getter runs.\n * `label` names what the record holds, as each refusal says it.\n *\n * @private\n */\nconst ownDataProperty = (\n record: Readonly<Record<string, unknown>>,\n from: string,\n label: \"Digest\" | \"Settled result\"\n): Effect.Effect<unknown, KeyMaterialError> => {\n const descriptor = Object.getOwnPropertyDescriptor(record, from)\n if (descriptor === undefined) {\n return Effect.fail(\n new KeyMaterialError({\n code: \"missing_dependency\",\n message: `Missing ${label.toLowerCase()} for graph dependency ${from}`\n })\n )\n }\n if (!(\"value\" in descriptor)) {\n return Effect.fail(\n new KeyMaterialError({\n code: \"missing_dependency\",\n message: `${label} for graph dependency ${from} must be a data property`\n })\n )\n }\n return Effect.succeed(descriptor.value)\n}\n\n/**\n * The positional inputs both identities hash. A `Literal` contributes its raw\n * value, so `normalizeInputs` applies the one literal wrap; `resolve` supplies\n * the digest for each `Ref` and `Pending`, tagged with the reference variant.\n *\n * @private\n */\nconst resolveInputs = <E, R>(\n material: KeyMaterial.KeyMaterial,\n resolve: (reference: Exclude<KeyMaterial.InputRef, { readonly _tag: \"Literal\" }>) => Effect.Effect<string, E, R>\n): Effect.Effect<Record<string, unknown>, E, R> =>\n Effect.gen(function*() {\n const inputs: Record<string, unknown> = {}\n for (let index = 0; index < material.inputs.length; index++) {\n const input = material.inputs[index]!\n if (input._tag === \"Literal\") {\n inputs[String(index)] = input.value\n continue\n }\n const digest = yield* resolve(input)\n inputs[String(index)] = input._tag === \"Pending\"\n ? digestInput(digest, { reference: \"pending\" })\n : input.path.length > 0\n ? digestInput(digest, { reference: \"ref-projected\", path: input.path })\n : digestInput(digest, { reference: \"ref\" })\n }\n return inputs\n })\n\n/** Resolves plan references once for both content and non-cacheable declarations. */\nconst materialIdentity = (\n material: KeyMaterial.KeyMaterial,\n dependencyDigests: Readonly<Record<string, string>>\n): Effect.Effect<ContentIdentity, KeyMaterialError> =>\n resolveInputs(\n material,\n (reference) =>\n Effect.flatMap(ownDataProperty(dependencyDigests, reference.from, \"Digest\"), (digest) =>\n typeof digest === \"string\" ? Effect.succeed(digest) : Effect.fail(\n new KeyMaterialError({\n code: \"missing_dependency\",\n message: `Digest for graph dependency ${reference.from} must be a string`\n })\n ))\n ).pipe(Effect.map((inputs) => ({\n body: materialBody(material),\n inputs,\n layers: material.layers,\n capabilities: { declared: material.capabilities }\n })))\n\n/**\n * The node's own declaration, hashed. Shared by {@link planIdentity},\n * {@link fromKeyMaterial}, and {@link dispatchIdentity} so derivations cannot drift about what\n * \"the node itself\" means.\n *\n * @private\n */\nconst materialBody = (material: KeyMaterial.KeyMaterial) => ({\n version: material.version,\n declaration: material.body,\n ...(material.nondeterministic === undefined ? {} : { nondeterministic: material.nondeterministic }),\n ...(material.effects === undefined ? {} : { effects: material.effects }),\n ...(material.placement === undefined ? {} : { placement: material.placement })\n})\n\n/**\n * The digest a `Pending` input contributes to a dispatch key. It is a\n * constant, and that is the point: `Pending` is an ordering reference, and\n * ordering does not change what a node consumes, so it must not change what\n * the node caches under. The string is self-describing, so a reader of a\n * hashed payload can see that no upstream value was folded.\n *\n * @private\n */\nconst orderingOnly = \"ordering-only\"\n\n/**\n * Projects a settled result along a `Ref` path. Only own data properties\n * resolve, so a missing, inherited, or accessor segment yields `undefined`\n * without invoking a getter. This is a stable, distinct value: a projection that\n * walks off the end of a result is a fact about the graph, not a failure.\n * `undefined` drops out of the canonical form, so it hashes distinctly from\n * every JSON value including `null`.\n *\n * Exported because it is the ONE projection semantics for the value channel:\n * {@link dispatchIdentity} digests what this returns, so every consumer that\n * resolves a `Ref` at execution time must resolve it the same way, or two\n * inputs that key identically could be consumed differently \u2014 a stale-hit\n * vector.\n *\n * @since 0.1.0\n * @category utilities\n * @slop\n */\nexport const project = (value: unknown, path: ReadonlyArray<string>): unknown => {\n let current = value\n for (const segment of path) {\n if (typeof current !== \"object\" || current === null) return undefined\n const descriptor = Object.getOwnPropertyDescriptor(current, segment)\n if (descriptor === undefined || !(\"value\" in descriptor)) return undefined\n current = descriptor.value\n }\n return current\n}\n\n/**\n * The key a dispatch is *cached* under, as distinct from the plan key a node\n * is *identified* by.\n *\n * A plan key folds the resolved keys of every upstream node, transitively, so\n * an edit anywhere upstream re-keys everything below it \u2014 even when the edited\n * node's output value is byte for byte what it was before. Bazel does not work\n * that way: `ActionCacheChecker` keys an action by the *content* of its\n * inputs, so an unchanged output stops invalidation dead. The file channel in\n * flows already had that property through the measured boundary digests; the\n * JSON value channel did not, and this is what gives it one.\n *\n * The derivation folds the node's OWN material \u2014 body, version, effects,\n * placement, layers, capabilities \u2014 and never an upstream key. Each material\n * input contributes content instead: a `Literal` its value, a `Ref` the digest\n * of the settled result of `from` projected along `path`, and a `Pending`\n * nothing beyond its tag. The measured hermetic boundary is folded unchanged.\n *\n * `results` must hold every dependency the material names. The scheduler's\n * halt rule guarantees it: a dependent of failed or skipped work never\n * dispatches, so a `Ref` always resolves against a success.\n *\n * @since 0.1.0\n * @category constructors\n * @slop\n */\nexport const dispatchIdentity = (options: {\n readonly material: KeyMaterial.KeyMaterial\n /** The settled output value of each dependency, by node id. */\n readonly results: Readonly<Record<string, unknown>>\n readonly hermetic: NonNullable<ContentIdentity[\"hermetic\"]>\n /** The engine-resolved execution environment this dispatch runs under. */\n readonly environment?: EnvironmentIdentity | undefined\n /** Reuses projected-value digests while the corresponding settled values remain immutable. */\n readonly digestMemo?: DigestMemo | undefined\n}): Effect.Effect<StepKey, KeyMaterialError | Schema.SchemaError, Crypto.Crypto> =>\n Effect.gen(function*() {\n const material = options.material\n if (material.kind !== \"sealed\") {\n return yield* new KeyMaterialError({\n code: \"non_content_material\",\n message: `Cannot create a dispatch key for ${material.kind} material`\n })\n }\n const environment = options.environment === undefined ? undefined : yield* decodeEnvironment(options.environment)\n const inputs = yield* resolveInputs(material, (reference) =>\n reference._tag === \"Pending\"\n ? Effect.succeed(orderingOnly)\n : Effect.flatMap(ownDataProperty(options.results, reference.from, \"Settled result\"), (settled) => {\n const compute = decodeKey({ kind: \"input-value\", value: project(settled, reference.path) })\n return options.digestMemo === undefined\n ? compute\n : options.digestMemo.digest(reference.from, reference.path, compute)\n }))\n return yield* content({\n body: materialBody(material),\n inputs,\n layers: material.layers,\n capabilities: { declared: material.capabilities },\n environment,\n hermetic: options.hermetic\n })\n })\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/internal/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/internal/node.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,10 @@
6
6
  * 'what is different about this run' is a set comparison, not archaeology."
7
7
  * This module is the set comparison.
8
8
  *
9
- * The **verdict** is the key: two nodes with the same id and the same key are
10
- * the same step and nothing else needs saying. The **attribution** —
11
- * `changed: ["input[1]"]` — is a report for a human, derived by comparing the
12
- * declarations field by field. It is deliberately not part of any digest.
9
+ * The **verdict** is the key: two nodes with the same key are the same step,
10
+ * under the same id or a moved one, and nothing else needs saying. The
11
+ * **attribution** — `changed: ["input[1]"]` — is a report for a human, derived
12
+ * by comparing the declarations field by field. It is deliberately not part of any digest.
13
13
  *
14
14
  * @since 0.1.0
15
15
  */
@@ -50,6 +50,21 @@ export interface PlanDiff {
50
50
  /**
51
51
  * Compares a plan against the last plan for the same flow.
52
52
  *
53
+ * Nodes pair in three passes, each over the nodes no earlier pass paired:
54
+ * the same id with the same key, then the same key under any id, then the
55
+ * same id with a different key. The second pass exists because flow node ids
56
+ * can be positional: inserting a step shifts the ids after it while their
57
+ * keys stay equal, and that is one added step, not a re-key of every later
58
+ * one (#3905).
59
+ *
60
+ * `added`, `rekeyed`, and `unchanged` name nodes by their id in `next`;
61
+ * `removed` names nodes by their id in `previous`. A moved id can therefore
62
+ * appear once in `removed` or `added` and once in `unchanged`.
63
+ *
64
+ * @param previous - The last plan recorded for the flow.
65
+ * @param next - The plan to compare against it.
66
+ * @returns The added, removed, re-keyed, and unchanged node ids, each in its
67
+ * plan's node order.
53
68
  * @since 0.1.0
54
69
  * @category constructors
55
70
  * @slop
@@ -1 +1 @@
1
- {"version":3,"file":"PlanDiff.d.ts","sourceRoot":"","sources":["../../src/PlanDiff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAA;AAGtC;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IACxC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAC1C;AAuGD;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GAAI,UAAU,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,KAAG,QAmC3D,CAAA"}
1
+ {"version":3,"file":"PlanDiff.d.ts","sourceRoot":"","sources":["../../src/PlanDiff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAA;AAGtC;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IACxC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAC1C;AAuGD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,IAAI,GAAI,UAAU,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,KAAG,QA6D3D,CAAA"}