@younndai/lyt 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 +117 -0
- package/dist/automator-bodies/arc-builder.d.ts +13 -0
- package/dist/automator-bodies/arc-builder.d.ts.map +1 -0
- package/dist/automator-bodies/arc-builder.js +34 -0
- package/dist/automator-bodies/arc-builder.js.map +1 -0
- package/dist/automator-bodies/index.d.ts +20 -0
- package/dist/automator-bodies/index.d.ts.map +1 -0
- package/dist/automator-bodies/index.js +32 -0
- package/dist/automator-bodies/index.js.map +1 -0
- package/dist/automator-bodies/lane-builder.d.ts +12 -0
- package/dist/automator-bodies/lane-builder.d.ts.map +1 -0
- package/dist/automator-bodies/lane-builder.js +34 -0
- package/dist/automator-bodies/lane-builder.js.map +1 -0
- package/dist/automator-bodies/metadata-filler.d.ts +34 -0
- package/dist/automator-bodies/metadata-filler.d.ts.map +1 -0
- package/dist/automator-bodies/metadata-filler.js +211 -0
- package/dist/automator-bodies/metadata-filler.js.map +1 -0
- package/dist/automator-run.d.ts +27 -0
- package/dist/automator-run.d.ts.map +1 -0
- package/dist/automator-run.js +137 -0
- package/dist/automator-run.js.map +1 -0
- package/dist/bench/graded-corpus.d.ts +5 -0
- package/dist/bench/graded-corpus.d.ts.map +1 -0
- package/dist/bench/graded-corpus.js +121 -0
- package/dist/bench/graded-corpus.js.map +1 -0
- package/dist/bench/invariant-corpus.d.ts +18 -0
- package/dist/bench/invariant-corpus.d.ts.map +1 -0
- package/dist/bench/invariant-corpus.js +181 -0
- package/dist/bench/invariant-corpus.js.map +1 -0
- package/dist/bench/ir-metrics.d.ts +33 -0
- package/dist/bench/ir-metrics.d.ts.map +1 -0
- package/dist/bench/ir-metrics.js +79 -0
- package/dist/bench/ir-metrics.js.map +1 -0
- package/dist/bench/latency-bench.d.ts +15 -0
- package/dist/bench/latency-bench.d.ts.map +1 -0
- package/dist/bench/latency-bench.js +68 -0
- package/dist/bench/latency-bench.js.map +1 -0
- package/dist/bench/latency-corpus.d.ts +4 -0
- package/dist/bench/latency-corpus.d.ts.map +1 -0
- package/dist/bench/latency-corpus.js +109 -0
- package/dist/bench/latency-corpus.js.map +1 -0
- package/dist/bench/pod-harness.d.ts +16 -0
- package/dist/bench/pod-harness.d.ts.map +1 -0
- package/dist/bench/pod-harness.js +127 -0
- package/dist/bench/pod-harness.js.map +1 -0
- package/dist/bench/run-bench.d.ts +20 -0
- package/dist/bench/run-bench.d.ts.map +1 -0
- package/dist/bench/run-bench.js +86 -0
- package/dist/bench/run-bench.js.map +1 -0
- package/dist/cli-automator-run.d.ts +7 -0
- package/dist/cli-automator-run.d.ts.map +1 -0
- package/dist/cli-automator-run.js +80 -0
- package/dist/cli-automator-run.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +161 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/bench.d.ts +3 -0
- package/dist/commands/bench.d.ts.map +1 -0
- package/dist/commands/bench.js +92 -0
- package/dist/commands/bench.js.map +1 -0
- package/dist/commands/capture.d.ts +4 -0
- package/dist/commands/capture.d.ts.map +1 -0
- package/dist/commands/capture.js +251 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +741 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/primer.d.ts +3 -0
- package/dist/commands/primer.d.ts.map +1 -0
- package/dist/commands/primer.js +199 -0
- package/dist/commands/primer.js.map +1 -0
- package/dist/commands/reindex.d.ts +3 -0
- package/dist/commands/reindex.d.ts.map +1 -0
- package/dist/commands/reindex.js +105 -0
- package/dist/commands/reindex.js.map +1 -0
- package/dist/commands/search.d.ts +3 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +224 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/flows/heal.d.ts +29 -0
- package/dist/flows/heal.d.ts.map +1 -0
- package/dist/flows/heal.js +146 -0
- package/dist/flows/heal.js.map +1 -0
- package/dist/flows/init-bootstrap.d.ts +93 -0
- package/dist/flows/init-bootstrap.d.ts.map +1 -0
- package/dist/flows/init-bootstrap.js +561 -0
- package/dist/flows/init-bootstrap.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
// Lane V Workstream 2 — `lyt bench` temp-pod harness.
|
|
17
|
+
//
|
|
18
|
+
// Stands up a THROWAWAY pod under os.tmpdir (never the user's ~/lyt), seeds
|
|
19
|
+
// vaults + figments offline (federation self-heal disabled AND a synthetic
|
|
20
|
+
// identity pinned → no gh, no network, no interactive prompts), reindexes all
|
|
21
|
+
// content tiers, and runs the cascade. Productized from
|
|
22
|
+
// tools/lane-v/quality-probe.mjs (which only PROBED an already-built pod); this
|
|
23
|
+
// also BUILDS the pod, so the bench ships self-contained.
|
|
24
|
+
//
|
|
25
|
+
// Pod safety: LYT_HOME is repointed to a fresh mkdtemp dir for the harness'
|
|
26
|
+
// lifetime and restored on teardown. The dir is created by mkdtemp under
|
|
27
|
+
// os.tmpdir — it can never be ~/lyt — but we assert it (and reject anything
|
|
28
|
+
// under ~/lyt) anyway (defence-in-depth, mirroring quality-probe.mjs's guard).
|
|
29
|
+
import { mkdirSync, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
30
|
+
import { homedir, tmpdir } from "node:os";
|
|
31
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
32
|
+
import { initVaultFlow, rebuildVaultFlow, searchCascadeFlow, } from "@younndai/lyt-vault";
|
|
33
|
+
// Fixed clock threaded into reindex so temporal caches (keyword decay,
|
|
34
|
+
// recent-activity) are deterministic — the bench's metrics must not drift with
|
|
35
|
+
// wall-clock time.
|
|
36
|
+
export const BENCH_NOW_ISO = "2026-06-01T00:00:00.000Z";
|
|
37
|
+
const REAL_POD = resolve(homedir(), "lyt");
|
|
38
|
+
const BENCH_PREFIX = "lyt-bench-";
|
|
39
|
+
// Sweep leaked bench pods older than this (Windows libSQL handle lag can defeat
|
|
40
|
+
// the teardown rmSync). Age-gated so a concurrent run's live pod is never hit.
|
|
41
|
+
const STALE_POD_MS = 10 * 60_000;
|
|
42
|
+
// Best-effort reaper for bench pods a prior run failed to delete. Everything it
|
|
43
|
+
// touches is a mkdtemp dir named `lyt-bench-*` under os.tmpdir — junction-free,
|
|
44
|
+
// L0-safe. Age-gated + fully swallowed; never fails the bench.
|
|
45
|
+
function sweepStaleBenchPods(nowMs) {
|
|
46
|
+
let entries;
|
|
47
|
+
try {
|
|
48
|
+
entries = readdirSync(tmpdir());
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
for (const name of entries) {
|
|
54
|
+
if (!name.startsWith(BENCH_PREFIX))
|
|
55
|
+
continue;
|
|
56
|
+
const full = join(tmpdir(), name);
|
|
57
|
+
try {
|
|
58
|
+
if (nowMs - statSync(full).mtimeMs < STALE_POD_MS)
|
|
59
|
+
continue;
|
|
60
|
+
rmSync(full, { recursive: true, force: true, maxRetries: 3, retryDelay: 200 });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// leave it; never fail on cleanup
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function setupBenchPod() {
|
|
68
|
+
sweepStaleBenchPods(Date.now());
|
|
69
|
+
const home = mkdtempSync(join(tmpdir(), BENCH_PREFIX));
|
|
70
|
+
const resolvedHome = resolve(home);
|
|
71
|
+
if (resolvedHome === REAL_POD || resolvedHome.startsWith(REAL_POD + sep)) {
|
|
72
|
+
throw new Error(`bench: refusing to run against the real pod (${REAL_POD}).`);
|
|
73
|
+
}
|
|
74
|
+
const prevLytHome = process.env["LYT_HOME"];
|
|
75
|
+
const prevIdentity = process.env["LYT_IDENTITY_OVERRIDE"];
|
|
76
|
+
process.env["LYT_HOME"] = home;
|
|
77
|
+
// Pin a synthetic identity so vault scaffolding (initVault -> getIdentity)
|
|
78
|
+
// never spawns `gh auth status` / `gh api /user`. WITHOUT this the bench
|
|
79
|
+
// throws on any machine where gh is missing/unauthed (release review C1) — this
|
|
80
|
+
// is what makes it truly offline + safe to run anywhere. Mirrors how every
|
|
81
|
+
// init-touching test pins LYT_IDENTITY_OVERRIDE.
|
|
82
|
+
process.env["LYT_IDENTITY_OVERRIDE"] = "github:lyt-bench";
|
|
83
|
+
return {
|
|
84
|
+
home,
|
|
85
|
+
async seedVault(name, notes) {
|
|
86
|
+
const init = await initVaultFlow({
|
|
87
|
+
name,
|
|
88
|
+
gitInit: false,
|
|
89
|
+
commitInitial: false,
|
|
90
|
+
selfHeal: { federation: { enabled: false } },
|
|
91
|
+
});
|
|
92
|
+
for (const note of notes) {
|
|
93
|
+
const full = join(init.vaultPath, note.rel);
|
|
94
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
95
|
+
writeFileSync(full, `---\n${note.frontmatter}\n---\n${note.body}\n`, "utf8");
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
async reindex(name) {
|
|
99
|
+
await rebuildVaultFlow({ vault: name, nowIso: BENCH_NOW_ISO });
|
|
100
|
+
},
|
|
101
|
+
async search(args) {
|
|
102
|
+
return searchCascadeFlow(args);
|
|
103
|
+
},
|
|
104
|
+
teardown() {
|
|
105
|
+
// Restore env FIRST, unconditionally — a cleanup failure must never leave
|
|
106
|
+
// LYT_HOME / LYT_IDENTITY_OVERRIDE dangling.
|
|
107
|
+
if (prevLytHome === undefined)
|
|
108
|
+
delete process.env["LYT_HOME"];
|
|
109
|
+
else
|
|
110
|
+
process.env["LYT_HOME"] = prevLytHome;
|
|
111
|
+
if (prevIdentity === undefined)
|
|
112
|
+
delete process.env["LYT_IDENTITY_OVERRIDE"];
|
|
113
|
+
else
|
|
114
|
+
process.env["LYT_IDENTITY_OVERRIDE"] = prevIdentity;
|
|
115
|
+
// `home` is a fresh mkdtemp dir under os.tmpdir — no junctions, L0-safe.
|
|
116
|
+
// Best-effort: Windows libSQL handle lag can still defeat this; whatever is
|
|
117
|
+
// left is reaped by the next run's sweepStaleBenchPods.
|
|
118
|
+
try {
|
|
119
|
+
rmSync(home, { recursive: true, force: true, maxRetries: 5, retryDelay: 300 });
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// leave for the next run's sweep
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=pod-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pod-harness.js","sourceRoot":"","sources":["../../src/bench/pod-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type InvariantResult } from "./invariant-corpus.js";
|
|
2
|
+
import { type GradedAggregate, type GradedQueryScore } from "./ir-metrics.js";
|
|
3
|
+
export interface GradedReport {
|
|
4
|
+
queries: GradedQueryScore[];
|
|
5
|
+
aggregate: GradedAggregate;
|
|
6
|
+
}
|
|
7
|
+
export interface BenchReport {
|
|
8
|
+
invariants: InvariantResult[];
|
|
9
|
+
graded: GradedReport;
|
|
10
|
+
invariantsPassed: number;
|
|
11
|
+
invariantsTotal: number;
|
|
12
|
+
quick: boolean;
|
|
13
|
+
ok: boolean;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
}
|
|
16
|
+
export interface RunBenchOptions {
|
|
17
|
+
quick?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function runBench(opts?: RunBenchOptions): Promise<BenchReport>;
|
|
20
|
+
//# sourceMappingURL=run-bench.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-bench.d.ts","sourceRoot":"","sources":["../../src/bench/run-bench.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9F,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IAExB,KAAK,EAAE,OAAO,CAAC;IASf,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAmCD,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB/E"}
|
|
@@ -0,0 +1,86 @@
|
|
|
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
|
+
// Lane V Workstream 2 — `lyt bench` orchestrator.
|
|
17
|
+
//
|
|
18
|
+
// Runs two phases, each in its OWN isolated temp pod (so the invariant corpus
|
|
19
|
+
// and the graded corpus never cross-contaminate each other's queries):
|
|
20
|
+
// D-core — pass/fail retrieval invariants (the regression canary)
|
|
21
|
+
// E-lite — a planted-relevance graded score (nDCG/recall/MRR/P@1 + cleanliness)
|
|
22
|
+
// Metrics-only output — no user content, by construction (synthetic corpora).
|
|
23
|
+
// `--quick` runs only the D-core invariants (the every-CI fast path).
|
|
24
|
+
import { gradedCorpus, GRADED_QUERIES } from "./graded-corpus.js";
|
|
25
|
+
import { INVARIANT_CORPUS, runInvariants } from "./invariant-corpus.js";
|
|
26
|
+
import { aggregateGraded, scoreGradedQuery, } from "./ir-metrics.js";
|
|
27
|
+
import { setupBenchPod } from "./pod-harness.js";
|
|
28
|
+
const EMPTY_GRADED = {
|
|
29
|
+
queries: [],
|
|
30
|
+
aggregate: { queries: 0, ndcg: 0, recall: 0, mrr: 0, pAt1: 0, cleanliness: 0 },
|
|
31
|
+
};
|
|
32
|
+
async function runInvariantPhase() {
|
|
33
|
+
const pod = setupBenchPod();
|
|
34
|
+
try {
|
|
35
|
+
for (const seed of INVARIANT_CORPUS)
|
|
36
|
+
await pod.seedVault(seed.vault, seed.notes);
|
|
37
|
+
for (const seed of INVARIANT_CORPUS)
|
|
38
|
+
await pod.reindex(seed.vault);
|
|
39
|
+
return await runInvariants(pod);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
pod.teardown();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function runGradedPhase() {
|
|
46
|
+
const pod = setupBenchPod();
|
|
47
|
+
try {
|
|
48
|
+
const seeds = gradedCorpus();
|
|
49
|
+
for (const seed of seeds)
|
|
50
|
+
await pod.seedVault(seed.vault, seed.notes);
|
|
51
|
+
for (const seed of seeds)
|
|
52
|
+
await pod.reindex(seed.vault);
|
|
53
|
+
const queries = [];
|
|
54
|
+
for (const q of GRADED_QUERIES) {
|
|
55
|
+
const res = await pod.search({
|
|
56
|
+
query: q.query,
|
|
57
|
+
scope: q.scope,
|
|
58
|
+
...(q.scopeTarget !== undefined ? { scopeTarget: q.scopeTarget } : {}),
|
|
59
|
+
limit: 20,
|
|
60
|
+
});
|
|
61
|
+
queries.push(scoreGradedQuery(q, res.results));
|
|
62
|
+
}
|
|
63
|
+
return { queries, aggregate: aggregateGraded(queries) };
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
pod.teardown();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export async function runBench(opts = {}) {
|
|
70
|
+
const startedAt = Date.now();
|
|
71
|
+
const quick = opts.quick === true;
|
|
72
|
+
const invariants = await runInvariantPhase();
|
|
73
|
+
const graded = quick ? EMPTY_GRADED : await runGradedPhase();
|
|
74
|
+
const invariantsPassed = invariants.filter((i) => i.passed).length;
|
|
75
|
+
const ok = invariantsPassed === invariants.length && graded.aggregate.cleanliness === 0;
|
|
76
|
+
return {
|
|
77
|
+
invariants,
|
|
78
|
+
graded,
|
|
79
|
+
invariantsPassed,
|
|
80
|
+
invariantsTotal: invariants.length,
|
|
81
|
+
quick,
|
|
82
|
+
ok,
|
|
83
|
+
durationMs: Date.now() - startedAt,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=run-bench.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-bench.js","sourceRoot":"","sources":["../../src/bench/run-bench.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-automator-run.d.ts","sourceRoot":"","sources":["../src/cli-automator-run.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAEpF;AAED,wBAAgB,2BAA2B,IAAI,OAAO,CAyDrD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
// `lyt automator run <rid|name>` subcommand (block-B Commit 7).
|
|
17
|
+
//
|
|
18
|
+
// Lives in the meta @younndai/lyt CLI because runFiveStep pulls in lyt-runner
|
|
19
|
+
// and lyt-runner depends on lyt-vault — registering `run` inside lyt-vault
|
|
20
|
+
// would create a circular dep. Mirrors the lyt-mesh subcommand-attach pattern
|
|
21
|
+
// at packages/lyt/src/cli.ts.
|
|
22
|
+
//
|
|
23
|
+
// Per Lock 0.3 (SAI-compatible — brief §Conventions L191), --json emits a
|
|
24
|
+
// deterministic JSON envelope so SAIs / Claude Code / Codex can consume the
|
|
25
|
+
// invocation result without screen-scraping.
|
|
26
|
+
import { Command } from "commander";
|
|
27
|
+
import { uuid7BytesToDashedString } from "@younndai/lyt-vault";
|
|
28
|
+
import { runAutomator } from "./automator-run.js";
|
|
29
|
+
// commander stores `--no-push` as push:false (negated-flag convention); the
|
|
30
|
+
// noPush key is only set by test harnesses invoking the action directly.
|
|
31
|
+
// Track C Wave 3 F9: reading only opts.noPush dropped the CLI flag entirely
|
|
32
|
+
// and the run pushed. Exported so the regression test locks the mapping.
|
|
33
|
+
export function resolveNoPushOpt(opts) {
|
|
34
|
+
return opts.push === false || opts.noPush === true;
|
|
35
|
+
}
|
|
36
|
+
export function buildAutomatorRunSubcommand() {
|
|
37
|
+
return new Command("run")
|
|
38
|
+
.description("Run a declared automator end-to-end (5-step protocol: lease → sync → body → commit → release).")
|
|
39
|
+
.argument("<automator>", "Automator name or rid (e.g. 'metadata-filler' or 'automator:metadata-filler')")
|
|
40
|
+
.option("--vault <name>", "Vault name to run against; required when more than one vault is registered")
|
|
41
|
+
.option("--dry-run", "Skip lease acquisition + git pull/push (still invokes the body for inspection)")
|
|
42
|
+
.option("--no-push", "Run the commit step but skip `git push` (still commits locally)")
|
|
43
|
+
.option("--json", "Emit JSON instead of human-readable output")
|
|
44
|
+
.action(async (automator, opts) => {
|
|
45
|
+
const noPush = resolveNoPushOpt(opts);
|
|
46
|
+
const result = await runAutomator({
|
|
47
|
+
automator,
|
|
48
|
+
...(opts.vault !== undefined ? { vault: opts.vault } : {}),
|
|
49
|
+
...(opts.dryRun === true ? { dryRun: true } : {}),
|
|
50
|
+
...(noPush ? { noPush: true } : {}),
|
|
51
|
+
});
|
|
52
|
+
const payload = {
|
|
53
|
+
ok: result.ok,
|
|
54
|
+
automator: result.plan.automatorName,
|
|
55
|
+
automator_version: result.automatorVersion,
|
|
56
|
+
run_id_hex: uuid7BytesToDashedString(result.runId).replace(/-/g, ""),
|
|
57
|
+
vault: {
|
|
58
|
+
name: result.plan.vaultName,
|
|
59
|
+
path: result.plan.vaultPath,
|
|
60
|
+
},
|
|
61
|
+
status: result.status,
|
|
62
|
+
error_summary: result.errorSummary,
|
|
63
|
+
dry_run: opts.dryRun === true,
|
|
64
|
+
no_push: noPush,
|
|
65
|
+
body: result.body ?? null,
|
|
66
|
+
};
|
|
67
|
+
if (opts.json === true) {
|
|
68
|
+
// eslint-disable-next-line no-console
|
|
69
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
console.log(`${result.ok ? "✓" : "✗"} automator:${payload.automator} ` +
|
|
74
|
+
`→ status=${payload.status}${payload.error_summary !== null ? ` (${payload.error_summary})` : ""}`);
|
|
75
|
+
}
|
|
76
|
+
if (!result.ok)
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=cli-automator-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-automator-run.js","sourceRoot":"","sources":["../src/cli-automator-run.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026 MARLINK TRADING SRL (YounndAI)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { createRequire } from "node:module";
|
|
18
|
+
import { Command } from "commander";
|
|
19
|
+
import { buildMcpSubcommand } from "@younndai/lyt-mcp";
|
|
20
|
+
import { buildCloneAllCommand, buildPodStatusCommand, buildSourceCommand, buildStatusCommand, buildSyncCommand, } from "@younndai/lyt-mesh";
|
|
21
|
+
import { buildSkillsCommand } from "@younndai/lyt-skills";
|
|
22
|
+
import { registerVaultVerbs } from "@younndai/lyt-vault";
|
|
23
|
+
import { buildAgentManualCommand, buildDiscoverCommand, buildRepairCommand, } from "@younndai/lyt-vault";
|
|
24
|
+
import { buildAutomatorRunSubcommand } from "./cli-automator-run.js";
|
|
25
|
+
import { buildBenchCommand } from "./commands/bench.js";
|
|
26
|
+
import { buildCaptureCommand } from "./commands/capture.js";
|
|
27
|
+
import { buildLytInitCommand } from "./commands/init.js";
|
|
28
|
+
import { buildPrimerCommand } from "./commands/primer.js";
|
|
29
|
+
import { buildReindexCommand } from "./commands/reindex.js";
|
|
30
|
+
import { buildSearchCommand } from "./commands/search.js";
|
|
31
|
+
const program = new Command();
|
|
32
|
+
program
|
|
33
|
+
.name("lyt")
|
|
34
|
+
.description("Lyt — federated markdown-vault mesh CLI (vault + mesh + sync + mcp + help + doctor + pattern + machine + identity + audit + friction + provenance + capture-metric + automator)")
|
|
35
|
+
.version(createRequire(import.meta.url)("../package.json").version);
|
|
36
|
+
// release review + block-A.3 Commit 11 — single source of truth for
|
|
37
|
+
// the @younndai/lyt-vault verb surface; sync / mcp are kept here because
|
|
38
|
+
// they live in separate workspaces.
|
|
39
|
+
//
|
|
40
|
+
// v1.B.1 delta: the meta CLI used to compose @younndai/lyt-mesh's
|
|
41
|
+
// `buildMeshSubcommand()` directly, but that registers a `mesh` parent
|
|
42
|
+
// that now collides with @younndai/lyt-vault's new v1.B.1 mesh command
|
|
43
|
+
// (init/join/list). Resolution: registerVaultVerbs registers the v1.B.1
|
|
44
|
+
// mesh parent (the canonical surface per master plan §5 v1.B.1); the
|
|
45
|
+
// surviving lyt-mesh subcommands (clone-all, source, status) are
|
|
46
|
+
// attached AFTER. The legacy lyt-mesh `init` subcommand (manifest-
|
|
47
|
+
// driven Phase 7D) is intentionally NOT re-attached — the v1.B.1 multi-
|
|
48
|
+
// mesh `mesh init <name>` supersedes it per master plan §5 (manifest-
|
|
49
|
+
// driven bulk init moves to v1.B.3).
|
|
50
|
+
//
|
|
51
|
+
// v1.C.1 delta: the legacy lyt-mesh `validate` subcommand (parent_vault
|
|
52
|
+
// FK dangling-check) is ALSO intentionally NOT re-attached — the v1.C.1
|
|
53
|
+
// `lyt mesh validate` (cross-mesh @MESH_EDGE walker, registered by
|
|
54
|
+
// registerVaultVerbs via commands/mesh.ts) supersedes it per master plan
|
|
55
|
+
// §v1.C.1:609 acceptance "lyt mesh validate warns on broken edges". The
|
|
56
|
+
// legacy parent_vault FK check is now repaired by v1.C.4 `lyt repair`
|
|
57
|
+
// per master plan §G-5:277 (validate = read-only / repair = write
|
|
58
|
+
// boundary). Same pattern as the v1.B.1 mesh-init supersession above.
|
|
59
|
+
// v1.C.4 ships `lyt repair` at the meta-CLI top level (federation-design
|
|
60
|
+
// §6:250 lists it next to `lyt init` + `lyt discover`).
|
|
61
|
+
//
|
|
62
|
+
// block-B Commit 7 delta: same composition shape applies to `automator`.
|
|
63
|
+
// registerVaultVerbs registers the v1 automator parent with list/log/status
|
|
64
|
+
// subcommands (lyt-vault has no lyt-runner dep). The meta CLI attaches `run`
|
|
65
|
+
// here, because runFiveStep + the metadata-filler body live in packages that
|
|
66
|
+
// depend on lyt-vault — registering them inside lyt-vault would create a
|
|
67
|
+
// cycle. Mirror of the lyt-mesh subcommand attach pattern above.
|
|
68
|
+
registerVaultVerbs(program);
|
|
69
|
+
const meshCmd = program.commands.find((c) => c.name() === "mesh");
|
|
70
|
+
if (meshCmd === undefined) {
|
|
71
|
+
throw new Error("@younndai/lyt meta CLI: expected registerVaultVerbs to register a 'mesh' command but none was found.");
|
|
72
|
+
}
|
|
73
|
+
meshCmd.addCommand(buildCloneAllCommand());
|
|
74
|
+
meshCmd.addCommand(buildSourceCommand());
|
|
75
|
+
meshCmd.addCommand(buildStatusCommand());
|
|
76
|
+
const automatorCmd = program.commands.find((c) => c.name() === "automator");
|
|
77
|
+
if (automatorCmd === undefined) {
|
|
78
|
+
throw new Error("@younndai/lyt meta CLI: expected registerVaultVerbs to register an 'automator' command but none was found.");
|
|
79
|
+
}
|
|
80
|
+
automatorCmd.addCommand(buildAutomatorRunSubcommand());
|
|
81
|
+
program.addCommand(buildSyncCommand());
|
|
82
|
+
// Brief B (B.4) — `lyt status`: top-level publish-drift trust surface (per-vault
|
|
83
|
+
// + pod unpushed/no-remote/clean). Distinct from `lyt mesh status` (the
|
|
84
|
+
// mesh-graph renderer attached under `mesh` above): different scope, different
|
|
85
|
+
// answer ("is my stuff published?" vs "what's the federation topology?").
|
|
86
|
+
program.addCommand(buildPodStatusCommand());
|
|
87
|
+
program.addCommand(buildMcpSubcommand());
|
|
88
|
+
// v1.D.3b — `lyt search` lives at the meta-CLI level per master-plan
|
|
89
|
+
// §v1.D.3:785 wording "lyt search" (no `vault` subcommand). The
|
|
90
|
+
// default scope is federation; placing it under `vault` would tilt
|
|
91
|
+
// user mental model toward single-vault use. The cascade engine
|
|
92
|
+
// itself lives in @younndai/lyt-vault (data-layer ownership); the
|
|
93
|
+
// command builder here is the CLI-surface adapter.
|
|
94
|
+
program.addCommand(buildSearchCommand());
|
|
95
|
+
// V-C-1 Phase E / V-C-2 — `lyt capture "<text>"`: the frictionless top-level
|
|
96
|
+
// alias for `pattern run knowledge-capture capture` the wizard advertises.
|
|
97
|
+
// True alias (same ceremony: mandatory purpose+topic, 8-field contract) +
|
|
98
|
+
// index-on-write so a capture is searchable immediately. Top-level like
|
|
99
|
+
// search/primer/reindex; the flow lives in @younndai/lyt-vault.
|
|
100
|
+
program.addCommand(buildCaptureCommand());
|
|
101
|
+
// v1.D.4 — `lyt primer` mirrors the meta-CLI posture of `lyt search`.
|
|
102
|
+
// Same rationale: the verb operates at vault | mesh | federation scope
|
|
103
|
+
// per master-plan §v1.D.4:832; placing it under `vault` would tilt
|
|
104
|
+
// mental model. The generator flow lives in @younndai/lyt-vault; the
|
|
105
|
+
// command builder here is the CLI-surface adapter.
|
|
106
|
+
program.addCommand(buildPrimerCommand());
|
|
107
|
+
// Lane V Phase 0 (0.5 / CLI gaps C1+C2) — `lyt reindex [--all|--mesh|--vault]`
|
|
108
|
+
// rebuilds all content-tier caches (lanes+arcs+fts+rollup) across the pod, a
|
|
109
|
+
// mesh, or one vault. Top-level (like search/primer) because its mental model
|
|
110
|
+
// is pod-wide. The reindexFlow lives in @younndai/lyt-vault (data-layer
|
|
111
|
+
// ownership); this is the CLI-surface adapter.
|
|
112
|
+
program.addCommand(buildReindexCommand());
|
|
113
|
+
// Lane V Workstream 2 — `lyt bench`: privacy-trivial retrieval self-test over a
|
|
114
|
+
// synthetic temp pod (never the user's ~/lyt). Top-level like search/primer/
|
|
115
|
+
// reindex. The harness lives in ./bench (productized from tools/lane-v, which is
|
|
116
|
+
// dev-only and not shipped); this is the CLI-surface adapter.
|
|
117
|
+
program.addCommand(buildBenchCommand());
|
|
118
|
+
// v1.B.4 — `lyt init` lives at the meta-CLI top level per OD-1 default +
|
|
119
|
+
// master-plan §v1.B.4:543 + federation-design §5:248. Composes
|
|
120
|
+
// meshInitFlow + federationInitFlow into idempotent bootstrap with
|
|
121
|
+
// three branches (fresh / re-init / discovery) + `--auto` default.
|
|
122
|
+
program.addCommand(buildLytInitCommand());
|
|
123
|
+
// v1.C.3 — `lyt discover` lives at the meta-CLI top level per OD-1 default +
|
|
124
|
+
// federation-design §6:249 (lists `lyt discover` next to `lyt init`).
|
|
125
|
+
// Read-only walk of GH-accessible repos; clusters discovered Lyt vaults
|
|
126
|
+
// by @VAULT_HOME_MESH.mesh_name; per-cluster orphan-recovery prompt
|
|
127
|
+
// (adopt / external / skip) ships in Commit 3. Mirror lyt search / lyt
|
|
128
|
+
// primer / lyt init top-level attach pattern.
|
|
129
|
+
program.addCommand(buildDiscoverCommand());
|
|
130
|
+
// v1.C.4 — `lyt repair` lives at the meta-CLI top level per OD-1 default +
|
|
131
|
+
// federation-design §6:250 (lists `lyt repair` next to `lyt init` +
|
|
132
|
+
// `lyt discover`). Default mode is --dry-run; --apply performs writes
|
|
133
|
+
// across the 4 federation-design §11:515-521 failure classes (broken
|
|
134
|
+
// @MESH_EDGE, broken @MESH_SUBSCRIPTION, mesh.yon parse error → restore
|
|
135
|
+
// from Git, orphan vault re-attach). G-5 contract LOCK: this is the
|
|
136
|
+
// write side of validate = read-only / repair = write per master-plan
|
|
137
|
+
// §G-5:277.
|
|
138
|
+
program.addCommand(buildRepairCommand());
|
|
139
|
+
// v1.F.3 — `lyt skills` lives at the meta-CLI top level per OD-2 default +
|
|
140
|
+
// master-plan §v1.F.3:1033 verb wording ("lyt skills install"). Composes
|
|
141
|
+
// symlinkSkillsTriRuntime + listSkillsTriRuntime into the symlink + runtime-
|
|
142
|
+
// state-reporting surface for the 10 bundled skills across ~/.claude/skills,
|
|
143
|
+
// ~/.codex/skills, ~/.agents/skills. Per OD-5 + OD-16 ratified 2026-06-01,
|
|
144
|
+
// the legacy standalone `lyt-skills` bin + copy-based `installSkills` flow
|
|
145
|
+
// were removed in the same phase (pre-release clean slate).
|
|
146
|
+
program.addCommand(buildSkillsCommand());
|
|
147
|
+
// v1.G.5 — `lyt agent-manual --runtime {claude|codex|agents|generic}
|
|
148
|
+
// [--install] [--dry-run]` at the meta-CLI top level. Mirrors the
|
|
149
|
+
// discover / repair / skills attach pattern above. Generates the Lyt
|
|
150
|
+
// agent manual (~150 lines / ~1.5K tokens) and writes it (or previews
|
|
151
|
+
// it) into agent-runtime global instructions files via the
|
|
152
|
+
// `<!-- lyt-manual v<lyt-version> BEGIN -->...END -->` marker pattern
|
|
153
|
+
// (D9 update-path primitive per the ratified default ratified 2026-06-01).
|
|
154
|
+
program.addCommand(buildAgentManualCommand());
|
|
155
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
156
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
157
|
+
// eslint-disable-next-line no-console
|
|
158
|
+
console.error(`lyt: ${message}`);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CACV,iLAAiL,CAClL;KACA,OAAO,CAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC,CAAC;AAE/F,oEAAoE;AACpE,yEAAyE;AACzE,oCAAoC;AACpC,EAAE;AACF,kEAAkE;AAClE,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,qEAAqE;AACrE,iEAAiE;AACjE,mEAAmE;AACnE,wEAAwE;AACxE,sEAAsE;AACtE,qCAAqC;AACrC,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,mEAAmE;AACnE,yEAAyE;AACzE,wEAAwE;AACxE,sEAAsE;AACtE,kEAAkE;AAClE,sEAAsE;AACtE,yEAAyE;AACzE,wDAAwD;AACxD,EAAE;AACF,yEAAyE;AACzE,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,yEAAyE;AACzE,iEAAiE;AACjE,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC;AAClE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;IAC1B,MAAM,IAAI,KAAK,CACb,sGAAsG,CACvG,CAAC;AACJ,CAAC;AACD,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,WAAW,CAAC,CAAC;AAC5E,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;IAC/B,MAAM,IAAI,KAAK,CACb,4GAA4G,CAC7G,CAAC;AACJ,CAAC;AACD,YAAY,CAAC,UAAU,CAAC,2BAA2B,EAAE,CAAC,CAAC;AAEvD,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,iFAAiF;AACjF,wEAAwE;AACxE,+EAA+E;AAC/E,0EAA0E;AAC1E,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,qEAAqE;AACrE,gEAAgE;AAChE,mEAAmE;AACnE,gEAAgE;AAChE,kEAAkE;AAClE,mDAAmD;AACnD,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,6EAA6E;AAC7E,2EAA2E;AAC3E,0EAA0E;AAC1E,wEAAwE;AACxE,gEAAgE;AAChE,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,sEAAsE;AACtE,uEAAuE;AACvE,mEAAmE;AACnE,qEAAqE;AACrE,mDAAmD;AACnD,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,wEAAwE;AACxE,+CAA+C;AAC/C,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,gFAAgF;AAChF,6EAA6E;AAC7E,iFAAiF;AACjF,8DAA8D;AAC9D,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAExC,yEAAyE;AACzE,+DAA+D;AAC/D,mEAAmE;AACnE,mEAAmE;AACnE,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,6EAA6E;AAC7E,sEAAsE;AACtE,wEAAwE;AACxE,oEAAoE;AACpE,uEAAuE;AACvE,8CAA8C;AAC9C,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;AAE3C,2EAA2E;AAC3E,oEAAoE;AACpE,sEAAsE;AACtE,qEAAqE;AACrE,wEAAwE;AACxE,oEAAoE;AACpE,sEAAsE;AACtE,YAAY;AACZ,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,2EAA2E;AAC3E,yEAAyE;AACzE,6EAA6E;AAC7E,6EAA6E;AAC7E,2EAA2E;AAC3E,2EAA2E;AAC3E,4DAA4D;AAC5D,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,qEAAqE;AACrE,kEAAkE;AAClE,qEAAqE;AACrE,sEAAsE;AACtE,2DAA2D;AAC3D,sEAAsE;AACtE,2EAA2E;AAC3E,OAAO,CAAC,UAAU,CAAC,uBAAuB,EAAE,CAAC,CAAC;AAE9C,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../src/commands/bench.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,iBAAiB,IAAI,OAAO,CAsF3C"}
|
|
@@ -0,0 +1,92 @@
|
|
|
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 { Command } from "commander";
|
|
17
|
+
import { DEFAULT_LATENCY_COUNT, runLatencyBench } from "../bench/latency-bench.js";
|
|
18
|
+
import { runBench } from "../bench/run-bench.js";
|
|
19
|
+
// Lane V Workstream 2 — `lyt bench`: a privacy-trivial retrieval self-test.
|
|
20
|
+
// Stands up TEMP throwaway pods under os.tmpdir (never the user's ~/lyt), seeds
|
|
21
|
+
// tiny deterministic synthetic corpora, indexes them, and reports:
|
|
22
|
+
// • (default) D-core invariants + E-lite graded quality
|
|
23
|
+
// • --quick invariants only (the fast every-CI path)
|
|
24
|
+
// • --latency index + query p50/p95 on a synthetic corpus (--count to scale)
|
|
25
|
+
// No user content is read, by construction — safe to run anywhere.
|
|
26
|
+
export function buildBenchCommand() {
|
|
27
|
+
return new Command("bench")
|
|
28
|
+
.description("Self-test Lyt's retrieval engine against synthetic corpora (privacy-trivial — reads no user content). Asserts the retrieval invariants and reports a graded quality score; exits non-zero if an invariant or hygiene trap regressed.")
|
|
29
|
+
.option("--json", "Emit a JSON report instead of the human-readable summary")
|
|
30
|
+
.option("--quick", "Run only the pass/fail invariants (skip the graded-quality phase — faster)")
|
|
31
|
+
.option("--latency", "Run the latency benchmark (index + query p50/p95) instead of the quality self-test")
|
|
32
|
+
.option("--count <n>", `Latency corpus size (default ${DEFAULT_LATENCY_COUNT}; use 5000+ for a federation-scale reading)`)
|
|
33
|
+
.action(async (opts) => {
|
|
34
|
+
try {
|
|
35
|
+
if (opts.latency === true) {
|
|
36
|
+
const parsed = opts.count !== undefined ? Number.parseInt(opts.count, 10) : undefined;
|
|
37
|
+
const report = await runLatencyBench(parsed !== undefined && Number.isFinite(parsed) ? { count: parsed } : {});
|
|
38
|
+
if (opts.json === true) {
|
|
39
|
+
// eslint-disable-next-line no-console
|
|
40
|
+
console.log(JSON.stringify(report, null, 2));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.log([
|
|
45
|
+
`lyt bench --latency — synthetic corpus (${report.durationMs}ms)`,
|
|
46
|
+
` index: ${report.indexMs}ms (${report.corpusSize} figments, all tiers)`,
|
|
47
|
+
` query: p50 ${report.queryP50Ms}ms p95 ${report.queryP95Ms}ms mean ${report.queryMeanMs}ms (${report.querySamples} samples)`,
|
|
48
|
+
].join("\n"));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const report = await runBench({ quick: opts.quick === true });
|
|
52
|
+
if (opts.json === true) {
|
|
53
|
+
// eslint-disable-next-line no-console
|
|
54
|
+
console.log(JSON.stringify(report, null, 2));
|
|
55
|
+
if (!report.ok)
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const lines = [
|
|
60
|
+
`lyt bench — retrieval self-test${report.quick ? " (quick)" : ""} (${report.durationMs}ms)`,
|
|
61
|
+
"",
|
|
62
|
+
`Invariants (${report.invariantsPassed}/${report.invariantsTotal} passed):`,
|
|
63
|
+
];
|
|
64
|
+
for (const inv of report.invariants) {
|
|
65
|
+
lines.push(` ${inv.passed ? "✓" : "✗"} ${inv.id} ${inv.name}`);
|
|
66
|
+
if (!inv.passed)
|
|
67
|
+
lines.push(` ${inv.detail}`);
|
|
68
|
+
}
|
|
69
|
+
if (!report.quick) {
|
|
70
|
+
const g = report.graded.aggregate;
|
|
71
|
+
lines.push("", `Quality (synthetic graded oracle, ${g.queries} queries):`, ` nDCG@10 ${g.ndcg} recall ${g.recall} MRR ${g.mrr} P@1 ${g.pAt1} cleanliness ${g.cleanliness}`);
|
|
72
|
+
for (const q of report.graded.queries) {
|
|
73
|
+
lines.push(` ${q.id.padEnd(14)} nDCG ${q.ndcg} recall ${q.recall} MRR ${q.mrr}`);
|
|
74
|
+
}
|
|
75
|
+
lines.push(" (nDCG < 1.0 is expected — Q-replica is a deliberate non-aced case: raw BM25 ≠ graded relevance, the known v2 rank-fusion residual.)");
|
|
76
|
+
}
|
|
77
|
+
lines.push("", report.ok
|
|
78
|
+
? "PASS — invariants hold and no hygiene trap leaked."
|
|
79
|
+
: "FAIL — an invariant or hygiene trap regressed.");
|
|
80
|
+
// eslint-disable-next-line no-console
|
|
81
|
+
console.log(lines.join("\n"));
|
|
82
|
+
if (!report.ok)
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
// eslint-disable-next-line no-console
|
|
87
|
+
console.error(`lyt bench: ${err instanceof Error ? err.message : String(err)}`);
|
|
88
|
+
process.exitCode = 2;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=bench.js.map
|