@horizon36596/zenith-core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +18 -0
  3. package/README.md +16 -0
  4. package/dist/canonicalize.d.ts +25 -0
  5. package/dist/canonicalize.d.ts.map +1 -0
  6. package/dist/canonicalize.js +199 -0
  7. package/dist/canonicalize.js.map +1 -0
  8. package/dist/check.d.ts +26 -0
  9. package/dist/check.d.ts.map +1 -0
  10. package/dist/check.js +231 -0
  11. package/dist/check.js.map +1 -0
  12. package/dist/checks/heading.d.ts +17 -0
  13. package/dist/checks/heading.d.ts.map +1 -0
  14. package/dist/checks/heading.js +78 -0
  15. package/dist/checks/heading.js.map +1 -0
  16. package/dist/checks/intake.d.ts +28 -0
  17. package/dist/checks/intake.d.ts.map +1 -0
  18. package/dist/checks/intake.js +131 -0
  19. package/dist/checks/intake.js.map +1 -0
  20. package/dist/checks/motion.d.ts +28 -0
  21. package/dist/checks/motion.d.ts.map +1 -0
  22. package/dist/checks/motion.js +252 -0
  23. package/dist/checks/motion.js.map +1 -0
  24. package/dist/checks/schedule.d.ts +29 -0
  25. package/dist/checks/schedule.d.ts.map +1 -0
  26. package/dist/checks/schedule.js +166 -0
  27. package/dist/checks/schedule.js.map +1 -0
  28. package/dist/checks/season.d.ts +6 -0
  29. package/dist/checks/season.d.ts.map +1 -0
  30. package/dist/checks/season.js +126 -0
  31. package/dist/checks/season.js.map +1 -0
  32. package/dist/continuity.d.ts +38 -0
  33. package/dist/continuity.d.ts.map +1 -0
  34. package/dist/continuity.js +69 -0
  35. package/dist/continuity.js.map +1 -0
  36. package/dist/diff.d.ts +37 -0
  37. package/dist/diff.d.ts.map +1 -0
  38. package/dist/diff.js +258 -0
  39. package/dist/diff.js.map +1 -0
  40. package/dist/edit/command.d.ts +4 -0
  41. package/dist/edit/command.d.ts.map +1 -0
  42. package/dist/edit/command.js +16 -0
  43. package/dist/edit/command.js.map +1 -0
  44. package/dist/edit/errors.d.ts +9 -0
  45. package/dist/edit/errors.d.ts.map +1 -0
  46. package/dist/edit/errors.js +12 -0
  47. package/dist/edit/errors.js.map +1 -0
  48. package/dist/edit/fields.d.ts +40 -0
  49. package/dist/edit/fields.d.ts.map +1 -0
  50. package/dist/edit/fields.js +150 -0
  51. package/dist/edit/fields.js.map +1 -0
  52. package/dist/edit/finish.d.ts +15 -0
  53. package/dist/edit/finish.d.ts.map +1 -0
  54. package/dist/edit/finish.js +36 -0
  55. package/dist/edit/finish.js.map +1 -0
  56. package/dist/edit/groups.d.ts +66 -0
  57. package/dist/edit/groups.d.ts.map +1 -0
  58. package/dist/edit/groups.js +277 -0
  59. package/dist/edit/groups.js.map +1 -0
  60. package/dist/edit/ids.d.ts +39 -0
  61. package/dist/edit/ids.d.ts.map +1 -0
  62. package/dist/edit/ids.js +76 -0
  63. package/dist/edit/ids.js.map +1 -0
  64. package/dist/edit/index.d.ts +22 -0
  65. package/dist/edit/index.d.ts.map +1 -0
  66. package/dist/edit/index.js +22 -0
  67. package/dist/edit/index.js.map +1 -0
  68. package/dist/edit/meta.d.ts +15 -0
  69. package/dist/edit/meta.d.ts.map +1 -0
  70. package/dist/edit/meta.js +13 -0
  71. package/dist/edit/meta.js.map +1 -0
  72. package/dist/edit/path.d.ts +36 -0
  73. package/dist/edit/path.d.ts.map +1 -0
  74. package/dist/edit/path.js +135 -0
  75. package/dist/edit/path.js.map +1 -0
  76. package/dist/edit/steps.d.ts +53 -0
  77. package/dist/edit/steps.d.ts.map +1 -0
  78. package/dist/edit/steps.js +0 -0
  79. package/dist/edit/steps.js.map +1 -0
  80. package/dist/edit/template.d.ts +18 -0
  81. package/dist/edit/template.d.ts.map +1 -0
  82. package/dist/edit/template.js +30 -0
  83. package/dist/edit/template.js.map +1 -0
  84. package/dist/edit/timing.d.ts +11 -0
  85. package/dist/edit/timing.d.ts.map +1 -0
  86. package/dist/edit/timing.js +23 -0
  87. package/dist/edit/timing.js.map +1 -0
  88. package/dist/edit/tree.d.ts +32 -0
  89. package/dist/edit/tree.d.ts.map +1 -0
  90. package/dist/edit/tree.js +90 -0
  91. package/dist/edit/tree.js.map +1 -0
  92. package/dist/estimate.d.ts +48 -0
  93. package/dist/estimate.d.ts.map +1 -0
  94. package/dist/estimate.js +443 -0
  95. package/dist/estimate.js.map +1 -0
  96. package/dist/findingHelp.d.ts +18 -0
  97. package/dist/findingHelp.d.ts.map +1 -0
  98. package/dist/findingHelp.js +114 -0
  99. package/dist/findingHelp.js.map +1 -0
  100. package/dist/fix.d.ts +21 -0
  101. package/dist/fix.d.ts.map +1 -0
  102. package/dist/fix.js +180 -0
  103. package/dist/fix.js.map +1 -0
  104. package/dist/footprint.d.ts +33 -0
  105. package/dist/footprint.d.ts.map +1 -0
  106. package/dist/footprint.js +71 -0
  107. package/dist/footprint.js.map +1 -0
  108. package/dist/geometry/angle.d.ts +13 -0
  109. package/dist/geometry/angle.d.ts.map +1 -0
  110. package/dist/geometry/angle.js +21 -0
  111. package/dist/geometry/angle.js.map +1 -0
  112. package/dist/geometry/curve.d.ts +24 -0
  113. package/dist/geometry/curve.d.ts.map +1 -0
  114. package/dist/geometry/curve.js +78 -0
  115. package/dist/geometry/curve.js.map +1 -0
  116. package/dist/geometry/path.d.ts +29 -0
  117. package/dist/geometry/path.d.ts.map +1 -0
  118. package/dist/geometry/path.js +61 -0
  119. package/dist/geometry/path.js.map +1 -0
  120. package/dist/geometry/quadrature.d.ts +13 -0
  121. package/dist/geometry/quadrature.d.ts.map +1 -0
  122. package/dist/geometry/quadrature.js +57 -0
  123. package/dist/geometry/quadrature.js.map +1 -0
  124. package/dist/geometry/sat.d.ts +40 -0
  125. package/dist/geometry/sat.d.ts.map +1 -0
  126. package/dist/geometry/sat.js +86 -0
  127. package/dist/geometry/sat.js.map +1 -0
  128. package/dist/geometry/vec.d.ts +27 -0
  129. package/dist/geometry/vec.d.ts.map +1 -0
  130. package/dist/geometry/vec.js +30 -0
  131. package/dist/geometry/vec.js.map +1 -0
  132. package/dist/heading.d.ts +77 -0
  133. package/dist/heading.d.ts.map +1 -0
  134. package/dist/heading.js +164 -0
  135. package/dist/heading.js.map +1 -0
  136. package/dist/headingRanges.d.ts +48 -0
  137. package/dist/headingRanges.d.ts.map +1 -0
  138. package/dist/headingRanges.js +132 -0
  139. package/dist/headingRanges.js.map +1 -0
  140. package/dist/index.d.ts +41 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +41 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/kinematics.d.ts +63 -0
  145. package/dist/kinematics.d.ts.map +1 -0
  146. package/dist/kinematics.js +71 -0
  147. package/dist/kinematics.js.map +1 -0
  148. package/dist/ledger.d.ts +49 -0
  149. package/dist/ledger.d.ts.map +1 -0
  150. package/dist/ledger.js +136 -0
  151. package/dist/ledger.js.map +1 -0
  152. package/dist/load.d.ts +12 -0
  153. package/dist/load.d.ts.map +1 -0
  154. package/dist/load.js +12 -0
  155. package/dist/load.js.map +1 -0
  156. package/dist/mirror.d.ts +81 -0
  157. package/dist/mirror.d.ts.map +1 -0
  158. package/dist/mirror.js +282 -0
  159. package/dist/mirror.js.map +1 -0
  160. package/dist/plan.d.ts +29 -0
  161. package/dist/plan.d.ts.map +1 -0
  162. package/dist/plan.js +159 -0
  163. package/dist/plan.js.map +1 -0
  164. package/dist/prBody.d.ts +24 -0
  165. package/dist/prBody.d.ts.map +1 -0
  166. package/dist/prBody.js +112 -0
  167. package/dist/prBody.js.map +1 -0
  168. package/dist/provenance.d.ts +21 -0
  169. package/dist/provenance.d.ts.map +1 -0
  170. package/dist/provenance.js +46 -0
  171. package/dist/provenance.js.map +1 -0
  172. package/dist/render.d.ts +18 -0
  173. package/dist/render.d.ts.map +1 -0
  174. package/dist/render.js +464 -0
  175. package/dist/render.js.map +1 -0
  176. package/dist/resolve.d.ts +39 -0
  177. package/dist/resolve.d.ts.map +1 -0
  178. package/dist/resolve.js +172 -0
  179. package/dist/resolve.js.map +1 -0
  180. package/dist/season.d.ts +65 -0
  181. package/dist/season.d.ts.map +1 -0
  182. package/dist/season.js +16 -0
  183. package/dist/season.js.map +1 -0
  184. package/dist/sim/commands.d.ts +97 -0
  185. package/dist/sim/commands.d.ts.map +1 -0
  186. package/dist/sim/commands.js +185 -0
  187. package/dist/sim/commands.js.map +1 -0
  188. package/dist/sim/curves.d.ts +37 -0
  189. package/dist/sim/curves.d.ts.map +1 -0
  190. package/dist/sim/curves.js +187 -0
  191. package/dist/sim/curves.js.map +1 -0
  192. package/dist/sim/follower.d.ts +124 -0
  193. package/dist/sim/follower.d.ts.map +1 -0
  194. package/dist/sim/follower.js +472 -0
  195. package/dist/sim/follower.js.map +1 -0
  196. package/dist/sim/ideal.d.ts +103 -0
  197. package/dist/sim/ideal.d.ts.map +1 -0
  198. package/dist/sim/ideal.js +393 -0
  199. package/dist/sim/ideal.js.map +1 -0
  200. package/dist/sim/index.d.ts +11 -0
  201. package/dist/sim/index.d.ts.map +1 -0
  202. package/dist/sim/index.js +10 -0
  203. package/dist/sim/index.js.map +1 -0
  204. package/dist/sim/params.d.ts +91 -0
  205. package/dist/sim/params.d.ts.map +1 -0
  206. package/dist/sim/params.js +195 -0
  207. package/dist/sim/params.js.map +1 -0
  208. package/dist/sim/pedroPath.d.ts +41 -0
  209. package/dist/sim/pedroPath.d.ts.map +1 -0
  210. package/dist/sim/pedroPath.js +191 -0
  211. package/dist/sim/pedroPath.js.map +1 -0
  212. package/dist/sim/plant.d.ts +59 -0
  213. package/dist/sim/plant.d.ts.map +1 -0
  214. package/dist/sim/plant.js +128 -0
  215. package/dist/sim/plant.js.map +1 -0
  216. package/dist/sim/residuals.d.ts +36 -0
  217. package/dist/sim/residuals.d.ts.map +1 -0
  218. package/dist/sim/residuals.js +86 -0
  219. package/dist/sim/residuals.js.map +1 -0
  220. package/dist/sim/simulate.d.ts +27 -0
  221. package/dist/sim/simulate.d.ts.map +1 -0
  222. package/dist/sim/simulate.js +924 -0
  223. package/dist/sim/simulate.js.map +1 -0
  224. package/dist/sim/types.d.ts +209 -0
  225. package/dist/sim/types.d.ts.map +1 -0
  226. package/dist/sim/types.js +2 -0
  227. package/dist/sim/types.js.map +1 -0
  228. package/dist/tokens.d.ts +93 -0
  229. package/dist/tokens.d.ts.map +1 -0
  230. package/dist/tokens.js +93 -0
  231. package/dist/tokens.js.map +1 -0
  232. package/dist/trace.d.ts +89 -0
  233. package/dist/trace.d.ts.map +1 -0
  234. package/dist/trace.js +187 -0
  235. package/dist/trace.js.map +1 -0
  236. package/dist/types.d.ts +219 -0
  237. package/dist/types.d.ts.map +1 -0
  238. package/dist/types.js +2 -0
  239. package/dist/types.js.map +1 -0
  240. package/dist/unimplemented.d.ts +8 -0
  241. package/dist/unimplemented.d.ts.map +1 -0
  242. package/dist/unimplemented.js +11 -0
  243. package/dist/unimplemented.js.map +1 -0
  244. package/package.json +59 -0
package/dist/diff.js ADDED
@@ -0,0 +1,258 @@
1
+ import { childLists } from "@horizon36596/zenith-schema";
2
+ import { childPrefix, effectiveId } from "./edit/ids.js";
3
+ const CHILD_LISTS = ["steps", "then", "else"];
4
+ /**
5
+ * The child lists of a step, each with the id prefix `resolve` gives its members.
6
+ *
7
+ * The prefix comes from `childPrefix`, the one definition of it: a branch with both arms numbers
8
+ * them (`b.1.`, `b.2.`) and one with only a `then` does not. Naming the two arms alike gave two
9
+ * different steps the id `b.1`, and review mode then anchored both changes to the same step, so one
10
+ * change hid the other.
11
+ */
12
+ const childrenOf = (step, id) => {
13
+ const lists = childLists(step);
14
+ return lists.map((list, index) => ({
15
+ list: step.kind === "branch" ? (index === 0 ? "then" : "else") : "steps",
16
+ prefix: childPrefix(id, lists.length, index),
17
+ steps: list,
18
+ }));
19
+ };
20
+ /** Walks the whole step tree in document order, naming every step the way `resolve` names it. */
21
+ export function walkSteps(steps) {
22
+ const entries = [];
23
+ const visit = (list, listName, prefix) => {
24
+ list.forEach((step, index) => {
25
+ const id = effectiveId(step, index, prefix);
26
+ entries.push({ id, step, list: listName, index, order: entries.length });
27
+ for (const child of childrenOf(step, id)) {
28
+ visit(child.steps, `${id}.${child.list}`, child.prefix);
29
+ }
30
+ });
31
+ };
32
+ visit(steps, "steps", "step");
33
+ return entries;
34
+ }
35
+ /** The keys of a step that are its own content, rather than the steps nested inside it. */
36
+ const contentKeys = (step) => Object.keys(step).filter((key) => key !== "id" && !CHILD_LISTS.includes(key));
37
+ /** Deep equality over the plain JSON a step is made of. Key order does not count as a difference. */
38
+ function sameValue(a, b) {
39
+ if (a === b)
40
+ return true;
41
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
42
+ return false;
43
+ if (Array.isArray(a) !== Array.isArray(b))
44
+ return false;
45
+ if (Array.isArray(a) && Array.isArray(b)) {
46
+ return a.length === b.length && a.every((item, index) => sameValue(item, b[index]));
47
+ }
48
+ const left = a;
49
+ const right = b;
50
+ const keys = new Set([...Object.keys(left), ...Object.keys(right)]);
51
+ for (const key of keys)
52
+ if (!sameValue(left[key], right[key]))
53
+ return false;
54
+ return true;
55
+ }
56
+ const isPose = (source) => typeof source === "object" && source !== null && "xIn" in source;
57
+ /** The short way round, so a heading that crossed pi does not read as a six-radian turn. */
58
+ const wrapRad = (radians) => {
59
+ const wrapped = ((radians + Math.PI) % (2 * Math.PI)) - Math.PI;
60
+ return wrapped <= -Math.PI ? wrapped + 2 * Math.PI : wrapped;
61
+ };
62
+ function poseDelta(where, before, after) {
63
+ if (!isPose(before) || !isPose(after))
64
+ return null;
65
+ const dxIn = after.xIn - before.xIn;
66
+ const dyIn = after.yIn - before.yIn;
67
+ const dHeadingRad = before.headingRad === undefined || after.headingRad === undefined
68
+ ? null
69
+ : wrapRad(after.headingRad - before.headingRad);
70
+ if (dxIn === 0 && dyIn === 0 && (dHeadingRad === null || dHeadingRad === 0))
71
+ return null;
72
+ return { where, dxIn, dyIn, dHeadingRad, distanceIn: Math.hypot(dxIn, dyIn) };
73
+ }
74
+ /** Every pose that moved between two versions of a path step, named by where it sits. */
75
+ export function poseDeltas(before, after) {
76
+ if (before.kind !== "path" || after.kind !== "path")
77
+ return [];
78
+ const deltas = [];
79
+ const count = Math.min(before.segments.length, after.segments.length);
80
+ for (let index = 0; index < count; index += 1) {
81
+ const from = before.segments[index];
82
+ const to = after.segments[index];
83
+ if (from === undefined || to === undefined)
84
+ continue;
85
+ const at = `segments[${String(index)}]`;
86
+ for (const end of ["from", "to"]) {
87
+ const delta = poseDelta(`${at}.${end}`, from[end], to[end]);
88
+ if (delta !== null)
89
+ deltas.push(delta);
90
+ }
91
+ if (from.kind === "bezier" && to.kind === "bezier") {
92
+ const controls = Math.min(from.control.length, to.control.length);
93
+ for (let point = 0; point < controls; point += 1) {
94
+ const delta = poseDelta(`${at}.control[${String(point)}]`, from.control[point], to.control[point]);
95
+ if (delta !== null)
96
+ deltas.push(delta);
97
+ }
98
+ }
99
+ }
100
+ return deltas;
101
+ }
102
+ /** Inches to two places, without the trailing zeroes that make a table hard to read. */
103
+ const inches = (value) => {
104
+ const fixed = value.toFixed(2);
105
+ return fixed.includes(".") ? fixed.replace(/\.?0+$/, "") : fixed;
106
+ };
107
+ /** One sentence saying what happened to a step, which is what a reviewer reads first. */
108
+ function summarise(change, before, after) {
109
+ const kindOf = (step) => step?.kind ?? "step";
110
+ switch (change.kind) {
111
+ case "added":
112
+ return `A ${kindOf(after)} step was added at position ${String((change.toIndex ?? 0) + 1)}.`;
113
+ case "removed":
114
+ return `The ${kindOf(before)} step at position ${String((change.fromIndex ?? 0) + 1)} was removed.`;
115
+ case "moved":
116
+ return `The ${kindOf(after)} step moved from position ${String((change.fromIndex ?? 0) + 1)} to position ${String((change.toIndex ?? 0) + 1)}.`;
117
+ default: {
118
+ const fields = change.fields ?? [];
119
+ const moved = change.poseDeltas ?? [];
120
+ const furthest = moved.reduce((best, delta) => (best === null || delta.distanceIn > best.distanceIn ? delta : best), null);
121
+ const named = fields.length <= 1
122
+ ? `Its ${fields[0] ?? "content"} changed`
123
+ : `Its ${fields.slice(0, -1).join(", ")} and ${String(fields[fields.length - 1])} changed`;
124
+ const tail = furthest === null
125
+ ? "."
126
+ : `, and ${moved.length === 1 ? "one pose" : `${String(moved.length)} poses`} moved, the furthest by ${inches(furthest.distanceIn)} in.`;
127
+ return `${named}${tail}`;
128
+ }
129
+ }
130
+ }
131
+ /** The document's own fields, in the order the schema declares them. */
132
+ const HEADER_KEYS = [
133
+ "name",
134
+ "title",
135
+ "description",
136
+ "robot",
137
+ "field",
138
+ "alliance",
139
+ "authors",
140
+ "created",
141
+ "start",
142
+ ];
143
+ /** The step-level structural diff between two routines. */
144
+ export function diff(a, b) {
145
+ const before = walkSteps(a.steps);
146
+ const after = walkSteps(b.steps);
147
+ const beforeById = new Map(before.map((entry) => [entry.id, entry]));
148
+ const afterById = new Map(after.map((entry) => [entry.id, entry]));
149
+ const changes = [];
150
+ for (const entry of before) {
151
+ if (afterById.has(entry.id))
152
+ continue;
153
+ changes.push({
154
+ kind: "removed",
155
+ stepId: entry.id,
156
+ fromIndex: entry.index,
157
+ summary: summarise({ kind: "removed", stepId: entry.id, fromIndex: entry.index }, entry.step, null),
158
+ });
159
+ }
160
+ for (const entry of after) {
161
+ const old = beforeById.get(entry.id);
162
+ if (old === undefined) {
163
+ changes.push({
164
+ kind: "added",
165
+ stepId: entry.id,
166
+ toIndex: entry.index,
167
+ summary: summarise({ kind: "added", stepId: entry.id, toIndex: entry.index }, null, entry.step),
168
+ });
169
+ continue;
170
+ }
171
+ const fields = [...new Set([...contentKeys(old.step), ...contentKeys(entry.step)])].filter((key) => !sameValue(old.step[key], entry.step[key]));
172
+ if (fields.length > 0) {
173
+ const deltas = poseDeltas(old.step, entry.step);
174
+ const change = {
175
+ kind: "changed",
176
+ stepId: entry.id,
177
+ summary: "",
178
+ fields,
179
+ ...(deltas.length > 0 ? { poseDeltas: deltas } : {}),
180
+ fromIndex: old.index,
181
+ toIndex: entry.index,
182
+ };
183
+ change.summary = summarise(change, old.step, entry.step);
184
+ changes.push(change);
185
+ }
186
+ if (old.list !== entry.list || old.index !== entry.index) {
187
+ const change = {
188
+ kind: "moved",
189
+ stepId: entry.id,
190
+ summary: "",
191
+ fromIndex: old.index,
192
+ toIndex: entry.index,
193
+ };
194
+ change.summary =
195
+ old.list === entry.list
196
+ ? summarise(change, old.step, entry.step)
197
+ : `The ${entry.step.kind} step moved out of ${old.list} and into ${entry.list}.`;
198
+ changes.push(change);
199
+ }
200
+ }
201
+ // Document order in the new file, so a review reads top to bottom. A removed step keeps the place
202
+ // it held in the old one, just ahead of whatever now stands there.
203
+ const orderOf = (change) => {
204
+ const now = afterById.get(change.stepId);
205
+ if (now !== undefined)
206
+ return now.order;
207
+ return (beforeById.get(change.stepId)?.order ?? 0) - 0.5;
208
+ };
209
+ changes.sort((left, right) => orderOf(left) - orderOf(right));
210
+ const header = HEADER_KEYS.filter((key) => !sameValue(a[key], b[key])).map((key) => String(key));
211
+ return { changes, header, identical: changes.length === 0 && header.length === 0 };
212
+ }
213
+ const seconds = (value) => value === null || value === undefined ? "unknown" : value.toFixed(2);
214
+ const signed = (value, places = 2) => `${value >= 0 ? "+" : "-"}${Math.abs(value).toFixed(places)}`;
215
+ /** The estimate change for one step, or null when neither side has one to compare. */
216
+ function deltaS(stepId, a, b) {
217
+ const before = a?.byStepId[stepId]?.nominalS;
218
+ const after = b?.byStepId[stepId]?.nominalS;
219
+ if (before === undefined && after === undefined)
220
+ return null;
221
+ if (before === undefined || before === null || after === undefined || after === null) {
222
+ return `${seconds(before)} s to ${seconds(after)} s`;
223
+ }
224
+ return `${before.toFixed(2)} s to ${after.toFixed(2)} s (${signed(after - before)} s)`;
225
+ }
226
+ /**
227
+ * The diff as markdown, for a pull request comment or the CLI. Passing the two estimates adds what
228
+ * the change costs in seconds, which is usually the question being asked.
229
+ */
230
+ export function diffToMarkdown(autoDiff, estimateA, estimateB) {
231
+ const lines = [];
232
+ if (autoDiff.identical) {
233
+ lines.push("No structural changes.");
234
+ }
235
+ else {
236
+ if (autoDiff.header.length > 0) {
237
+ lines.push(`Header: ${autoDiff.header.join(", ")} changed.`, "");
238
+ }
239
+ for (const change of autoDiff.changes) {
240
+ const cost = deltaS(change.stepId, estimateA, estimateB);
241
+ lines.push(`- \`${change.stepId}\` ${change.kind}. ${change.summary}${cost === null ? "" : ` Estimate ${cost}.`}`);
242
+ for (const delta of change.poseDeltas ?? []) {
243
+ const heading = delta.dHeadingRad === null || delta.dHeadingRad === 0
244
+ ? ""
245
+ : `, heading ${signed((delta.dHeadingRad * 180) / Math.PI, 1)} degrees`;
246
+ lines.push(` - \`${delta.where}\` moved ${inches(delta.distanceIn)} in (x ${signed(delta.dxIn)}, y ${signed(delta.dyIn)}${heading}).`);
247
+ }
248
+ }
249
+ }
250
+ if (estimateA !== undefined && estimateB !== undefined) {
251
+ const before = estimateA.nominalS;
252
+ const after = estimateB.nominalS;
253
+ const change = before === null || after === null ? null : after - before;
254
+ lines.push("", `Total: ${seconds(before)} s to ${seconds(after)} s${change === null ? "" : ` (${signed(change)} s)`}.`);
255
+ }
256
+ return lines.join("\n").trim();
257
+ }
258
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Auto, CommandCall } from "@horizon36596/zenith-schema";
2
+ /** Replaces a `command` step's arguments outright. */
3
+ export declare function setCommandArgs(auto: Auto, stepId: string, args: CommandCall["args"]): Auto;
4
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/edit/command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAKrE,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAS1F"}
@@ -0,0 +1,16 @@
1
+ import { EditError } from "./errors.js";
2
+ import { finish } from "./finish.js";
3
+ import { updateStep } from "./tree.js";
4
+ /** Replaces a `command` step's arguments outright. */
5
+ export function setCommandArgs(auto, stepId, args) {
6
+ const result = updateStep(auto.steps, "step", stepId, (step) => {
7
+ if (step.kind !== "command") {
8
+ throw new EditError(`Step ${JSON.stringify(stepId)} is a ${step.kind} step, not a command.`);
9
+ }
10
+ return { ...step, args };
11
+ });
12
+ if (!result.found)
13
+ throw new EditError(`No step with id ${JSON.stringify(stepId)}.`);
14
+ return finish({ ...auto, steps: result.steps });
15
+ }
16
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/edit/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,sDAAsD;AACtD,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,MAAc,EAAE,IAAyB;IAClF,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,uBAAuB,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,SAAS,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrF,OAAO,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Thrown by every structural edit primitive in this directory: an id that does not exist, a
3
+ * target that does not fit the step kind, or a mutation that would leave the auto invalid. The
4
+ * message is written for whoever is holding the file, human or agent.
5
+ */
6
+ export declare class EditError extends Error {
7
+ constructor(message: string);
8
+ }
9
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/edit/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Thrown by every structural edit primitive in this directory: an id that does not exist, a
3
+ * target that does not fit the step kind, or a mutation that would leave the auto invalid. The
4
+ * message is written for whoever is holding the file, human or agent.
5
+ */
6
+ export class EditError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "EditError";
10
+ }
11
+ }
12
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/edit/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,40 @@
1
+ import type { Auto, CommandCall, ParallelStep, PoseSource, Segment } from "@horizon36596/zenith-schema";
2
+ /**
3
+ * Points a segment endpoint at a waypoint (`{ ref }`), at the previous step's end (`"current"`),
4
+ * or at a literal pose. The one edit `setPose` cannot express.
5
+ */
6
+ export declare function setSegmentSource(auto: Auto, stepId: string, segmentIndex: number, pointKind: "from" | "to", source: PoseSource): Auto;
7
+ /**
8
+ * Turns a segment into a line or a Bezier. Becoming a Bezier needs somewhere to put the new
9
+ * control point, and core will not invent one (CLAUDE.md rule 4): the caller passes the point,
10
+ * which is the segment's midpoint when the editor does it.
11
+ */
12
+ export declare function setSegmentKind(auto: Auto, stepId: string, segmentIndex: number, kind: Segment["kind"], control: {
13
+ xIn: number;
14
+ yIn: number;
15
+ }): Auto;
16
+ /** Sets or clears a path step's end condition ("stop when the hopper is full"). */
17
+ export declare function setEndCondition(auto: Auto, stepId: string, condition: string | null): Auto;
18
+ /** Sets a step's note, or removes it when the text is blank. */
19
+ export declare function setNotes(auto: Auto, stepId: string, notes: string): Auto;
20
+ /** Sets what a wait step waits for: a number of seconds, a robot-side condition, or both. */
21
+ export declare function setWait(auto: Auto, stepId: string, wait: {
22
+ seconds?: number;
23
+ until?: string;
24
+ }): Auto;
25
+ /** Sets a parallel group's mode, and which child is its deadline. */
26
+ export declare function setParallel(auto: Auto, stepId: string, patch: {
27
+ mode?: ParallelStep["mode"];
28
+ deadline?: string;
29
+ }): Auto;
30
+ /** Sets the robot-side condition a branch step asks about. */
31
+ export declare function setBranchCondition(auto: Auto, stepId: string, condition: string): Auto;
32
+ /**
33
+ * Points a command step at a different registered command. The arguments go with the old name:
34
+ * they were built from its parameters, and keeping them would silently pass one command's
35
+ * arguments to another.
36
+ */
37
+ export declare function setCommandName(auto: Auto, stepId: string, name: string): Auto;
38
+ /** Replaces the command a marker fires, keeping where on the path it sits. */
39
+ export declare function setMarkerCommand(auto: Auto, stepId: string, markerIndex: number, command: CommandCall): Auto;
40
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/edit/fields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EAEJ,WAAW,EACX,YAAY,EAEZ,UAAU,EACV,OAAO,EAGR,MAAM,6BAA6B,CAAC;AAyCrC;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,UAAU,GACjB,IAAI,CAUN;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EACrB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACpC,IAAI,CAWN;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAU1F;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CASxE;AAED,6FAA6F;AAC7F,wBAAgB,OAAO,CACrB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,IAAI,CAQN;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,IAAI,CAUN;AAED,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAQtF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAO7E;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,WAAW,GACnB,IAAI,CAgBN"}
@@ -0,0 +1,150 @@
1
+ import { EditError } from "./errors.js";
2
+ import { finish } from "./finish.js";
3
+ import { updateStep } from "./tree.js";
4
+ /**
5
+ * The field-level edits the inspector and an agent both need, on top of the structural primitives
6
+ * next to them: pointing a segment endpoint at a waypoint, turning a line into a curve, and
7
+ * setting the one field that makes a wait a wait or a branch a branch.
8
+ *
9
+ * `setPose` (`path.ts`) writes literal poses only, so the editor could not say "this endpoint is
10
+ * the `shootNorth` waypoint" through core at all; these fill that gap. Same contract as every
11
+ * other primitive here: never mutate the input, always `finish` the candidate, so an edit that
12
+ * would leave the file invalid throws rather than being written.
13
+ */
14
+ function asPathStep(step, stepId) {
15
+ if (step.kind !== "path") {
16
+ throw new EditError(`Step ${JSON.stringify(stepId)} is a ${step.kind} step, not a path.`);
17
+ }
18
+ return step;
19
+ }
20
+ /** Applies `edit` to the step with this effective id, or throws naming the id that is not there. */
21
+ function editStep(auto, stepId, edit) {
22
+ const result = updateStep(auto.steps, "step", stepId, (step) => edit(step));
23
+ if (!result.found)
24
+ throw new EditError(`No step with id ${JSON.stringify(stepId)}.`);
25
+ return finish({ ...auto, steps: result.steps });
26
+ }
27
+ /** The segment at this index, or a message naming the step that has no such segment. */
28
+ function segmentAt(step, stepId, segmentIndex) {
29
+ const segment = step.segments[segmentIndex];
30
+ if (segment === undefined) {
31
+ throw new EditError(`Step ${JSON.stringify(stepId)} has no segment at index ${String(segmentIndex)}.`);
32
+ }
33
+ return segment;
34
+ }
35
+ /**
36
+ * Points a segment endpoint at a waypoint (`{ ref }`), at the previous step's end (`"current"`),
37
+ * or at a literal pose. The one edit `setPose` cannot express.
38
+ */
39
+ export function setSegmentSource(auto, stepId, segmentIndex, pointKind, source) {
40
+ return editStep(auto, stepId, (step) => {
41
+ const path = asPathStep(step, stepId);
42
+ segmentAt(path, stepId, segmentIndex);
43
+ const segments = path.segments.map((segment, index) => {
44
+ if (index !== segmentIndex)
45
+ return segment;
46
+ return pointKind === "from" ? { ...segment, from: source } : { ...segment, to: source };
47
+ });
48
+ return { ...path, segments };
49
+ });
50
+ }
51
+ /**
52
+ * Turns a segment into a line or a Bezier. Becoming a Bezier needs somewhere to put the new
53
+ * control point, and core will not invent one (CLAUDE.md rule 4): the caller passes the point,
54
+ * which is the segment's midpoint when the editor does it.
55
+ */
56
+ export function setSegmentKind(auto, stepId, segmentIndex, kind, control) {
57
+ return editStep(auto, stepId, (step) => {
58
+ const path = asPathStep(step, stepId);
59
+ segmentAt(path, stepId, segmentIndex);
60
+ const segments = path.segments.map((segment, index) => {
61
+ if (index !== segmentIndex || segment.kind === kind)
62
+ return segment;
63
+ if (kind === "line")
64
+ return { kind: "line", from: segment.from, to: segment.to };
65
+ return { kind: "bezier", from: segment.from, control: [control], to: segment.to };
66
+ });
67
+ return { ...path, segments };
68
+ });
69
+ }
70
+ /** Sets or clears a path step's end condition ("stop when the hopper is full"). */
71
+ export function setEndCondition(auto, stepId, condition) {
72
+ return editStep(auto, stepId, (step) => {
73
+ const path = asPathStep(step, stepId);
74
+ if (condition === null) {
75
+ const next = { ...path };
76
+ delete next.endCondition;
77
+ return next;
78
+ }
79
+ return { ...path, endCondition: { condition } };
80
+ });
81
+ }
82
+ /** Sets a step's note, or removes it when the text is blank. */
83
+ export function setNotes(auto, stepId, notes) {
84
+ return editStep(auto, stepId, (step) => {
85
+ if (notes.trim() === "") {
86
+ const next = { ...step };
87
+ delete next.notes;
88
+ return next;
89
+ }
90
+ return { ...step, notes };
91
+ });
92
+ }
93
+ /** Sets what a wait step waits for: a number of seconds, a robot-side condition, or both. */
94
+ export function setWait(auto, stepId, wait) {
95
+ return editStep(auto, stepId, (step) => {
96
+ if (step.kind !== "wait") {
97
+ throw new EditError(`Step ${JSON.stringify(stepId)} is a ${step.kind} step, not a wait.`);
98
+ }
99
+ const next = { ...step, seconds: wait.seconds, until: wait.until };
100
+ return next;
101
+ });
102
+ }
103
+ /** Sets a parallel group's mode, and which child is its deadline. */
104
+ export function setParallel(auto, stepId, patch) {
105
+ return editStep(auto, stepId, (step) => {
106
+ if (step.kind !== "parallel") {
107
+ throw new EditError(`Step ${JSON.stringify(stepId)} is a ${step.kind} step, not a parallel group.`);
108
+ }
109
+ const next = { ...step, ...patch };
110
+ return next;
111
+ });
112
+ }
113
+ /** Sets the robot-side condition a branch step asks about. */
114
+ export function setBranchCondition(auto, stepId, condition) {
115
+ return editStep(auto, stepId, (step) => {
116
+ if (step.kind !== "branch") {
117
+ throw new EditError(`Step ${JSON.stringify(stepId)} is a ${step.kind} step, not a branch.`);
118
+ }
119
+ const next = { ...step, condition };
120
+ return next;
121
+ });
122
+ }
123
+ /**
124
+ * Points a command step at a different registered command. The arguments go with the old name:
125
+ * they were built from its parameters, and keeping them would silently pass one command's
126
+ * arguments to another.
127
+ */
128
+ export function setCommandName(auto, stepId, name) {
129
+ return editStep(auto, stepId, (step) => {
130
+ if (step.kind !== "command") {
131
+ throw new EditError(`Step ${JSON.stringify(stepId)} is a ${step.kind} step, not a command.`);
132
+ }
133
+ return { ...step, name, args: undefined };
134
+ });
135
+ }
136
+ /** Replaces the command a marker fires, keeping where on the path it sits. */
137
+ export function setMarkerCommand(auto, stepId, markerIndex, command) {
138
+ return editStep(auto, stepId, (step) => {
139
+ const path = asPathStep(step, stepId);
140
+ const markers = path.markers ?? [];
141
+ if (markers[markerIndex] === undefined) {
142
+ throw new EditError(`Step ${JSON.stringify(stepId)} has no marker at index ${String(markerIndex)}.`);
143
+ }
144
+ return {
145
+ ...path,
146
+ markers: markers.map((marker, index) => index === markerIndex ? { ...marker, command } : marker),
147
+ };
148
+ });
149
+ }
150
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/edit/fields.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC;;;;;;;;;GASG;AAEH,SAAS,UAAU,CAAC,IAAU,EAAE,MAAc;IAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,oBAAoB,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oGAAoG;AACpG,SAAS,QAAQ,CAAC,IAAU,EAAE,MAAc,EAAE,IAA0B;IACtE,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,SAAS,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrF,OAAO,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,wFAAwF;AACxF,SAAS,SAAS,CAAC,IAAc,EAAE,MAAc,EAAE,YAAoB;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC5C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,SAAS,CACjB,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,4BAA4B,MAAM,CAAC,YAAY,CAAC,GAAG,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAU,EACV,MAAc,EACd,YAAoB,EACpB,SAAwB,EACxB,MAAkB;IAElB,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAW,EAAE;YAC7D,IAAI,KAAK,KAAK,YAAY;gBAAE,OAAO,OAAO,CAAC;YAC3C,OAAO,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAC1F,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAU,EACV,MAAc,EACd,YAAoB,EACpB,IAAqB,EACrB,OAAqC;IAErC,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAW,EAAE;YAC7D,IAAI,KAAK,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAC;YACpE,IAAI,IAAI,KAAK,MAAM;gBAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;YACjF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;QACpF,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,IAAU,EAAE,MAAc,EAAE,SAAwB;IAClF,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,YAAY,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,QAAQ,CAAC,IAAU,EAAE,MAAc,EAAE,KAAa;IAChE,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAA+B,CAAC;YACtD,OAAO,IAAI,CAAC,KAAK,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAU,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,OAAO,CACrB,IAAU,EACV,MAAc,EACd,IAA0C;IAE1C,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,oBAAoB,CAAC,CAAC;QAC5F,CAAC;QACD,MAAM,IAAI,GAAa,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,WAAW,CACzB,IAAU,EACV,MAAc,EACd,KAAyD;IAEzD,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,IAAI,SAAS,CACjB,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,8BAA8B,CAC/E,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAiB,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,kBAAkB,CAAC,IAAU,EAAE,MAAc,EAAE,SAAiB;IAC9E,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,sBAAsB,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,IAAI,GAAe,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,MAAc,EAAE,IAAY;IACrE,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,uBAAuB,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAC9B,IAAU,EACV,MAAc,EACd,WAAmB,EACnB,OAAoB;IAEpB,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,WAAW,CAAC,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,IAAI,SAAS,CACjB,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,2BAA2B,MAAM,CAAC,WAAW,CAAC,GAAG,CAChF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,GAAG,IAAI;YACP,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACrC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CACxD;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type Auto } from "@horizon36596/zenith-schema";
2
+ /**
3
+ * Every primitive in this directory ends by calling this on the candidate document it built.
4
+ * Parsing through the zod schema is what "keep canonical validity" means in practice: the schema
5
+ * both validates the result and produces a fresh object tree, so a primitive can build its
6
+ * candidate with ordinary object spreads without worrying about mutating anything the caller
7
+ * still holds a reference to, and a mutation that would leave the file invalid throws here with
8
+ * every failing key named, instead of writing a broken file.
9
+ *
10
+ * Unique effective ids are part of that validity, and the schema cannot express them: every
11
+ * primitive addresses a step by its id and `updateStep` stops at the first match, so a document
12
+ * with the same id twice would have its later steps silently unreachable.
13
+ */
14
+ export declare function finish(candidate: unknown): Auto;
15
+ //# sourceMappingURL=finish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../src/edit/finish.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAIhF;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAsB/C"}
@@ -0,0 +1,36 @@
1
+ import { parseAuto, SchemaError } from "@horizon36596/zenith-schema";
2
+ import { EditError } from "./errors.js";
3
+ import { duplicateIds } from "./ids.js";
4
+ /**
5
+ * Every primitive in this directory ends by calling this on the candidate document it built.
6
+ * Parsing through the zod schema is what "keep canonical validity" means in practice: the schema
7
+ * both validates the result and produces a fresh object tree, so a primitive can build its
8
+ * candidate with ordinary object spreads without worrying about mutating anything the caller
9
+ * still holds a reference to, and a mutation that would leave the file invalid throws here with
10
+ * every failing key named, instead of writing a broken file.
11
+ *
12
+ * Unique effective ids are part of that validity, and the schema cannot express them: every
13
+ * primitive addresses a step by its id and `updateStep` stops at the first match, so a document
14
+ * with the same id twice would have its later steps silently unreachable.
15
+ */
16
+ export function finish(candidate) {
17
+ try {
18
+ const auto = parseAuto(candidate);
19
+ const repeated = duplicateIds(auto.steps);
20
+ if (repeated.length > 0) {
21
+ throw new EditError(`This edit would leave two steps sharing the id ${repeated
22
+ .map((id) => JSON.stringify(id))
23
+ .join(", ")}, and every step is addressed by its id.`);
24
+ }
25
+ return auto;
26
+ }
27
+ catch (error) {
28
+ if (error instanceof SchemaError) {
29
+ throw new EditError(`This edit would leave the auto invalid:\n ${error.issues
30
+ .map((issue) => `${issue.path.length === 0 ? "(root)" : issue.path.join(".")}: ${issue.message}`)
31
+ .join("\n ")}`);
32
+ }
33
+ throw error;
34
+ }
35
+ }
36
+ //# sourceMappingURL=finish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finish.js","sourceRoot":"","sources":["../../src/edit/finish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAa,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,SAAkB;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,SAAS,CACjB,kDAAkD,QAAQ;iBACvD,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;iBAC/B,IAAI,CAAC,IAAI,CAAC,0CAA0C,CACxD,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,SAAS,CACjB,8CAA8C,KAAK,CAAC,MAAM;iBACvD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;iBAChG,IAAI,CAAC,MAAM,CAAC,EAAE,CAClB,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}