@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.
- package/LICENSE +200 -0
- package/NOTICE +23 -0
- package/README.md +135 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +34 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/clone-all.d.ts +3 -0
- package/dist/commands/clone-all.d.ts.map +1 -0
- package/dist/commands/clone-all.js +66 -0
- package/dist/commands/clone-all.js.map +1 -0
- package/dist/commands/mesh-init.d.ts +3 -0
- package/dist/commands/mesh-init.d.ts.map +1 -0
- package/dist/commands/mesh-init.js +70 -0
- package/dist/commands/mesh-init.js.map +1 -0
- package/dist/commands/pod-status.d.ts +3 -0
- package/dist/commands/pod-status.d.ts.map +1 -0
- package/dist/commands/pod-status.js +67 -0
- package/dist/commands/pod-status.js.map +1 -0
- package/dist/commands/source.d.ts +3 -0
- package/dist/commands/source.d.ts.map +1 -0
- package/dist/commands/source.js +83 -0
- package/dist/commands/source.js.map +1 -0
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +121 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +3 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +234 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +66 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/discovery/github.d.ts +19 -0
- package/dist/discovery/github.d.ts.map +1 -0
- package/dist/discovery/github.js +90 -0
- package/dist/discovery/github.js.map +1 -0
- package/dist/discovery/walk.d.ts +28 -0
- package/dist/discovery/walk.d.ts.map +1 -0
- package/dist/discovery/walk.js +78 -0
- package/dist/discovery/walk.js.map +1 -0
- package/dist/flows/clone-all.d.ts +53 -0
- package/dist/flows/clone-all.d.ts.map +1 -0
- package/dist/flows/clone-all.js +123 -0
- package/dist/flows/clone-all.js.map +1 -0
- package/dist/flows/mesh-init-validate.d.ts +22 -0
- package/dist/flows/mesh-init-validate.d.ts.map +1 -0
- package/dist/flows/mesh-init-validate.js +195 -0
- package/dist/flows/mesh-init-validate.js.map +1 -0
- package/dist/flows/mesh-init.d.ts +46 -0
- package/dist/flows/mesh-init.d.ts.map +1 -0
- package/dist/flows/mesh-init.js +302 -0
- package/dist/flows/mesh-init.js.map +1 -0
- package/dist/flows/pod-status.d.ts +37 -0
- package/dist/flows/pod-status.d.ts.map +1 -0
- package/dist/flows/pod-status.js +269 -0
- package/dist/flows/pod-status.js.map +1 -0
- package/dist/flows/status.d.ts +16 -0
- package/dist/flows/status.d.ts.map +1 -0
- package/dist/flows/status.js +76 -0
- package/dist/flows/status.js.map +1 -0
- package/dist/flows/sync-check.d.ts +38 -0
- package/dist/flows/sync-check.d.ts.map +1 -0
- package/dist/flows/sync-check.js +180 -0
- package/dist/flows/sync-check.js.map +1 -0
- package/dist/flows/sync-watch.d.ts +24 -0
- package/dist/flows/sync-watch.d.ts.map +1 -0
- package/dist/flows/sync-watch.js +217 -0
- package/dist/flows/sync-watch.js.map +1 -0
- package/dist/flows/sync.d.ts +45 -0
- package/dist/flows/sync.d.ts.map +1 -0
- package/dist/flows/sync.js +513 -0
- package/dist/flows/sync.js.map +1 -0
- package/dist/flows/validate.d.ts +22 -0
- package/dist/flows/validate.d.ts.map +1 -0
- package/dist/flows/validate.js +62 -0
- package/dist/flows/validate.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/mesh-command.d.ts +3 -0
- package/dist/mesh-command.d.ts.map +1 -0
- package/dist/mesh-command.js +31 -0
- package/dist/mesh-command.js.map +1 -0
- package/dist/source/repo.d.ts +14 -0
- package/dist/source/repo.d.ts.map +1 -0
- package/dist/source/repo.js +71 -0
- package/dist/source/repo.js.map +1 -0
- package/dist/source/types.d.ts +22 -0
- package/dist/source/types.d.ts.map +1 -0
- package/dist/source/types.js +49 -0
- package/dist/source/types.js.map +1 -0
- 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"}
|