@adhamalkhaja/seyola-runtime 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,418 @@
1
+ /**
2
+ * seyola-runtime resolve-state — the I-010 architectural fix.
3
+ *
4
+ * Reads the day-graph + artifact-registry + workspace filesystem and
5
+ * computes the member's current day deterministically. Replaces the
6
+ * Phase 0a algorithm in atlas/SKILL.md that was previously LLM-
7
+ * interpreted (and prone to the defensive-Bash regression).
8
+ *
9
+ * Algorithm (deterministic; same input → same output):
10
+ *
11
+ * 1. Load .seyola/pack/architecture/day-graph.yaml
12
+ * 2. Load .seyola/pack/architecture/artifact-registry.yaml
13
+ * 3. For each day in day-graph.days[] where status: active, in
14
+ * ascending day order:
15
+ * a. For each step in steps[], collect artifact IDs from outputs[]
16
+ * where step is `required: true` (default true if unset)
17
+ * b. Resolve each artifact ID to its primary filesystem path via
18
+ * artifact-registry. Try aliases if primary doesn't exist.
19
+ * c. Check existence via fs.existsSync
20
+ * d. The day is COMPLETE iff every required output exists
21
+ * 4. completed_days = set of day numbers where complete=true
22
+ * 5. highest_contiguous = largest N such that {1..N} ⊆ completed_days
23
+ * 6. non_contiguous_completes = completed_days \ {1..highest_contiguous}
24
+ * 7. current_day = highest_contiguous + 1
25
+ * (unless current_day exceeds max active day — then program complete)
26
+ * 8. skip_detected = non_contiguous_completes is non-empty
27
+ * 9. skipped_days = the gap between highest_contiguous and the first
28
+ * non-contiguous-complete day (these are days the member needs to
29
+ * back-fill before routing forward)
30
+ * 10. Read runtime/atlas-state.md if it exists. Parse the canonical
31
+ * fields (First-touch, Days completed, Days skipped, Last-touch-day,
32
+ * plus any other fields written by downstream phases).
33
+ * 11. Reconcile: if cache.Days_completed != completed_days OR
34
+ * cache.Days_skipped != skipped_days OR cache.Last_touch_day
35
+ * != highest_contiguous, rewrite atlas-state.md preserving
36
+ * every other field verbatim. Only the 3 Phase-0a-owned fields
37
+ * change.
38
+ *
39
+ * Returns structured JSON. Skills invoke and surface consultatively.
40
+ *
41
+ * Special cases handled:
42
+ *
43
+ * - Empty workspace (no atlas-state.md): treat all values as
44
+ * null/empty. current_day = 1. Phase 2 first-session orientation
45
+ * writes the file (via Write tool in skill prose, not here).
46
+ *
47
+ * - Pre-shipped skeleton (atlas-state.md exists, First-touch: null):
48
+ * same as empty workspace. current_day = 1. The skeleton lives;
49
+ * Phase 2 will populate First-touch.
50
+ *
51
+ * - Member-written annotations in atlas-state.md: preserved verbatim
52
+ * across the reconciliation rewrite.
53
+ *
54
+ * - Rep-log pattern paths (runtime/{ordinal}-rep-log.md): handled via
55
+ * Glob-style scan when the artifact-registry entry uses a pattern.
56
+ *
57
+ * - Required: false outputs: skipped from the completeness check
58
+ * (path-aware, opt-in steps don't block day-completion).
59
+ */
60
+ import { existsSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
61
+ import { join, resolve } from "node:path";
62
+ import { parse as parseYamlText } from "yaml";
63
+ function parseYaml(text) {
64
+ return parseYamlText(text);
65
+ }
66
+ function resolveArtifactPath(registry, artifactId, workspacePath) {
67
+ const entry = registry.artifacts.find(a => a.id === artifactId);
68
+ if (!entry)
69
+ return null;
70
+ const cp = entry.current_paths ?? {};
71
+ const primary = cp.primary ?? cp.machine_readable ?? "";
72
+ const aliases = cp.aliases ?? [];
73
+ return {
74
+ primary: primary ? join(workspacePath, primary) : "",
75
+ aliases: aliases.map(a => join(workspacePath, a)),
76
+ pattern: entry.pattern_path,
77
+ };
78
+ }
79
+ function checkArtifactExists(registry, artifactId, workspacePath) {
80
+ const paths = resolveArtifactPath(registry, artifactId, workspacePath);
81
+ if (!paths)
82
+ return false;
83
+ if (paths.pattern) {
84
+ // Pattern paths: scan the parent directory for matching files
85
+ // e.g., "runtime/{ordinal}-rep-log.md" → check if any file matches
86
+ const parentDir = join(workspacePath, paths.pattern.split("/").slice(0, -1).join("/"));
87
+ if (!existsSync(parentDir))
88
+ return false;
89
+ const filenamePattern = paths.pattern.split("/").pop() ?? "";
90
+ const regex = new RegExp("^" + filenamePattern.replace(/\{[^}]+\}/g, ".*").replace(/\./g, "\\.") + "$");
91
+ try {
92
+ const entries = readdirSync(parentDir);
93
+ return entries.some(e => regex.test(e));
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ }
99
+ if (paths.primary && existsSync(paths.primary))
100
+ return true;
101
+ for (const alias of paths.aliases) {
102
+ if (existsSync(alias))
103
+ return true;
104
+ }
105
+ return false;
106
+ }
107
+ function walkDayGraph(dayGraph, registry, workspacePath) {
108
+ const result = [];
109
+ const activeDays = (dayGraph.days ?? [])
110
+ .filter(d => d.status === "active")
111
+ .sort((a, b) => a.day - b.day);
112
+ for (const day of activeDays) {
113
+ const missing = [];
114
+ for (const step of day.steps ?? []) {
115
+ const isRequired = step.required !== false; // default true
116
+ if (!isRequired)
117
+ continue;
118
+ for (const outputId of step.outputs ?? []) {
119
+ if (!checkArtifactExists(registry, outputId, workspacePath)) {
120
+ missing.push(outputId);
121
+ }
122
+ }
123
+ }
124
+ result.push({
125
+ day_number: day.day,
126
+ complete: missing.length === 0,
127
+ missing_outputs: missing,
128
+ });
129
+ }
130
+ return result;
131
+ }
132
+ function computeCurrentDay(walk) {
133
+ const completed = walk.filter(d => d.complete).map(d => d.day_number).sort((a, b) => a - b);
134
+ // highest_contiguous: largest N such that {1..N} ⊆ completed
135
+ let highest = 0;
136
+ const completedSet = new Set(completed);
137
+ for (let n = 1; n <= Math.max(...completed, 0) + 1; n++) {
138
+ if (completedSet.has(n))
139
+ highest = n;
140
+ else
141
+ break;
142
+ }
143
+ const skipped = completed.filter(d => d > highest);
144
+ // Day numbers between highest+1 and the lowest skipped-complete day are the "skipped days"
145
+ // (the ones the member needs to back-fill)
146
+ let skippedDays = [];
147
+ if (skipped.length > 0) {
148
+ const lowestSkipped = skipped[0];
149
+ for (let n = highest + 1; n < lowestSkipped; n++) {
150
+ skippedDays.push(n);
151
+ }
152
+ }
153
+ const current = highest + 1;
154
+ return {
155
+ completed,
156
+ skipped: skippedDays,
157
+ current,
158
+ skip_detected: skippedDays.length > 0,
159
+ };
160
+ }
161
+ function getNextSkill(dayGraph, currentDay) {
162
+ // Returns the FIRST skill to run for current_day.
163
+ // The day-graph's day-level `next_skill` field is the NEXT day's first
164
+ // skill (used by opens.day routing), NOT current day's first skill.
165
+ // So we always use steps[0].skill of the current day.
166
+ const day = dayGraph.days?.find(d => d.day === currentDay);
167
+ if (!day)
168
+ return null;
169
+ const firstStep = day.steps?.[0];
170
+ return firstStep?.skill ?? null;
171
+ }
172
+ function parseAtlasState(text) {
173
+ const lines = text.split("\n");
174
+ const result = {
175
+ first_touch: null,
176
+ urgency: "not_yet_surfaced",
177
+ external_deadline: null,
178
+ days_completed: [],
179
+ days_skipped: [],
180
+ file_anomalies: [],
181
+ last_touch_day: 0,
182
+ extra_lines: [],
183
+ };
184
+ for (const line of lines) {
185
+ const ftMatch = line.match(/^First-touch:\s*(.*)$/);
186
+ if (ftMatch) {
187
+ const v = ftMatch[1].trim();
188
+ result.first_touch = v === "null" || v === "" ? null : v;
189
+ continue;
190
+ }
191
+ const urgMatch = line.match(/^Urgency:\s*(.*)$/);
192
+ if (urgMatch) {
193
+ result.urgency = urgMatch[1].trim();
194
+ continue;
195
+ }
196
+ const edMatch = line.match(/^External-deadline:\s*(.*)$/);
197
+ if (edMatch) {
198
+ const v = edMatch[1].trim();
199
+ result.external_deadline = v === "null" || v === "" ? null : v;
200
+ continue;
201
+ }
202
+ const dcMatch = line.match(/^Days completed:\s*\[(.*)\]$/);
203
+ if (dcMatch) {
204
+ result.days_completed = dcMatch[1]
205
+ .split(",")
206
+ .map(s => parseInt(s.trim(), 10))
207
+ .filter(n => !isNaN(n));
208
+ continue;
209
+ }
210
+ const dsMatch = line.match(/^Days skipped:\s*\[(.*)\]$/);
211
+ if (dsMatch) {
212
+ result.days_skipped = dsMatch[1]
213
+ .split(",")
214
+ .map(s => parseInt(s.trim(), 10))
215
+ .filter(n => !isNaN(n));
216
+ continue;
217
+ }
218
+ const faMatch = line.match(/^File anomalies:\s*\[(.*)\]$/);
219
+ if (faMatch) {
220
+ result.file_anomalies = faMatch[1]
221
+ .split(",")
222
+ .map(s => s.trim())
223
+ .filter(s => s.length > 0);
224
+ continue;
225
+ }
226
+ const ltMatch = line.match(/^Last-touch-day:\s*(\d+)$/);
227
+ if (ltMatch) {
228
+ result.last_touch_day = parseInt(ltMatch[1], 10);
229
+ continue;
230
+ }
231
+ // Preserve everything else verbatim (other fields like
232
+ // urgency_capture, pause_state, buyer_fit_signal, reverse_drift_state,
233
+ // headers, comments, annotations).
234
+ result.extra_lines.push(line);
235
+ }
236
+ return result;
237
+ }
238
+ function serializeAtlasState(fields) {
239
+ // Reconstruct the file from the canonical structure + preserved extras.
240
+ // Phase 2 / first-session orientation uses this same shape.
241
+ const canonicalLines = [];
242
+ const seenKeys = new Set();
243
+ // Walk extras first, replacing canonical-field lines as we go.
244
+ // This preserves comments, headers, and other phase-owned fields in
245
+ // their original order.
246
+ for (const line of fields.extra_lines) {
247
+ if (/^First-touch:/.test(line)) {
248
+ canonicalLines.push(`First-touch: ${fields.first_touch ?? "null"}`);
249
+ seenKeys.add("first_touch");
250
+ continue;
251
+ }
252
+ if (/^Urgency:/.test(line)) {
253
+ canonicalLines.push(`Urgency: ${fields.urgency}`);
254
+ seenKeys.add("urgency");
255
+ continue;
256
+ }
257
+ if (/^External-deadline:/.test(line)) {
258
+ canonicalLines.push(`External-deadline: ${fields.external_deadline ?? "null"}`);
259
+ seenKeys.add("external_deadline");
260
+ continue;
261
+ }
262
+ if (/^Days completed:/.test(line)) {
263
+ canonicalLines.push(`Days completed: [${fields.days_completed.join(", ")}]`);
264
+ seenKeys.add("days_completed");
265
+ continue;
266
+ }
267
+ if (/^Days skipped:/.test(line)) {
268
+ canonicalLines.push(`Days skipped: [${fields.days_skipped.join(", ")}]`);
269
+ seenKeys.add("days_skipped");
270
+ continue;
271
+ }
272
+ if (/^File anomalies:/.test(line)) {
273
+ canonicalLines.push(`File anomalies: [${fields.file_anomalies.join(", ")}]`);
274
+ seenKeys.add("file_anomalies");
275
+ continue;
276
+ }
277
+ if (/^Last-touch-day:/.test(line)) {
278
+ canonicalLines.push(`Last-touch-day: ${fields.last_touch_day}`);
279
+ seenKeys.add("last_touch_day");
280
+ continue;
281
+ }
282
+ canonicalLines.push(line);
283
+ }
284
+ // If any canonical field was never present in the file, append it
285
+ // (covers freshly-skeletoned files).
286
+ if (!seenKeys.has("first_touch"))
287
+ canonicalLines.push(`First-touch: ${fields.first_touch ?? "null"}`);
288
+ if (!seenKeys.has("urgency"))
289
+ canonicalLines.push(`Urgency: ${fields.urgency}`);
290
+ if (!seenKeys.has("external_deadline"))
291
+ canonicalLines.push(`External-deadline: ${fields.external_deadline ?? "null"}`);
292
+ if (!seenKeys.has("days_completed"))
293
+ canonicalLines.push(`Days completed: [${fields.days_completed.join(", ")}]`);
294
+ if (!seenKeys.has("days_skipped"))
295
+ canonicalLines.push(`Days skipped: [${fields.days_skipped.join(", ")}]`);
296
+ if (!seenKeys.has("file_anomalies"))
297
+ canonicalLines.push(`File anomalies: [${fields.file_anomalies.join(", ")}]`);
298
+ if (!seenKeys.has("last_touch_day"))
299
+ canonicalLines.push(`Last-touch-day: ${fields.last_touch_day}`);
300
+ return canonicalLines.join("\n");
301
+ }
302
+ export async function runResolveState(inputs) {
303
+ const start = Date.now();
304
+ const workspace = resolve(inputs.workspacePath);
305
+ const dayGraphPath = join(workspace, ".seyola", "pack", "architecture", "day-graph.yaml");
306
+ const registryPath = join(workspace, ".seyola", "pack", "architecture", "artifact-registry.yaml");
307
+ if (!existsSync(dayGraphPath)) {
308
+ const result = {
309
+ exitCode: 2,
310
+ workspace_path: workspace,
311
+ current_day: 0,
312
+ completed_days: [],
313
+ skipped_days: [],
314
+ skip_detected: false,
315
+ next_skill: null,
316
+ atlas_state_rewritten: false,
317
+ atlas_state_path: join(workspace, "runtime", "atlas-state.md"),
318
+ is_first_session: false,
319
+ duration_ms: Date.now() - start,
320
+ day_walk: [],
321
+ };
322
+ if (inputs.json)
323
+ console.log(JSON.stringify({ ...result, error: "day-graph.yaml not found" }, null, 2));
324
+ else
325
+ console.error("seyola-runtime resolve-state: day-graph.yaml not found at " + dayGraphPath);
326
+ return result;
327
+ }
328
+ if (!existsSync(registryPath)) {
329
+ const result = {
330
+ exitCode: 2,
331
+ workspace_path: workspace,
332
+ current_day: 0,
333
+ completed_days: [],
334
+ skipped_days: [],
335
+ skip_detected: false,
336
+ next_skill: null,
337
+ atlas_state_rewritten: false,
338
+ atlas_state_path: join(workspace, "runtime", "atlas-state.md"),
339
+ is_first_session: false,
340
+ duration_ms: Date.now() - start,
341
+ day_walk: [],
342
+ };
343
+ if (inputs.json)
344
+ console.log(JSON.stringify({ ...result, error: "artifact-registry.yaml not found" }, null, 2));
345
+ else
346
+ console.error("seyola-runtime resolve-state: artifact-registry.yaml not found at " + registryPath);
347
+ return result;
348
+ }
349
+ const dayGraph = parseYaml(readFileSync(dayGraphPath, "utf8"));
350
+ const registry = parseYaml(readFileSync(registryPath, "utf8"));
351
+ const walk = walkDayGraph(dayGraph, registry, workspace);
352
+ const computed = computeCurrentDay(walk);
353
+ const nextSkill = getNextSkill(dayGraph, computed.current);
354
+ // Atlas-state reconciliation
355
+ const atlasStatePath = join(workspace, "runtime", "atlas-state.md");
356
+ let atlasStateRewritten = false;
357
+ let isFirstSession = false;
358
+ if (existsSync(atlasStatePath)) {
359
+ const text = readFileSync(atlasStatePath, "utf8");
360
+ const cache = parseAtlasState(text);
361
+ isFirstSession = cache.first_touch === null;
362
+ // Compute the reconciled fields (Phase-0a owns only 3 fields)
363
+ const reconciled = {
364
+ ...cache,
365
+ days_completed: computed.completed,
366
+ days_skipped: computed.skipped,
367
+ last_touch_day: Math.max(...computed.completed, 0),
368
+ };
369
+ // Compare against cache to decide if rewrite is needed
370
+ const sameCompleted = cache.days_completed.length === reconciled.days_completed.length &&
371
+ cache.days_completed.every((v, i) => v === reconciled.days_completed[i]);
372
+ const sameSkipped = cache.days_skipped.length === reconciled.days_skipped.length &&
373
+ cache.days_skipped.every((v, i) => v === reconciled.days_skipped[i]);
374
+ const sameLastTouch = cache.last_touch_day === reconciled.last_touch_day;
375
+ if (!sameCompleted || !sameSkipped || !sameLastTouch) {
376
+ const newText = serializeAtlasState(reconciled);
377
+ writeFileSync(atlasStatePath, newText, "utf8");
378
+ atlasStateRewritten = true;
379
+ }
380
+ }
381
+ else {
382
+ // No atlas-state.md present. Treat as first-session. Don't create
383
+ // the file here — Phase 2 first-session orientation owns creation
384
+ // (or the bundle's pre-shipped skeleton, since v0.12.2).
385
+ isFirstSession = true;
386
+ }
387
+ const result = {
388
+ exitCode: 0,
389
+ workspace_path: workspace,
390
+ current_day: computed.current,
391
+ completed_days: computed.completed,
392
+ skipped_days: computed.skipped,
393
+ skip_detected: computed.skip_detected,
394
+ next_skill: nextSkill,
395
+ atlas_state_rewritten: atlasStateRewritten,
396
+ atlas_state_path: atlasStatePath,
397
+ is_first_session: isFirstSession,
398
+ duration_ms: Date.now() - start,
399
+ day_walk: walk,
400
+ };
401
+ if (inputs.json) {
402
+ console.log(JSON.stringify(result, null, 2));
403
+ }
404
+ else {
405
+ console.error(`seyola-runtime resolve-state: status=ok, exitCode=0\n` +
406
+ ` workspace: ${workspace}\n` +
407
+ ` current_day: ${result.current_day}\n` +
408
+ ` completed_days: [${result.completed_days.join(", ")}]\n` +
409
+ ` skipped_days: [${result.skipped_days.join(", ")}]\n` +
410
+ ` skip_detected: ${result.skip_detected}\n` +
411
+ ` next_skill: ${result.next_skill ?? "(none)"}\n` +
412
+ ` atlas_state_rewritten: ${result.atlas_state_rewritten}\n` +
413
+ ` is_first_session: ${result.is_first_session}\n` +
414
+ ` duration: ${result.duration_ms}ms`);
415
+ }
416
+ return result;
417
+ }
418
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resolve-state/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAkE9C,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,mBAAmB,CAC1B,QAA0B,EAC1B,UAAkB,EAClB,aAAqB;IAErB,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,EAAE,GAAG,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC;IACjC,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;QACpD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QACjD,OAAO,EAAE,KAAK,CAAC,YAAY;KAC5B,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,QAA0B,EAC1B,UAAkB,EAClB,aAAqB;IAErB,MAAM,KAAK,GAAG,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,8DAA8D;QAC9D,mEAAmE;QACnE,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QACzC,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,GAAG,CAC9E,CAAC;QACF,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;YACvC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CACnB,QAAkB,EAClB,QAA0B,EAC1B,aAAqB;IAErB,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;SACrC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC;SAClC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACnC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,eAAe;YAC3D,IAAI,CAAC,UAAU;gBAAE,SAAS;YAC1B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC;oBAC5D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;YACV,UAAU,EAAE,GAAG,CAAC,GAAG;YACnB,QAAQ,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;YAC9B,eAAe,EAAE,OAAO;SACzB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAiB;IAM1C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5F,6DAA6D;IAC7D,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxD,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC,CAAC;;YAChC,MAAM;IACb,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;IACnD,2FAA2F;IAC3F,2CAA2C;IAC3C,IAAI,WAAW,GAAa,EAAE,CAAC;IAC/B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,CAAC;IAC5B,OAAO;QACL,SAAS;QACT,OAAO,EAAE,WAAW;QACpB,OAAO;QACP,aAAa,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,QAAkB,EAAE,UAAkB;IAC1D,kDAAkD;IAClD,uEAAuE;IACvE,oEAAoE;IACpE,sDAAsD;IACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC;IAC3D,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,OAAO,SAAS,EAAE,KAAK,IAAI,IAAI,CAAC;AAClC,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAqB;QAC/B,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,kBAAkB;QAC3B,iBAAiB,EAAE,IAAI;QACvB,cAAc,EAAE,EAAE;QAClB,YAAY,EAAE,EAAE;QAChB,cAAc,EAAE,EAAE;QAClB,cAAc,EAAE,CAAC;QACjB,WAAW,EAAE,EAAE;KAChB,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACpD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;YAC7B,MAAM,CAAC,WAAW,GAAG,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACjD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;YACrC,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC1D,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;YAC7B,MAAM,CAAC,iBAAiB,GAAG,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/D,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC3D,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,CAAC,CAAE;iBAChC,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;iBAChC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QACzD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,YAAY,GAAG,OAAO,CAAC,CAAC,CAAE;iBAC9B,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;iBAChC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC3D,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,CAAC,CAAE;iBAChC,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACxD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;YAClD,SAAS;QACX,CAAC;QACD,uDAAuD;QACvD,uEAAuE;QACvE,mCAAmC;QACnC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAwB;IACnD,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,+DAA+D;IAC/D,oEAAoE;IACpE,wBAAwB;IACxB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACtC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,cAAc,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,WAAW,IAAI,MAAM,EAAE,CAAC,CAAC;YACpE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,cAAc,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAClD,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACxB,SAAS;QACX,CAAC;QACD,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,cAAc,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,iBAAiB,IAAI,MAAM,EAAE,CAAC,CAAC;YAChF,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAClC,SAAS;QACX,CAAC;QACD,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,cAAc,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7E,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,cAAc,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzE,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,cAAc,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7E,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,cAAc,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;YAChE,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,kEAAkE;IAClE,qCAAqC;IACrC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,WAAW,IAAI,MAAM,EAAE,CAAC,CAAC;IACtG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAChF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,iBAAiB,IAAI,MAAM,EAAE,CAAC,CAAC;IACxH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5G,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACrG,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAA0B;IAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC1F,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,wBAAwB,CAAC,CAAC;IAElG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAuB;YACjC,QAAQ,EAAE,CAAC;YACX,cAAc,EAAE,SAAS;YACzB,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,EAAE;YAClB,YAAY,EAAE,EAAE;YAChB,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,IAAI;YAChB,qBAAqB,EAAE,KAAK;YAC5B,gBAAgB,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,CAAC;YAC9D,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC/B,QAAQ,EAAE,EAAE;SACb,CAAC;QACF,IAAI,MAAM,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,0BAA0B,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;YACnG,OAAO,CAAC,KAAK,CAAC,4DAA4D,GAAG,YAAY,CAAC,CAAC;QAChG,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAuB;YACjC,QAAQ,EAAE,CAAC;YACX,cAAc,EAAE,SAAS;YACzB,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,EAAE;YAClB,YAAY,EAAE,EAAE;YAChB,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,IAAI;YAChB,qBAAqB,EAAE,KAAK;YAC5B,gBAAgB,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,CAAC;YAC9D,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC/B,QAAQ,EAAE,EAAE;SACb,CAAC;QACF,IAAI,MAAM,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,kCAAkC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;YAC3G,OAAO,CAAC,KAAK,CAAC,oEAAoE,GAAG,YAAY,CAAC,CAAC;QACxG,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAa,CAAC;IAC3E,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAqB,CAAC;IAEnF,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE3D,6BAA6B;IAC7B,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACpE,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAChC,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACpC,cAAc,GAAG,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC;QAE5C,8DAA8D;QAC9D,MAAM,UAAU,GAAqB;YACnC,GAAG,KAAK;YACR,cAAc,EAAE,QAAQ,CAAC,SAAS;YAClC,YAAY,EAAE,QAAQ,CAAC,OAAO;YAC9B,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;SACnD,CAAC;QAEF,uDAAuD;QACvD,MAAM,aAAa,GACjB,KAAK,CAAC,cAAc,CAAC,MAAM,KAAK,UAAU,CAAC,cAAc,CAAC,MAAM;YAChE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,WAAW,GACf,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU,CAAC,YAAY,CAAC,MAAM;YAC5D,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,aAAa,GAAG,KAAK,CAAC,cAAc,KAAK,UAAU,CAAC,cAAc,CAAC;QAEzE,IAAI,CAAC,aAAa,IAAI,CAAC,WAAW,IAAI,CAAC,aAAa,EAAE,CAAC;YACrD,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;YAChD,aAAa,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/C,mBAAmB,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,kEAAkE;QAClE,kEAAkE;QAClE,yDAAyD;QACzD,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,MAAM,MAAM,GAAuB;QACjC,QAAQ,EAAE,CAAC;QACX,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,QAAQ,CAAC,OAAO;QAC7B,cAAc,EAAE,QAAQ,CAAC,SAAS;QAClC,YAAY,EAAE,QAAQ,CAAC,OAAO;QAC9B,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,UAAU,EAAE,SAAS;QACrB,qBAAqB,EAAE,mBAAmB;QAC1C,gBAAgB,EAAE,cAAc;QAChC,gBAAgB,EAAE,cAAc;QAChC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;QAC/B,QAAQ,EAAE,IAAI;KACf,CAAC;IAEF,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CACX,uDAAuD;YACrD,uBAAuB,SAAS,IAAI;YACpC,uBAAuB,MAAM,CAAC,WAAW,IAAI;YAC7C,wBAAwB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAC7D,wBAAwB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAC3D,uBAAuB,MAAM,CAAC,aAAa,IAAI;YAC/C,uBAAuB,MAAM,CAAC,UAAU,IAAI,QAAQ,IAAI;YACxD,4BAA4B,MAAM,CAAC,qBAAqB,IAAI;YAC5D,uBAAuB,MAAM,CAAC,gBAAgB,IAAI;YAClD,uBAAuB,MAAM,CAAC,WAAW,IAAI,CAChD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * seyola-runtime verify-write-count — generic Phase-6 self-check.
3
+ *
4
+ * The I-008 fix codified as a runtime check. Skills like
5
+ * /sales-infrastructure write exactly 3 (or 5 for sales_email) files in
6
+ * their Phase 6. If duplicate writes happen, I-008 reproduces and
7
+ * downstream skills get confused.
8
+ *
9
+ * This command counts files written to specific paths within a recent
10
+ * time window + verifies the count matches expected. Returns structured
11
+ * verdict.
12
+ *
13
+ * Usage:
14
+ * seyola-runtime verify-write-count --expected 3 --workspace .
15
+ * --paths outreach/reply-playbook.md,outreach/lead-tracker.md,outreach/booking-flow-setup.md
16
+ * --since 2026-05-24T10:00:00Z
17
+ *
18
+ * Returns: {verdict, actual_count, expected_count, files_found, duplicates_detected}
19
+ *
20
+ * Note: this command operates on filesystem state, not session history.
21
+ * If a skill writes a file twice in the SAME session, only the latest
22
+ * version exists on disk — so this won't directly catch "wrote it twice."
23
+ * But it WILL catch "wrote a file that shouldn't exist" or "didn't write
24
+ * a file that should." For genuine duplicate-write detection, the skill
25
+ * must log its Write tool calls separately and pass --log <path>.
26
+ */
27
+ export interface VerifyWriteCountInputs {
28
+ workspacePath: string;
29
+ expected: number;
30
+ paths?: string[];
31
+ since?: string;
32
+ json?: boolean;
33
+ }
34
+ export interface VerifyWriteCountResult {
35
+ exitCode: number;
36
+ expected_count: number;
37
+ actual_count: number;
38
+ verdict: "pass" | "fail";
39
+ files_found: Array<{
40
+ path: string;
41
+ modified: string;
42
+ size_bytes: number;
43
+ }>;
44
+ files_missing: string[];
45
+ unexpected_files: string[];
46
+ duration_ms: number;
47
+ }
48
+ export declare function runVerifyWriteCount(inputs: VerifyWriteCountInputs): Promise<VerifyWriteCountResult>;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verify-write-count/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAuEzG"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * seyola-runtime verify-write-count — generic Phase-6 self-check.
3
+ *
4
+ * The I-008 fix codified as a runtime check. Skills like
5
+ * /sales-infrastructure write exactly 3 (or 5 for sales_email) files in
6
+ * their Phase 6. If duplicate writes happen, I-008 reproduces and
7
+ * downstream skills get confused.
8
+ *
9
+ * This command counts files written to specific paths within a recent
10
+ * time window + verifies the count matches expected. Returns structured
11
+ * verdict.
12
+ *
13
+ * Usage:
14
+ * seyola-runtime verify-write-count --expected 3 --workspace .
15
+ * --paths outreach/reply-playbook.md,outreach/lead-tracker.md,outreach/booking-flow-setup.md
16
+ * --since 2026-05-24T10:00:00Z
17
+ *
18
+ * Returns: {verdict, actual_count, expected_count, files_found, duplicates_detected}
19
+ *
20
+ * Note: this command operates on filesystem state, not session history.
21
+ * If a skill writes a file twice in the SAME session, only the latest
22
+ * version exists on disk — so this won't directly catch "wrote it twice."
23
+ * But it WILL catch "wrote a file that shouldn't exist" or "didn't write
24
+ * a file that should." For genuine duplicate-write detection, the skill
25
+ * must log its Write tool calls separately and pass --log <path>.
26
+ */
27
+ import { existsSync, statSync } from "node:fs";
28
+ import { join, resolve } from "node:path";
29
+ export async function runVerifyWriteCount(inputs) {
30
+ const start = Date.now();
31
+ const workspace = resolve(inputs.workspacePath);
32
+ const expectedPaths = inputs.paths ?? [];
33
+ let sinceDate = null;
34
+ if (inputs.since) {
35
+ sinceDate = new Date(inputs.since);
36
+ if (isNaN(sinceDate.getTime())) {
37
+ const result = {
38
+ exitCode: 2,
39
+ expected_count: inputs.expected,
40
+ actual_count: 0,
41
+ verdict: "fail",
42
+ files_found: [],
43
+ files_missing: [],
44
+ unexpected_files: [],
45
+ duration_ms: Date.now() - start,
46
+ };
47
+ if (inputs.json)
48
+ console.log(JSON.stringify({ ...result, error: "Invalid --since date" }, null, 2));
49
+ else
50
+ console.error(`verify-write-count: invalid --since date '${inputs.since}'`);
51
+ return result;
52
+ }
53
+ }
54
+ const filesFound = [];
55
+ const filesMissing = [];
56
+ for (const relPath of expectedPaths) {
57
+ const absPath = join(workspace, relPath);
58
+ if (!existsSync(absPath)) {
59
+ filesMissing.push(relPath);
60
+ continue;
61
+ }
62
+ const stat = statSync(absPath);
63
+ if (sinceDate && stat.mtime < sinceDate) {
64
+ // File exists but was written before the --since cutoff. Treat as missing for this check.
65
+ filesMissing.push(`${relPath} (modified before --since cutoff)`);
66
+ continue;
67
+ }
68
+ filesFound.push({
69
+ path: relPath,
70
+ modified: stat.mtime.toISOString(),
71
+ size_bytes: stat.size,
72
+ });
73
+ }
74
+ const actualCount = filesFound.length;
75
+ const verdict = actualCount === inputs.expected && filesMissing.length === 0 ? "pass" : "fail";
76
+ const result = {
77
+ exitCode: verdict === "pass" ? 0 : 1,
78
+ expected_count: inputs.expected,
79
+ actual_count: actualCount,
80
+ verdict,
81
+ files_found: filesFound,
82
+ files_missing: filesMissing,
83
+ unexpected_files: [], // could extend to scan for files that shouldn't exist
84
+ duration_ms: Date.now() - start,
85
+ };
86
+ if (inputs.json) {
87
+ console.log(JSON.stringify(result, null, 2));
88
+ }
89
+ else {
90
+ console.error(`verify-write-count: ${verdict} (${actualCount}/${inputs.expected}` +
91
+ (filesMissing.length > 0 ? `, missing: ${filesMissing.join(", ")}` : "") +
92
+ `)`);
93
+ }
94
+ return result;
95
+ }
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verify-write-count/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhamalkhaja/seyola-runtime",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "Local CLI runtime for the Seyola business operating system. Reads contracts from a Seyola pack and executes them against a runtime backend (claude-code-local).",
5
5
  "keywords": [
6
6
  "seyola",