@younndai/lyt-mesh 0.9.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.
Files changed (96) hide show
  1. package/LICENSE +200 -0
  2. package/NOTICE +23 -0
  3. package/README.md +135 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +34 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/clone-all.d.ts +3 -0
  9. package/dist/commands/clone-all.d.ts.map +1 -0
  10. package/dist/commands/clone-all.js +66 -0
  11. package/dist/commands/clone-all.js.map +1 -0
  12. package/dist/commands/mesh-init.d.ts +3 -0
  13. package/dist/commands/mesh-init.d.ts.map +1 -0
  14. package/dist/commands/mesh-init.js +70 -0
  15. package/dist/commands/mesh-init.js.map +1 -0
  16. package/dist/commands/pod-status.d.ts +3 -0
  17. package/dist/commands/pod-status.d.ts.map +1 -0
  18. package/dist/commands/pod-status.js +67 -0
  19. package/dist/commands/pod-status.js.map +1 -0
  20. package/dist/commands/source.d.ts +3 -0
  21. package/dist/commands/source.d.ts.map +1 -0
  22. package/dist/commands/source.js +83 -0
  23. package/dist/commands/source.js.map +1 -0
  24. package/dist/commands/status.d.ts +4 -0
  25. package/dist/commands/status.d.ts.map +1 -0
  26. package/dist/commands/status.js +121 -0
  27. package/dist/commands/status.js.map +1 -0
  28. package/dist/commands/sync.d.ts +3 -0
  29. package/dist/commands/sync.d.ts.map +1 -0
  30. package/dist/commands/sync.js +234 -0
  31. package/dist/commands/sync.js.map +1 -0
  32. package/dist/commands/validate.d.ts +3 -0
  33. package/dist/commands/validate.d.ts.map +1 -0
  34. package/dist/commands/validate.js +66 -0
  35. package/dist/commands/validate.js.map +1 -0
  36. package/dist/discovery/github.d.ts +19 -0
  37. package/dist/discovery/github.d.ts.map +1 -0
  38. package/dist/discovery/github.js +90 -0
  39. package/dist/discovery/github.js.map +1 -0
  40. package/dist/discovery/walk.d.ts +28 -0
  41. package/dist/discovery/walk.d.ts.map +1 -0
  42. package/dist/discovery/walk.js +78 -0
  43. package/dist/discovery/walk.js.map +1 -0
  44. package/dist/flows/clone-all.d.ts +53 -0
  45. package/dist/flows/clone-all.d.ts.map +1 -0
  46. package/dist/flows/clone-all.js +123 -0
  47. package/dist/flows/clone-all.js.map +1 -0
  48. package/dist/flows/mesh-init-validate.d.ts +22 -0
  49. package/dist/flows/mesh-init-validate.d.ts.map +1 -0
  50. package/dist/flows/mesh-init-validate.js +195 -0
  51. package/dist/flows/mesh-init-validate.js.map +1 -0
  52. package/dist/flows/mesh-init.d.ts +46 -0
  53. package/dist/flows/mesh-init.d.ts.map +1 -0
  54. package/dist/flows/mesh-init.js +302 -0
  55. package/dist/flows/mesh-init.js.map +1 -0
  56. package/dist/flows/pod-status.d.ts +37 -0
  57. package/dist/flows/pod-status.d.ts.map +1 -0
  58. package/dist/flows/pod-status.js +269 -0
  59. package/dist/flows/pod-status.js.map +1 -0
  60. package/dist/flows/status.d.ts +16 -0
  61. package/dist/flows/status.d.ts.map +1 -0
  62. package/dist/flows/status.js +76 -0
  63. package/dist/flows/status.js.map +1 -0
  64. package/dist/flows/sync-check.d.ts +38 -0
  65. package/dist/flows/sync-check.d.ts.map +1 -0
  66. package/dist/flows/sync-check.js +180 -0
  67. package/dist/flows/sync-check.js.map +1 -0
  68. package/dist/flows/sync-watch.d.ts +24 -0
  69. package/dist/flows/sync-watch.d.ts.map +1 -0
  70. package/dist/flows/sync-watch.js +217 -0
  71. package/dist/flows/sync-watch.js.map +1 -0
  72. package/dist/flows/sync.d.ts +45 -0
  73. package/dist/flows/sync.d.ts.map +1 -0
  74. package/dist/flows/sync.js +513 -0
  75. package/dist/flows/sync.js.map +1 -0
  76. package/dist/flows/validate.d.ts +22 -0
  77. package/dist/flows/validate.d.ts.map +1 -0
  78. package/dist/flows/validate.js +62 -0
  79. package/dist/flows/validate.js.map +1 -0
  80. package/dist/index.d.ts +35 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +39 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/mesh-command.d.ts +3 -0
  85. package/dist/mesh-command.d.ts.map +1 -0
  86. package/dist/mesh-command.js +31 -0
  87. package/dist/mesh-command.js.map +1 -0
  88. package/dist/source/repo.d.ts +14 -0
  89. package/dist/source/repo.d.ts.map +1 -0
  90. package/dist/source/repo.js +71 -0
  91. package/dist/source/repo.js.map +1 -0
  92. package/dist/source/types.d.ts +22 -0
  93. package/dist/source/types.d.ts.map +1 -0
  94. package/dist/source/types.js +49 -0
  95. package/dist/source/types.js.map +1 -0
  96. package/package.json +77 -0
@@ -0,0 +1,513 @@
1
+ /*
2
+ * Copyright 2026 MARLINK TRADING SRL (YounndAI)
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { existsSync, readFileSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ import { buildVaultCommitMessage, classifyPorcelainLine, closeRegistry, getHandleFromIdentity, isConfigPath, isFigmentPath, isLytDbCorrupt, listMeshes, listSubscriptionsForMesh, listVaults, openRegistry, readFigmentTitle, readFrozenLock, regenContextFlow, runGit as defaultRunGit, upsertArcsCache, upsertFtsCache, upsertLanesCache, upsertLedgerCache, uuid7BytesToHex, writeIndexWatermark, } from "@younndai/lyt-vault";
19
+ const MESH_CONTEXT_PATH = ".lyt/mesh-context.md";
20
+ export async function syncFlow(args = {}) {
21
+ const runGit = args.runGit ?? defaultRunGit;
22
+ const now = args.now ?? new Date();
23
+ const db = await openRegistry();
24
+ let candidates;
25
+ // v1.C.2 — derive the set of subscribed-vault rids across all
26
+ // registered meshes BEFORE iterating, so each report can be tagged
27
+ // with `subscribed: true` when applicable. Subscribed vaults are
28
+ // already registered locally (clone-on-subscribe lands them in the
29
+ // vaults table), so no double-dispatch is needed; the cross-mesh
30
+ // subscription view is purely classificatory at sync time. Per
31
+ // brief OD-9 default extension path: no meta-CLI edit, no new
32
+ // syncOneVault call — additive discriminator only.
33
+ let subscribedRidHexes = new Set();
34
+ try {
35
+ const all = await listVaults(db);
36
+ candidates =
37
+ args.vaultNames && args.vaultNames.length > 0
38
+ ? all.filter((v) => args.vaultNames.includes(v.name))
39
+ : all;
40
+ const meshes = await listMeshes(db);
41
+ for (const m of meshes) {
42
+ const subs = await listSubscriptionsForMesh(db, m.rid);
43
+ for (const s of subs) {
44
+ subscribedRidHexes.add(uuid7BytesToHex(s.externalVaultRid));
45
+ }
46
+ }
47
+ }
48
+ finally {
49
+ await closeRegistry(db);
50
+ }
51
+ const reports = [];
52
+ for (const v of candidates) {
53
+ const report = await syncOneVault(v, runGit, now, args.resolveMeshContext === true, args.message);
54
+ const ridHex = uuid7BytesToHex(v.rid);
55
+ if (subscribedRidHexes.has(ridHex)) {
56
+ report.subscribed = true;
57
+ }
58
+ // index-corruption surface. One probe at the loop chokepoint
59
+ // (not per-return inside syncOneVault). Skipped-* statuses are excluded:
60
+ // sync didn't touch the vault, so it makes no claims about it (the probe
61
+ // itself is READ-ONLY — raw client + PRAGMA quick_check, no migrations —
62
+ // so this is a consistency choice, not a freeze-safety requirement;
63
+ // doctor/repair probe frozen vaults with the same read-only probe). The
64
+ // probe is detect-only (isLytDbCorrupt never heals); failures of the
65
+ // probe itself are non-fatal — sync's git work already succeeded.
66
+ if (!report.status.startsWith("skipped-") && report.status !== "not-git-repo") {
67
+ try {
68
+ if (await isLytDbCorrupt(v.path)) {
69
+ report.indexCorrupt = true;
70
+ report.message =
71
+ `${report.message}; WARNING: search index (.lyt/indexes/lyt.db) is corrupt — ` +
72
+ `git layer synced fine, but search/recall/primer are degraded. Run 'lyt reindex --vault '${v.name}'' to rebuild it.`;
73
+ }
74
+ }
75
+ catch {
76
+ // probe failure (e.g. transient lock) — never fail the sync over it
77
+ }
78
+ }
79
+ reports.push(report);
80
+ }
81
+ const ok = reports.every((r) => r.status !== "conflict" && r.status !== "error");
82
+ return { reports, ok, frictionHints: deriveFrictionHints(reports) };
83
+ }
84
+ // Arc §10.4 — on a sync that hits a friction-worthy outcome, surface a
85
+ // one-line capture nudge so the handler can log it without re-typing
86
+ // boilerplate. The hints are returned as data; the calling command
87
+ // (packages/lyt-mesh/src/commands/sync.ts) decides whether to emit them
88
+ // to stderr (gated by --quiet + --json — both silence).
89
+ // v1.M.0 (P0-b) — reconcile the four .db caches (ledger → lanes → arcs →
90
+ // fts) from the on-disk SoT (YON ledgers + lanes/arcs.yon + notes/*.md).
91
+ // Extracted from the former post-pull-only block so a single sync
92
+ // reconciles caches UNCONDITIONALLY — whether the new state arrived via a
93
+ // local commit (no-remote vault) or a successful pull. Each upsert is
94
+ // best-effort + non-fatal (matches the prior post-pull posture); a failure
95
+ // in one upsert logs and does NOT abort the others or fail the sync.
96
+ // Deterministic call order matches the master-plan search-tier dependency:
97
+ // ledger → lanes → arcs → fts. The downstream upsert flows each early-
98
+ // return ran=false when their SoT is absent, so calling all four on a
99
+ // vault that only has notes/ (or only ledgers) is cheap, not wasteful.
100
+ async function reconcileVaultCaches(vaultPath, vaultName) {
101
+ try {
102
+ await upsertLedgerCache(vaultPath);
103
+ }
104
+ catch (err) {
105
+ // eslint-disable-next-line no-console
106
+ console.error(`lyt sync: ledger upsert failed for ${vaultName}: ${err instanceof Error ? err.message : String(err)}`);
107
+ }
108
+ try {
109
+ await upsertLanesCache(vaultPath);
110
+ }
111
+ catch (err) {
112
+ // eslint-disable-next-line no-console
113
+ console.error(`lyt sync: lanes upsert failed for ${vaultName}: ${err instanceof Error ? err.message : String(err)}`);
114
+ }
115
+ try {
116
+ await upsertArcsCache(vaultPath);
117
+ }
118
+ catch (err) {
119
+ // eslint-disable-next-line no-console
120
+ console.error(`lyt sync: arcs upsert failed for ${vaultName}: ${err instanceof Error ? err.message : String(err)}`);
121
+ }
122
+ try {
123
+ await upsertFtsCache(vaultPath);
124
+ }
125
+ catch (err) {
126
+ // eslint-disable-next-line no-console
127
+ console.error(`lyt sync: fts upsert failed for ${vaultName}: ${err instanceof Error ? err.message : String(err)}`);
128
+ }
129
+ // V-C-1 Phase B (L2) — stamp the index watermark after a post-pull cache
130
+ // reconcile. The FTS full-walk above re-reads the pulled markdown (so Tier-2
131
+ // search is fresh); lanes/arcs REFLECT the pulled committed SoT (we don't
132
+ // re-cluster on pull — that would churn the git tree, reindex-inbound.ts:14).
133
+ // Stamping "indexed as of now" keeps the L3 self-heal from redundantly
134
+ // re-clustering a vault we just reconciled.
135
+ //
136
+ // KNOWN TRADEOFF (release review, deferred to v1.V.x.1): if a peer
137
+ // pushed notes WITHOUT a fresh lanes.yon/arcs.yon (a pre-Phase-A pusher),
138
+ // those reflected tiers are stale — and this stamp then suppresses the L3 heal
139
+ // that would catch it, so Tier-0/1 (arc/lane) search stays degraded until a
140
+ // manual `lyt reindex`. Tier-2 FTS still surfaces the content (search is never
141
+ // EMPTY), so this is tier-degradation, not loss. Post-Phase-A pushers commit
142
+ // fresh SoT via index-on-write, so the stale case is a shrinking legacy edge;
143
+ // the structural fix (detect stale lanes.yon vs newest pulled figment +
144
+ // re-cluster those two tiers on pull) is booked for v1.V.x.1.
145
+ writeIndexWatermark(vaultPath);
146
+ }
147
+ function deriveFrictionHints(reports) {
148
+ const hints = [];
149
+ for (const r of reports) {
150
+ if (r.status === "conflict") {
151
+ hints.push({
152
+ vaultName: r.name,
153
+ vaultStatus: r.status,
154
+ category: "sync.conflict",
155
+ message: `Log this as friction with: lyt friction note --category=sync.conflict "${r.name}: ${r.message.replace(/"/g, '\\"').slice(0, 200)}"`,
156
+ });
157
+ }
158
+ else if (r.status === "error") {
159
+ hints.push({
160
+ vaultName: r.name,
161
+ vaultStatus: r.status,
162
+ category: "sync.failed",
163
+ message: `Log this as friction with: lyt friction note --category=sync.failed "${r.name}: ${r.message.replace(/"/g, '\\"').slice(0, 200)}"`,
164
+ });
165
+ }
166
+ }
167
+ return hints;
168
+ }
169
+ async function syncOneVault(vault, runGit, now, resolveMeshContext, messageOverride) {
170
+ const base = {
171
+ name: vault.name,
172
+ path: vault.path,
173
+ status: "clean",
174
+ message: "",
175
+ };
176
+ if (vault.status === "tombstoned") {
177
+ return { ...base, status: "skipped-tombstoned", message: "vault is tombstoned" };
178
+ }
179
+ if (vault.status === "disconnected") {
180
+ return { ...base, status: "skipped-disconnected", message: "vault is disconnected" };
181
+ }
182
+ if (vault.status === "missing") {
183
+ return { ...base, status: "skipped-missing", message: "vault path missing on disk" };
184
+ }
185
+ if (!existsSync(vault.path)) {
186
+ return { ...base, status: "skipped-missing", message: `path does not exist: ${vault.path}` };
187
+ }
188
+ const frozen = readFrozenLock(vault.path, now);
189
+ if (frozen.frozen && !frozen.expired) {
190
+ return {
191
+ ...base,
192
+ status: "skipped-frozen",
193
+ message: `frozen until ${frozen.frozenUntil ?? "?"} (${frozen.remaining ?? "?"})`,
194
+ };
195
+ }
196
+ const gitDir = await runGit(["rev-parse", "--git-dir"], { cwd: vault.path, allowFailure: true });
197
+ if (gitDir.code !== 0) {
198
+ return { ...base, status: "not-git-repo", message: "not a Git repo (no .git/)" };
199
+ }
200
+ // Fetch first so ahead/behind reflects truth (if upstream is configured).
201
+ const upstreamRes = await runGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], {
202
+ cwd: vault.path,
203
+ allowFailure: true,
204
+ });
205
+ const hasUpstreamFlag = upstreamRes.code === 0;
206
+ if (hasUpstreamFlag) {
207
+ const fetched = await runGit(["fetch", "--quiet"], { cwd: vault.path, allowFailure: true });
208
+ if (fetched.code !== 0) {
209
+ return {
210
+ ...base,
211
+ status: "error",
212
+ message: "git fetch failed",
213
+ errorOutput: fetched.stderr,
214
+ };
215
+ }
216
+ }
217
+ const status = await runGit(["status", "--porcelain"], { cwd: vault.path });
218
+ const statusLines = status.stdout
219
+ .split(/\r?\n/)
220
+ .map((l) => l.trimEnd())
221
+ .filter((l) => l.length > 0);
222
+ const dirtyCount = statusLines.length;
223
+ let ahead = 0;
224
+ let behind = 0;
225
+ if (hasUpstreamFlag) {
226
+ const ab = await runGit(["rev-list", "--left-right", "--count", "HEAD...@{u}"], {
227
+ cwd: vault.path,
228
+ allowFailure: true,
229
+ });
230
+ if (ab.code === 0) {
231
+ const parts = ab.stdout.trim().split(/\s+/);
232
+ ahead = Number(parts[0]) || 0;
233
+ behind = Number(parts[1]) || 0;
234
+ }
235
+ }
236
+ // v1.M.0 (P0-b) — single-reconcile guard. Each sync reconciles the .db
237
+ // caches AT MOST ONCE, via reconcileVaultCaches(). It fires after a local
238
+ // commit OR after a successful pull (the two ways on-disk SoT can change
239
+ // within one sync); the guard prevents the local-commit-then-pull path
240
+ // from reconciling twice.
241
+ let reconciled = false;
242
+ // Stage + commit dirty changes (explicit paths only, never `git add -A`).
243
+ let committed = false;
244
+ if (dirtyCount > 0) {
245
+ const paths = statusLines
246
+ .map((line) => parsePorcelainPath(line))
247
+ .filter((p) => p !== null);
248
+ if (paths.length > 0) {
249
+ // Use `--` separator to keep paths from being interpreted as flags/refs.
250
+ await runGit(["add", "--", ...paths], { cwd: vault.path });
251
+ // Brief C (F2) — metadata-driven commit message (subject + per-figment
252
+ // body, +new/~updated/-deleted from git status), unless the caller
253
+ // supplied an explicit `message` override (e.g. an agent's semantic
254
+ // summary). The deterministic path NEVER calls an LLM.
255
+ const commitMsg = messageOverride ?? buildSyncCommitMessage(vault, statusLines, now);
256
+ const commitRes = await runGit(["commit", "-m", commitMsg], {
257
+ cwd: vault.path,
258
+ allowFailure: true,
259
+ });
260
+ if (commitRes.code === 0) {
261
+ committed = true;
262
+ ahead += 1;
263
+ // v1.M.0 (P0-b) — reconcile right after the local commit lands, but
264
+ // ONLY when no pull will follow (behind === 0). When behind > 0 the
265
+ // pull below can bring in NEW remote SoT (notes another machine
266
+ // pushed); reconciling here would miss that, so we defer to the
267
+ // single post-pull reconcile which sees committed + pulled state at
268
+ // once. This keeps it exactly-once AND correct: the no-pull paths
269
+ // (no-remote, nothing-to-pull) previously skipped reconcile entirely
270
+ // and left search silently stale — that is the P0-b bug being fixed.
271
+ if (behind === 0) {
272
+ await reconcileVaultCaches(vault.path, vault.name);
273
+ reconciled = true;
274
+ }
275
+ }
276
+ }
277
+ }
278
+ if (!hasUpstreamFlag) {
279
+ // No remote to pull/push from. A local-only vault still needs its caches
280
+ // reconciled — if the commit above already reconciled, skip; otherwise
281
+ // (e.g. a commit that didn't change indexed SoT, or a defensive re-run)
282
+ // reconcile here before the early return so no-remote vaults are never
283
+ // left with stale search. Cheap when SoT is unchanged (upserts no-op).
284
+ if (committed && !reconciled) {
285
+ await reconcileVaultCaches(vault.path, vault.name);
286
+ reconciled = true;
287
+ }
288
+ return {
289
+ ...base,
290
+ status: "no-upstream",
291
+ message: committed
292
+ ? `committed ${dirtyCount} file(s); no upstream configured for push`
293
+ : "no upstream configured",
294
+ dirtyCount,
295
+ };
296
+ }
297
+ let meshContextResolved = false;
298
+ if (behind > 0) {
299
+ const pulled = await runGit(["pull", "--rebase", "--quiet"], {
300
+ cwd: vault.path,
301
+ allowFailure: true,
302
+ });
303
+ // v1.A.2 Lock 0.2 / v1.D.1b / v1.D.2b / v1.D.3a — after a successful
304
+ // pull, reconcile the .db caches (ledger → lanes → arcs → fts) so
305
+ // audit-export / provenance-trace / lanes / arcs / FTS search see
306
+ // records another machine appended. v1.M.0 (P0-b) folded the four
307
+ // formerly-inline upserts into reconcileVaultCaches() and guarded it
308
+ // with `reconciled`: if a local commit already reconciled this sync,
309
+ // skip the redundant re-walk here (the pulled state plus the committed
310
+ // state are both on disk, so one reconcile covers both).
311
+ if (pulled.code === 0 && !reconciled) {
312
+ await reconcileVaultCaches(vault.path, vault.name);
313
+ reconciled = true;
314
+ }
315
+ if (pulled.code !== 0) {
316
+ const conflictPaths = await readConflictPaths(runGit, vault.path);
317
+ const isMeshContextOnly = conflictPaths.length > 0 && conflictPaths.every((p) => p === MESH_CONTEXT_PATH);
318
+ if (resolveMeshContext && isMeshContextOnly) {
319
+ // Apply the documented recipe.
320
+ await runGit(["checkout", "--theirs", "--", MESH_CONTEXT_PATH], { cwd: vault.path });
321
+ try {
322
+ await regenContextFlow(vault.name);
323
+ }
324
+ catch {
325
+ // best-effort regen — proceed
326
+ }
327
+ await runGit(["add", "--", MESH_CONTEXT_PATH], { cwd: vault.path });
328
+ const continued = await runGit(["rebase", "--continue"], {
329
+ cwd: vault.path,
330
+ allowFailure: true,
331
+ });
332
+ if (continued.code !== 0) {
333
+ await runGit(["rebase", "--abort"], { cwd: vault.path, allowFailure: true });
334
+ return {
335
+ ...base,
336
+ status: "conflict",
337
+ message: "rebase conflict beyond .lyt/mesh-context.md; --resolve-mesh-context could not heal alone",
338
+ ahead,
339
+ behind,
340
+ dirtyCount,
341
+ errorOutput: continued.stderr,
342
+ };
343
+ }
344
+ meshContextResolved = true;
345
+ // v1.M.0 (P0-b) — the heal applied the pulled commits to disk
346
+ // (rebase --continue), so remote SoT is now present. Reconcile here
347
+ // since the earlier `pulled.code === 0` branch did not run (the pull
348
+ // initially conflicted). Guarded so we never double-reconcile.
349
+ if (!reconciled) {
350
+ await reconcileVaultCaches(vault.path, vault.name);
351
+ reconciled = true;
352
+ }
353
+ }
354
+ else {
355
+ await runGit(["rebase", "--abort"], { cwd: vault.path, allowFailure: true });
356
+ const recipe = isMeshContextOnly
357
+ ? `Conflict on .lyt/mesh-context.md only. Re-run with --resolve-mesh-context, or manually: 'git pull --rebase' → 'git checkout --theirs .lyt/mesh-context.md' → 'lyt vault regen-context ${vault.name}' → 'git add .lyt/mesh-context.md' → 'git rebase --continue'.`
358
+ : `Rebase conflict on: ${conflictPaths.join(", ") || "(unknown paths)"}. Resolve with normal git tooling.`;
359
+ return {
360
+ ...base,
361
+ status: "conflict",
362
+ message: recipe,
363
+ ahead,
364
+ behind,
365
+ dirtyCount,
366
+ errorOutput: pulled.stderr,
367
+ };
368
+ }
369
+ }
370
+ }
371
+ if (ahead > 0) {
372
+ const pushed = await runGit(["push"], { cwd: vault.path, allowFailure: true });
373
+ if (pushed.code !== 0) {
374
+ return {
375
+ ...base,
376
+ status: "error",
377
+ message: "git push failed",
378
+ ahead,
379
+ behind,
380
+ dirtyCount,
381
+ errorOutput: pushed.stderr,
382
+ };
383
+ }
384
+ }
385
+ let finalStatus = "clean";
386
+ let message = "up to date";
387
+ if (committed && behind > 0) {
388
+ finalStatus = "diverged-synced";
389
+ message = `rebased ${behind} commit(s) + pushed ${ahead} local commit(s)`;
390
+ }
391
+ else if (committed) {
392
+ finalStatus = "pushed";
393
+ message = `committed ${dirtyCount} file(s) + pushed`;
394
+ }
395
+ else if (ahead > 0 && behind > 0) {
396
+ finalStatus = "diverged-synced";
397
+ message = `rebased ${behind} + pushed ${ahead}`;
398
+ }
399
+ else if (ahead > 0) {
400
+ finalStatus = "pushed";
401
+ message = `pushed ${ahead} commit(s)`;
402
+ }
403
+ else if (behind > 0) {
404
+ finalStatus = "pulled";
405
+ message = `pulled ${behind} commit(s) from upstream`;
406
+ }
407
+ return {
408
+ ...base,
409
+ status: finalStatus,
410
+ message,
411
+ ahead,
412
+ behind,
413
+ dirtyCount,
414
+ meshContextResolved,
415
+ };
416
+ }
417
+ function parsePorcelainPath(line) {
418
+ // Porcelain v1 lines: "XY <path>" or "XY <orig> -> <new>" (renames).
419
+ if (line.length < 4)
420
+ return null;
421
+ const rest = line.slice(3);
422
+ const arrow = rest.indexOf(" -> ");
423
+ if (arrow >= 0) {
424
+ return rest.slice(arrow + 4);
425
+ }
426
+ return rest;
427
+ }
428
+ // Brief C (F2) — assemble the deterministic metadata-driven commit message for
429
+ // a vault's ongoing-changes commit. Classifies each porcelain status line into
430
+ // a figment change (+new/~updated/-deleted), resolves each figment's display
431
+ // title from its frontmatter (filename fallback; the path's basename for a
432
+ // deletion, which can't be read), folds `.lyt/**` churn into a single
433
+ // `+ .lyt config` line, and stamps the subject with the handle + `<mesh>/<vault>`
434
+ // + a minute-granularity timestamp. The pure heavy-lifting lives in lyt-vault
435
+ // sync-helpers (unit-tested); this is the fs glue. No LLM is ever called.
436
+ function buildSyncCommitMessage(vault, statusLines, now) {
437
+ const figments = [];
438
+ let configChanged = false;
439
+ for (const line of statusLines) {
440
+ const change = classifyPorcelainLine(line);
441
+ if (change === null)
442
+ continue;
443
+ if (isConfigPath(change.path)) {
444
+ configChanged = true;
445
+ continue;
446
+ }
447
+ if (!isFigmentPath(change.path))
448
+ continue; // non-figment, non-config: not enumerated
449
+ const title = change.changeType === "delete"
450
+ ? figmentBasename(change.path)
451
+ : (readVaultFigmentTitle(vault.path, change.path) ?? figmentBasename(change.path));
452
+ figments.push({ path: change.path, changeType: change.changeType, title });
453
+ }
454
+ let handle = "";
455
+ try {
456
+ handle = getHandleFromIdentity();
457
+ }
458
+ catch {
459
+ // No identity resolvable → the `(<handle>)` subject segment is omitted.
460
+ }
461
+ const shortTs = `${now.toISOString().slice(0, 16)}Z`;
462
+ return buildVaultCommitMessage(figments, {
463
+ handle,
464
+ vaultName: vault.name,
465
+ shortTs,
466
+ configChanged,
467
+ });
468
+ }
469
+ // Read a figment's frontmatter title from disk (non-deleted figments only).
470
+ // Non-fatal: an unreadable file returns null → the caller falls back to the
471
+ // filename.
472
+ function readVaultFigmentTitle(vaultPath, relPath) {
473
+ try {
474
+ return readFigmentTitle(readFileSync(join(vaultPath, relPath), "utf8"));
475
+ }
476
+ catch {
477
+ return null;
478
+ }
479
+ }
480
+ // Basename without the `.md` extension — the filename fallback / deletion title.
481
+ function figmentBasename(relPath) {
482
+ const norm = relPath.replace(/\\/g, "/");
483
+ const base = norm.slice(norm.lastIndexOf("/") + 1);
484
+ return base.replace(/\.md$/i, "");
485
+ }
486
+ async function readConflictPaths(runGit, cwd) {
487
+ const r = await runGit(["diff", "--name-only", "--diff-filter=U"], { cwd, allowFailure: true });
488
+ if (r.code !== 0)
489
+ return [];
490
+ return r.stdout
491
+ .split(/\r?\n/)
492
+ .map((l) => l.trim())
493
+ .filter((l) => l.length > 0);
494
+ }
495
+ // `git status --porcelain` field interpretation used downstream by `sync --check`.
496
+ export function classifyCheckStatus(args) {
497
+ if (args.frozen)
498
+ return "frozen";
499
+ if (!args.hasUpstream)
500
+ return "no-upstream";
501
+ if (args.dirtyCount > 0)
502
+ return "dirty";
503
+ if (args.ahead > 0 && args.behind > 0)
504
+ return "diverged";
505
+ if (args.ahead > 0)
506
+ return `ahead-${args.ahead}`;
507
+ if (args.behind > 0)
508
+ return `behind-${args.behind}`;
509
+ return "clean";
510
+ }
511
+ // Re-export for `sync.ts:syncOneVault` tests that want to seed paths.
512
+ export { parsePorcelainPath as _parsePorcelainPath };
513
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/flows/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,UAAU,EACV,wBAAwB,EACxB,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,MAAM,IAAI,aAAa,EACvB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,GAKpB,MAAM,qBAAqB,CAAC;AAuE7B,MAAM,iBAAiB,GAAG,sBAAsB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAqB,EAAE;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACnC,MAAM,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;IAChC,IAAI,UAAsB,CAAC;IAC3B,8DAA8D;IAC9D,mEAAmE;IACnE,iEAAiE;IACjE,mEAAmE;IACnE,iEAAiE;IACjE,+DAA+D;IAC/D,8DAA8D;IAC9D,mDAAmD;IACnD,IAAI,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,EAAE,CAAC,CAAC;QACjC,UAAU;YACR,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;gBAC3C,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACtD,CAAC,CAAC,GAAG,CAAC;QACV,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,CAAC,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;YACvD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,CAAC,EACD,MAAM,EACN,GAAG,EACH,IAAI,CAAC,kBAAkB,KAAK,IAAI,EAChC,IAAI,CAAC,OAAO,CACb,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,6DAA6D;QAC7D,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,oEAAoE;QACpE,wEAAwE;QACxE,qEAAqE;QACrE,kEAAkE;QAClE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YAC9E,IAAI,CAAC;gBACH,IAAI,MAAM,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC;oBAC3B,MAAM,CAAC,OAAO;wBACZ,GAAG,MAAM,CAAC,OAAO,6DAA6D;4BAC9E,2FAA2F,CAAC,CAAC,IAAI,mBAAmB,CAAC;gBACzH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;YACtE,CAAC;QACH,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;IACjF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,uEAAuE;AACvE,qEAAqE;AACrE,mEAAmE;AACnE,wEAAwE;AACxE,wDAAwD;AACxD,yEAAyE;AACzE,yEAAyE;AACzE,kEAAkE;AAClE,0EAA0E;AAC1E,sEAAsE;AACtE,2EAA2E;AAC3E,qEAAqE;AACrE,2EAA2E;AAC3E,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,KAAK,UAAU,oBAAoB,CAAC,SAAiB,EAAE,SAAiB;IACtE,IAAI,CAAC;QACH,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sCAAsC;QACtC,OAAO,CAAC,KAAK,CACX,sCAAsC,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACvG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sCAAsC;QACtC,OAAO,CAAC,KAAK,CACX,qCAAqC,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACtG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sCAAsC;QACtC,OAAO,CAAC,KAAK,CACX,oCAAoC,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACrG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sCAAsC;QACtC,OAAO,CAAC,KAAK,CACX,mCAAmC,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACpG,CAAC;IACJ,CAAC;IACD,yEAAyE;IACzE,6EAA6E;IAC7E,0EAA0E;IAC1E,8EAA8E;IAC9E,uEAAuE;IACvE,4CAA4C;IAC5C,EAAE;IACF,mEAAmE;IACnE,0EAA0E;IAC1E,+EAA+E;IAC/E,4EAA4E;IAC5E,+EAA+E;IAC/E,6EAA6E;IAC7E,8EAA8E;IAC9E,wEAAwE;IACxE,8DAA8D;IAC9D,mBAAmB,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAmC;IAC9D,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,CAAC,CAAC,IAAI;gBACjB,WAAW,EAAE,CAAC,CAAC,MAAM;gBACrB,QAAQ,EAAE,eAAe;gBACzB,OAAO,EAAE,0EAA0E,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG;aAC9I,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,CAAC,CAAC,IAAI;gBACjB,WAAW,EAAE,CAAC,CAAC,MAAM;gBACrB,QAAQ,EAAE,aAAa;gBACvB,OAAO,EAAE,wEAAwE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG;aAC5I,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,KAAe,EACf,MAAiB,EACjB,GAAS,EACT,kBAA2B,EAC3B,eAAwB;IAExB,MAAM,IAAI,GAAoB;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,EAAE;KACZ,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACpC,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACvF,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC;IACvF,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,wBAAwB,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;IAC/F,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,gBAAgB;YACxB,OAAO,EAAE,gBAAgB,MAAM,CAAC,WAAW,IAAI,GAAG,KAAK,MAAM,CAAC,SAAS,IAAI,GAAG,GAAG;SAClF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IACjG,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;IACnF,CAAC;IAED,0EAA0E;IAC1E,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,CAAC,EAAE;QAC9F,GAAG,EAAE,KAAK,CAAC,IAAI;QACf,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,WAAW,CAAC,IAAI,KAAK,CAAC,CAAC;IAC/C,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5F,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,kBAAkB;gBAC3B,WAAW,EAAE,OAAO,CAAC,MAAM;aAC5B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM;SAC9B,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SACvB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC;IAEtC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE;YAC9E,GAAG,EAAE,KAAK,CAAC,IAAI;YACf,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5C,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,0EAA0E;IAC1E,yEAAyE;IACzE,uEAAuE;IACvE,0BAA0B;IAC1B,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,0EAA0E;IAC1E,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,WAAW;aACtB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;aACvC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,yEAAyE;YACzE,MAAM,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,uEAAuE;YACvE,mEAAmE;YACnE,oEAAoE;YACpE,uDAAuD;YACvD,MAAM,SAAS,GAAG,eAAe,IAAI,sBAAsB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;YACrF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE;gBAC1D,GAAG,EAAE,KAAK,CAAC,IAAI;gBACf,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS,GAAG,IAAI,CAAC;gBACjB,KAAK,IAAI,CAAC,CAAC;gBACX,oEAAoE;gBACpE,oEAAoE;gBACpE,gEAAgE;gBAChE,gEAAgE;gBAChE,oEAAoE;gBACpE,kEAAkE;gBAClE,qEAAqE;gBACrE,qEAAqE;gBACrE,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;oBACjB,MAAM,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBACnD,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,uEAAuE;QACvE,uEAAuE;QACvE,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7B,MAAM,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACnD,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE,SAAS;gBAChB,CAAC,CAAC,aAAa,UAAU,2CAA2C;gBACpE,CAAC,CAAC,wBAAwB;YAC5B,UAAU;SACX,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAChC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE;YAC3D,GAAG,EAAE,KAAK,CAAC,IAAI;YACf,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,qEAAqE;QACrE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,qEAAqE;QACrE,qEAAqE;QACrE,uEAAuE;QACvE,yDAAyD;QACzD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACnD,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAClE,MAAM,iBAAiB,GACrB,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC;YAClF,IAAI,kBAAkB,IAAI,iBAAiB,EAAE,CAAC;gBAC5C,+BAA+B;gBAC/B,MAAM,MAAM,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrF,IAAI,CAAC;oBACH,MAAM,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACP,8BAA8B;gBAChC,CAAC;gBACD,MAAM,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACpE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE;oBACvD,GAAG,EAAE,KAAK,CAAC,IAAI;oBACf,YAAY,EAAE,IAAI;iBACnB,CAAC,CAAC;gBACH,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACzB,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC7E,OAAO;wBACL,GAAG,IAAI;wBACP,MAAM,EAAE,UAAU;wBAClB,OAAO,EACL,0FAA0F;wBAC5F,KAAK;wBACL,MAAM;wBACN,UAAU;wBACV,WAAW,EAAE,SAAS,CAAC,MAAM;qBAC9B,CAAC;gBACJ,CAAC;gBACD,mBAAmB,GAAG,IAAI,CAAC;gBAC3B,8DAA8D;gBAC9D,oEAAoE;gBACpE,qEAAqE;gBACrE,+DAA+D;gBAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBACnD,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7E,MAAM,MAAM,GAAG,iBAAiB;oBAC9B,CAAC,CAAC,yLAAyL,KAAK,CAAC,IAAI,+DAA+D;oBACpQ,CAAC,CAAC,uBAAuB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,iBAAiB,oCAAoC,CAAC;gBAC7G,OAAO;oBACL,GAAG,IAAI;oBACP,MAAM,EAAE,UAAU;oBAClB,OAAO,EAAE,MAAM;oBACf,KAAK;oBACL,MAAM;oBACN,UAAU;oBACV,WAAW,EAAE,MAAM,CAAC,MAAM;iBAC3B,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,iBAAiB;gBAC1B,KAAK;gBACL,MAAM;gBACN,UAAU;gBACV,WAAW,EAAE,MAAM,CAAC,MAAM;aAC3B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,WAAW,GAAoB,OAAO,CAAC;IAC3C,IAAI,OAAO,GAAG,YAAY,CAAC;IAC3B,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,WAAW,GAAG,iBAAiB,CAAC;QAChC,OAAO,GAAG,WAAW,MAAM,uBAAuB,KAAK,kBAAkB,CAAC;IAC5E,CAAC;SAAM,IAAI,SAAS,EAAE,CAAC;QACrB,WAAW,GAAG,QAAQ,CAAC;QACvB,OAAO,GAAG,aAAa,UAAU,mBAAmB,CAAC;IACvD,CAAC;SAAM,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,WAAW,GAAG,iBAAiB,CAAC;QAChC,OAAO,GAAG,WAAW,MAAM,aAAa,KAAK,EAAE,CAAC;IAClD,CAAC;SAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACrB,WAAW,GAAG,QAAQ,CAAC;QACvB,OAAO,GAAG,UAAU,KAAK,YAAY,CAAC;IACxC,CAAC;SAAM,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,WAAW,GAAG,QAAQ,CAAC;QACvB,OAAO,GAAG,UAAU,MAAM,0BAA0B,CAAC;IACvD,CAAC;IACD,OAAO;QACL,GAAG,IAAI;QACP,MAAM,EAAE,WAAW;QACnB,OAAO;QACP,KAAK;QACL,MAAM;QACN,UAAU;QACV,mBAAmB;KACpB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY;IACtC,qEAAqE;IACrE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,+EAA+E;AAC/E,6EAA6E;AAC7E,2EAA2E;AAC3E,sEAAsE;AACtE,kFAAkF;AAClF,8EAA8E;AAC9E,0EAA0E;AAC1E,SAAS,sBAAsB,CAC7B,KAAe,EACf,WAA8B,EAC9B,GAAS;IAET,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9B,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,aAAa,GAAG,IAAI,CAAC;YACrB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,0CAA0C;QACrF,MAAM,KAAK,GACT,MAAM,CAAC,UAAU,KAAK,QAAQ;YAC5B,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC;YAC9B,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACvF,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;IAC1E,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC;IACrD,OAAO,uBAAuB,CAAC,QAAQ,EAAE;QACvC,MAAM;QACN,SAAS,EAAE,KAAK,CAAC,IAAI;QACrB,OAAO;QACP,aAAa;KACd,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,4EAA4E;AAC5E,YAAY;AACZ,SAAS,qBAAqB,CAAC,SAAiB,EAAE,OAAe;IAC/D,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,MAAiB,EAAE,GAAW;IAC7D,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAChG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,CAAC,MAAM;SACZ,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,mBAAmB,CAAC,IAMnC;IACC,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,OAAO,aAAa,CAAC;IAC5C,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IACzD,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;QAAE,OAAO,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;IACjD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;IACpD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sEAAsE;AACtE,OAAO,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type VaultRow } from "@younndai/lyt-vault";
2
+ import type { Client } from "@libsql/client";
3
+ export type ValidateIssueStatus = "dangling" | "tombstoned-target";
4
+ export type ValidateEdgeKind = "parent_vault";
5
+ export interface ValidateFinding {
6
+ sourceVaultRid: string;
7
+ sourceVaultName: string;
8
+ declaredEdge: ValidateEdgeKind;
9
+ targetVaultRid: string;
10
+ status: ValidateIssueStatus;
11
+ }
12
+ export interface ValidateOutcome {
13
+ findings: ValidateFinding[];
14
+ totalVaults: number;
15
+ totalEdges: number;
16
+ }
17
+ export interface ValidateOptions {
18
+ db?: Client;
19
+ }
20
+ export declare function validateFlow(opts?: ValidateOptions): Promise<ValidateOutcome>;
21
+ export type { VaultRow };
22
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/flows/validate.ts"],"names":[],"mappings":"AAgBA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAO7C,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,mBAAmB,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IAIpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,YAAY,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4CvF;AAID,YAAY,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,62 @@
1
+ /*
2
+ * Copyright 2026 MARLINK TRADING SRL (YounndAI)
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { closeRegistry, listVaults, openRegistry, ridsEqual, } from "@younndai/lyt-vault";
17
+ export async function validateFlow(opts = {}) {
18
+ const db = opts.db ?? (await openRegistry());
19
+ const ownDb = opts.db === undefined;
20
+ try {
21
+ const vaults = await listVaults(db);
22
+ const findings = [];
23
+ let edgeCount = 0;
24
+ for (const v of vaults) {
25
+ if (v.parentVault === null)
26
+ continue;
27
+ edgeCount += 1;
28
+ const target = vaults.find((p) => ridsEqual(p.rid, v.parentVault));
29
+ const parentHex = v.parentVaultHex ?? "(unknown)";
30
+ if (!target) {
31
+ findings.push({
32
+ sourceVaultRid: v.ridHex,
33
+ sourceVaultName: v.name,
34
+ declaredEdge: "parent_vault",
35
+ targetVaultRid: parentHex,
36
+ status: "dangling",
37
+ });
38
+ continue;
39
+ }
40
+ if (target.status === "tombstoned") {
41
+ findings.push({
42
+ sourceVaultRid: v.ridHex,
43
+ sourceVaultName: v.name,
44
+ declaredEdge: "parent_vault",
45
+ targetVaultRid: target.ridHex,
46
+ status: "tombstoned-target",
47
+ });
48
+ }
49
+ }
50
+ return {
51
+ findings,
52
+ totalVaults: vaults.length,
53
+ totalEdges: edgeCount,
54
+ };
55
+ }
56
+ finally {
57
+ if (ownDb) {
58
+ await closeRegistry(db);
59
+ }
60
+ }
61
+ }
62
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/flows/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,aAAa,EACb,UAAU,EACV,YAAY,EACZ,SAAS,GAEV,MAAM,qBAAqB,CAAC;AAkC7B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAwB,EAAE;IAC3D,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI;gBAAE,SAAS;YACrC,SAAS,IAAI,CAAC,CAAC;YACf,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;YACnE,MAAM,SAAS,GAAG,CAAC,CAAC,cAAc,IAAI,WAAW,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,QAAQ,CAAC,IAAI,CAAC;oBACZ,cAAc,EAAE,CAAC,CAAC,MAAM;oBACxB,eAAe,EAAE,CAAC,CAAC,IAAI;oBACvB,YAAY,EAAE,cAAc;oBAC5B,cAAc,EAAE,SAAS;oBACzB,MAAM,EAAE,UAAU;iBACnB,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC;oBACZ,cAAc,EAAE,CAAC,CAAC,MAAM;oBACxB,eAAe,EAAE,CAAC,CAAC,IAAI;oBACvB,YAAY,EAAE,cAAc;oBAC5B,cAAc,EAAE,MAAM,CAAC,MAAM;oBAC7B,MAAM,EAAE,mBAAmB;iBAC5B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO;YACL,QAAQ;YACR,WAAW,EAAE,MAAM,CAAC,MAAM;YAC1B,UAAU,EAAE,SAAS;SACtB,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;AACH,CAAC"}