@djolex999/vir-cli 0.24.3 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -1
- package/dist/claude/updater.js +83 -7
- package/dist/claude/updater.js.map +1 -1
- package/dist/cli/connect.js +100 -0
- package/dist/cli/connect.js.map +1 -0
- package/dist/cli/initConfig.js +2 -0
- package/dist/cli/initConfig.js.map +1 -1
- package/dist/cli/insightsStatus.js +13 -0
- package/dist/cli/insightsStatus.js.map +1 -0
- package/dist/cli/reviewInsights.js +145 -0
- package/dist/cli/reviewInsights.js.map +1 -0
- package/dist/cli/syncClaude.js +101 -0
- package/dist/cli/syncClaude.js.map +1 -0
- package/dist/cli.js +43 -66
- package/dist/cli.js.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/connect/calibrate.js +44 -0
- package/dist/connect/calibrate.js.map +1 -0
- package/dist/connect/cluster.js +63 -0
- package/dist/connect/cluster.js.map +1 -0
- package/dist/connect/embed.js +47 -0
- package/dist/connect/embed.js.map +1 -0
- package/dist/connect/extract.js +129 -0
- package/dist/connect/extract.js.map +1 -0
- package/dist/connect/identity.js +65 -0
- package/dist/connect/identity.js.map +1 -0
- package/dist/connect/insightFile.js +61 -0
- package/dist/connect/insightFile.js.map +1 -0
- package/dist/connect/qualify.js +39 -0
- package/dist/connect/qualify.js.map +1 -0
- package/dist/connect/run.js +199 -0
- package/dist/connect/run.js.map +1 -0
- package/dist/connect/text.js +20 -0
- package/dist/connect/text.js.map +1 -0
- package/dist/connect/types.js +2 -0
- package/dist/connect/types.js.map +1 -0
- package/dist/connect/verify.js +77 -0
- package/dist/connect/verify.js.map +1 -0
- package/dist/mcp/server.js +10 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/output/json.js +2 -0
- package/dist/output/json.js.map +1 -1
- package/dist/pipeline/run.js +6 -0
- package/dist/pipeline/run.js.map +1 -1
- package/dist/search/retriever.js +19 -0
- package/dist/search/retriever.js.map +1 -1
- package/dist/search/thresholds.js +22 -2
- package/dist/search/thresholds.js.map +1 -1
- package/dist/state/db.js +238 -0
- package/dist/state/db.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.js","sourceRoot":"","sources":["../../src/connect/cluster.ts"],"names":[],"mappings":"AAEA,SAAS,IAAI,CAAC,CAAW;IACvB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,CAAC;AACD,SAAS,GAAG,CAAC,CAAW,EAAE,CAAW;IACnC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;QAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,CAAC;AACX,CAAC;AACD,SAAS,QAAQ,CAAC,EAAc;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE;QAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;YAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACtF,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAiB,EACjB,OAA8B,EAC9B,MAAc,EACd,OAAe,EACf,GAAG,GAAG,EAAE;IAER,MAAM,KAAK,GAAG,OAAO;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;SACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE;QACjC,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;QACxF,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC/C,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACX,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAC3B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAC3B,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,GAAG,CAAC;aACF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACtC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;aACrE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Vectors for every lesson, keyed by contentHash. Cached vectors are reused;
|
|
2
|
+
// misses are embedded once per distinct hash and stored as they arrive, so a
|
|
3
|
+
// retry resumes where this run stopped. A provider failure stops the run
|
|
4
|
+
// (spec §10): clustering a fragment of the vault would propose rules from
|
|
5
|
+
// partial evidence. Over-long text is not a failure — the provider truncates.
|
|
6
|
+
export async function embedLessons(lessons, db, provider) {
|
|
7
|
+
const textByHash = new Map();
|
|
8
|
+
for (const l of lessons)
|
|
9
|
+
textByHash.set(l.contentHash, l.text);
|
|
10
|
+
const hashes = [...textByHash.keys()];
|
|
11
|
+
const out = db.getLessonEmbeddings(hashes, provider.modelName);
|
|
12
|
+
let embedded = 0;
|
|
13
|
+
for (const hash of hashes) {
|
|
14
|
+
if (out.has(hash))
|
|
15
|
+
continue;
|
|
16
|
+
let vec;
|
|
17
|
+
try {
|
|
18
|
+
vec = (await provider.embedDoc(textByHash.get(hash) ?? "")).embedding;
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
throw new Error(`embedding provider failed after ${embedded} lesson(s) — nothing written: ${err.message}`);
|
|
22
|
+
}
|
|
23
|
+
db.storeLessonEmbedding(hash, provider.modelName, vec);
|
|
24
|
+
out.set(hash, vec);
|
|
25
|
+
embedded += 1;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
// Self-heal for accepted rules: embedded at accept time, but a provider outage
|
|
30
|
+
// then, or a later model switch, would leave them out of embedding search.
|
|
31
|
+
// Best-effort — a failed embed is retried on the next sweep. Returns the count.
|
|
32
|
+
export async function backfillInsightEmbeddings(db, provider) {
|
|
33
|
+
let n = 0;
|
|
34
|
+
for (const t of db.listInsightEmbeddingTargets(provider.modelName)) {
|
|
35
|
+
let vec;
|
|
36
|
+
try {
|
|
37
|
+
vec = (await provider.embedDoc(`${t.rule}\n${t.why}`)).embedding;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
db.setInsightEmbedding(t.id, vec, { model: provider.modelName, dim: vec.length });
|
|
43
|
+
n += 1;
|
|
44
|
+
}
|
|
45
|
+
return n;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=embed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed.js","sourceRoot":"","sources":["../../src/connect/embed.ts"],"names":[],"mappings":"AAIA,6EAA6E;AAC7E,6EAA6E;AAC7E,yEAAyE;AACzE,0EAA0E;AAC1E,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAiB,EACjB,EAAW,EACX,QAA2B;IAE3B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC/D,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5B,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,mCAAmC,QAAQ,iCAAkC,GAAa,CAAC,OAAO,EAAE,CACrG,CAAC;QACJ,CAAC;QACD,EAAE,CAAC,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACvD,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACnB,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+EAA+E;AAC/E,2EAA2E;AAC3E,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,EAAW,EAAE,QAA2B;IACtF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,2BAA2B,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACnE,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAClF,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
import { parseFrontmatter } from "../cli/review.js";
|
|
5
|
+
import { kebab } from "../pipeline/slug.js";
|
|
6
|
+
import { CATEGORY_DIR } from "../pipeline/writer.js";
|
|
7
|
+
const ITEM_RE = /^(?:[-*]|\d+\.)?\s*(?:\*\*|__)/;
|
|
8
|
+
const HEADING_RE = /^#{1,2}\s/;
|
|
9
|
+
function section(lines, title) {
|
|
10
|
+
const start = lines.findIndex((l) => title.test(l));
|
|
11
|
+
if (start === -1)
|
|
12
|
+
return null;
|
|
13
|
+
const out = [];
|
|
14
|
+
for (let i = start + 1; i < lines.length; i += 1) {
|
|
15
|
+
const line = lines[i] ?? "";
|
|
16
|
+
if (HEADING_RE.test(line))
|
|
17
|
+
break;
|
|
18
|
+
out.push(line);
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
// A lesson starts on a base-indent line beginning with an optional list marker
|
|
23
|
+
// and bold; its body runs to the next base-indent item or heading. Nested
|
|
24
|
+
// (indented) bold lines belong to their parent. Mid-line bold is not an item.
|
|
25
|
+
export function extractLessonTexts(markdown) {
|
|
26
|
+
const lines = markdown.split("\n");
|
|
27
|
+
const learned = section(lines, /^##\s+What Was Learned\s*$/);
|
|
28
|
+
if (learned === null) {
|
|
29
|
+
const summary = section(lines, /^##\s+Summary\s*$/);
|
|
30
|
+
const text = (summary ?? []).join("\n").trim();
|
|
31
|
+
return text.length > 0 ? [text] : [];
|
|
32
|
+
}
|
|
33
|
+
const items = [];
|
|
34
|
+
let cur = null;
|
|
35
|
+
for (const line of learned) {
|
|
36
|
+
// ### subheadings group lessons; they end the current item and are not text.
|
|
37
|
+
if (/^#{3,6}\s/.test(line)) {
|
|
38
|
+
cur = null;
|
|
39
|
+
}
|
|
40
|
+
else if (ITEM_RE.test(line) && !/^\s/.test(line)) {
|
|
41
|
+
cur = [line];
|
|
42
|
+
items.push(cur);
|
|
43
|
+
}
|
|
44
|
+
else if (cur) {
|
|
45
|
+
cur.push(line);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return items.map((l) => l.join("\n").trim()).filter((t) => t.length > 0);
|
|
49
|
+
}
|
|
50
|
+
export function normalizeLesson(raw) {
|
|
51
|
+
return raw
|
|
52
|
+
.split("\n")
|
|
53
|
+
.map((l) => l.replace(/^\s*(?:[-*]|\d+\.)\s+/, ""))
|
|
54
|
+
.join(" ")
|
|
55
|
+
.replace(/\*\*|__/g, "")
|
|
56
|
+
.replace(/\s+/g, " ")
|
|
57
|
+
.trim();
|
|
58
|
+
}
|
|
59
|
+
export function lessonHash(normalized) {
|
|
60
|
+
return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
61
|
+
}
|
|
62
|
+
export function archivedDuplicateSlugs(markdown) {
|
|
63
|
+
const lines = section(markdown.split("\n"), /^##\s+Archived Duplicates\s*$/) ?? [];
|
|
64
|
+
return lines
|
|
65
|
+
.map((l) => l.match(/^\s*-\s*\[\[([^\]|]+)(?:\|[^\]]*)?\]\]/)?.[1]?.trim())
|
|
66
|
+
.filter((s) => typeof s === "string" && s.length > 0);
|
|
67
|
+
}
|
|
68
|
+
function lessonsFromNote(path, citeSlug, archivedVia) {
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = readFileSync(path, "utf8");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const fm = parseFrontmatter(raw);
|
|
77
|
+
const sessionId = fm.session_id ?? "";
|
|
78
|
+
if (sessionId.length === 0)
|
|
79
|
+
return [];
|
|
80
|
+
const noteSlug = basename(path, ".md");
|
|
81
|
+
return extractLessonTexts(raw).map((t, itemIndex) => {
|
|
82
|
+
const text = normalizeLesson(t);
|
|
83
|
+
return {
|
|
84
|
+
id: `${noteSlug}#${itemIndex}`,
|
|
85
|
+
noteSlug,
|
|
86
|
+
citeSlug,
|
|
87
|
+
sessionId,
|
|
88
|
+
noteDate: fm.date ?? "",
|
|
89
|
+
project: kebab(fm.project ?? ""),
|
|
90
|
+
category: (fm.category ?? "pattern"),
|
|
91
|
+
itemIndex,
|
|
92
|
+
text,
|
|
93
|
+
contentHash: lessonHash(text),
|
|
94
|
+
archivedVia,
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
export function collectLessons(vaultRoot) {
|
|
99
|
+
const out = [];
|
|
100
|
+
for (const dir of Object.values(CATEGORY_DIR)) {
|
|
101
|
+
const full = join(vaultRoot, dir);
|
|
102
|
+
let names;
|
|
103
|
+
try {
|
|
104
|
+
names = readdirSync(full).filter((n) => n.endsWith(".md")).sort();
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
for (const name of names) {
|
|
110
|
+
const path = join(full, name);
|
|
111
|
+
const slug = basename(name, ".md");
|
|
112
|
+
out.push(...lessonsFromNote(path, slug, null));
|
|
113
|
+
let raw = "";
|
|
114
|
+
try {
|
|
115
|
+
raw = readFileSync(path, "utf8");
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
for (const loser of archivedDuplicateSlugs(raw)) {
|
|
121
|
+
const lp = join(vaultRoot, "archived", `${loser}.md`);
|
|
122
|
+
if (existsSync(lp))
|
|
123
|
+
out.push(...lessonsFromNote(lp, slug, slug));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/connect/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export function jaccard(a, b) {
|
|
2
|
+
const sa = new Set(a);
|
|
3
|
+
const sb = new Set(b);
|
|
4
|
+
let inter = 0;
|
|
5
|
+
for (const x of sa)
|
|
6
|
+
if (sb.has(x))
|
|
7
|
+
inter += 1;
|
|
8
|
+
const union = sa.size + sb.size - inter;
|
|
9
|
+
return union === 0 ? 0 : inter / union;
|
|
10
|
+
}
|
|
11
|
+
export const MATCH_JACCARD = 0.5;
|
|
12
|
+
function cosine(a, b) {
|
|
13
|
+
let dot = 0;
|
|
14
|
+
let na = 0;
|
|
15
|
+
let nb = 0;
|
|
16
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
17
|
+
const x = a[i] ?? 0;
|
|
18
|
+
const y = b[i] ?? 0;
|
|
19
|
+
dot += x * y;
|
|
20
|
+
na += x * x;
|
|
21
|
+
nb += y * y;
|
|
22
|
+
}
|
|
23
|
+
return na === 0 || nb === 0 ? 0 : dot / Math.sqrt(na * nb);
|
|
24
|
+
}
|
|
25
|
+
// Identity is the member SESSION set: session ids survive note rewrites
|
|
26
|
+
// (reconcile, run --full, dedupe winners, review edits); content hashes don't.
|
|
27
|
+
// Hash overlap only breaks ties. A rejected rule is also matched by its rule
|
|
28
|
+
// embedding, so a reworded re-discovery from new sessions stays rejected.
|
|
29
|
+
export function matchCandidate(candidate, insights, rejectedVectors, coreSim) {
|
|
30
|
+
let best = null;
|
|
31
|
+
let bestJ = -1;
|
|
32
|
+
let bestH = -1;
|
|
33
|
+
for (const ins of insights) {
|
|
34
|
+
const j = jaccard(candidate.sessionIds, ins.memberSessionIds);
|
|
35
|
+
if (j < MATCH_JACCARD)
|
|
36
|
+
continue;
|
|
37
|
+
const h = jaccard(candidate.hashes, ins.memberHashes);
|
|
38
|
+
if (j > bestJ || (j === bestJ && h > bestH)) {
|
|
39
|
+
best = ins;
|
|
40
|
+
bestJ = j;
|
|
41
|
+
bestH = h;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (best === null && candidate.ruleVector !== null) {
|
|
45
|
+
for (const ins of insights) {
|
|
46
|
+
if (ins.status !== "rejected")
|
|
47
|
+
continue;
|
|
48
|
+
const v = rejectedVectors.get(ins.id);
|
|
49
|
+
if (v && cosine(candidate.ruleVector, v) >= coreSim)
|
|
50
|
+
return { kind: "skip-rejected", insight: ins };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (best === null)
|
|
54
|
+
return { kind: "new" };
|
|
55
|
+
if (best.status === "rejected")
|
|
56
|
+
return { kind: "skip-rejected", insight: best };
|
|
57
|
+
if (best.status === "proposed")
|
|
58
|
+
return { kind: "update-proposed", insight: best };
|
|
59
|
+
const known = new Set(best.memberSessionIds);
|
|
60
|
+
const added = [...new Set(candidate.sessionIds)].filter((s) => !known.has(s));
|
|
61
|
+
return added.length === 0
|
|
62
|
+
? { kind: "accepted-unchanged", insight: best }
|
|
63
|
+
: { kind: "accepted-additions", insight: best, addedSessions: added };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/connect/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { kebab } from "../pipeline/slug.js";
|
|
4
|
+
import { ruleText } from "./text.js";
|
|
5
|
+
export const INSIGHTS_RULES_DIR = "insights/rules";
|
|
6
|
+
export function insightSlug(rule, id) {
|
|
7
|
+
const base = kebab(rule).slice(0, 60).replace(/-+$/, "");
|
|
8
|
+
const suffix = id.replace(/[^a-z0-9]/gi, "").slice(0, 8).toLowerCase();
|
|
9
|
+
return base.length > 0 ? `${base}-${suffix}` : `rule-${suffix}`;
|
|
10
|
+
}
|
|
11
|
+
const q = (s) => JSON.stringify(s);
|
|
12
|
+
export function renderInsight(row) {
|
|
13
|
+
const fm = [
|
|
14
|
+
"---",
|
|
15
|
+
"type: insight",
|
|
16
|
+
`insight_type: ${row.insightType}`,
|
|
17
|
+
`status: ${row.status}`,
|
|
18
|
+
`promotion: ${row.promotion}`,
|
|
19
|
+
`verified: ${row.status === "accepted"}`,
|
|
20
|
+
`scope: ${row.scope}`,
|
|
21
|
+
`sessions: ${row.sessions}`,
|
|
22
|
+
`projects: [${row.projects.map(q).join(", ")}]`,
|
|
23
|
+
`first_seen: ${row.firstSeen.slice(0, 10)}`,
|
|
24
|
+
`last_seen: ${row.lastSeen.slice(0, 10)}`,
|
|
25
|
+
"sources:",
|
|
26
|
+
...row.sources.map((s) => ` - ${q(`[[${s}]]`)}`),
|
|
27
|
+
`generated: ${row.createdAt}`,
|
|
28
|
+
`model: ${row.model}`,
|
|
29
|
+
"---",
|
|
30
|
+
];
|
|
31
|
+
const evidence = row.evidence.map((e) => `- [[${e.citeSlug}]] (${e.project || "-"}, ${e.date.slice(0, 10)}): ${q(e.quote)}`);
|
|
32
|
+
return [
|
|
33
|
+
...fm,
|
|
34
|
+
`**Rule:** ${row.rule}`,
|
|
35
|
+
"",
|
|
36
|
+
`**Why:** ${row.why}`,
|
|
37
|
+
"",
|
|
38
|
+
"## Evidence",
|
|
39
|
+
"",
|
|
40
|
+
...evidence,
|
|
41
|
+
"",
|
|
42
|
+
].join("\n");
|
|
43
|
+
}
|
|
44
|
+
// The owner edits only the **Rule:** and **Why:** lines; everything else is
|
|
45
|
+
// re-rendered from the DB on the next state write.
|
|
46
|
+
export function parseRuleEdit(raw) {
|
|
47
|
+
const rule = ruleText(raw.match(/^\*\*Rule:\*\*[ \t]*(.+)$/m)?.[1] ?? "");
|
|
48
|
+
if (rule.length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
const why = ruleText(raw.match(/^\*\*Why:\*\*[ \t]*(.+)$/m)?.[1] ?? "");
|
|
51
|
+
return { rule, why };
|
|
52
|
+
}
|
|
53
|
+
export function writeInsightFile(vaultRoot, row) {
|
|
54
|
+
const path = join(vaultRoot, INSIGHTS_RULES_DIR, `${row.slug}.md`);
|
|
55
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
56
|
+
const tmp = `${path}.vir-${process.pid}.tmp`;
|
|
57
|
+
writeFileSync(tmp, renderInsight(row));
|
|
58
|
+
renameSync(tmp, path);
|
|
59
|
+
return path;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=insightFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insightFile.js","sourceRoot":"","sources":["../../src/connect/insightFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const MIN_SESSIONS = 3;
|
|
2
|
+
export const MIN_SPAN_DAYS = 7;
|
|
3
|
+
const DAY_MS = 86_400_000;
|
|
4
|
+
// Each session counts once, dated by its earliest parseable note date. A
|
|
5
|
+
// session with no parseable date still counts toward sessions but not the span.
|
|
6
|
+
export function recurrence(members) {
|
|
7
|
+
const earliest = new Map();
|
|
8
|
+
for (const m of members) {
|
|
9
|
+
const t = Date.parse(m.noteDate);
|
|
10
|
+
const prev = earliest.get(m.sessionId);
|
|
11
|
+
if (prev === undefined)
|
|
12
|
+
earliest.set(m.sessionId, Number.isFinite(t) ? t : null);
|
|
13
|
+
else if (Number.isFinite(t) && (prev === null || t < prev))
|
|
14
|
+
earliest.set(m.sessionId, t);
|
|
15
|
+
}
|
|
16
|
+
const times = [...earliest.values()].filter((t) => t !== null);
|
|
17
|
+
const first = times.length > 0 ? Math.min(...times) : null;
|
|
18
|
+
const last = times.length > 0 ? Math.max(...times) : null;
|
|
19
|
+
const projects = [...new Set(members.map((m) => m.project).filter((p) => p.length > 0))].sort();
|
|
20
|
+
return {
|
|
21
|
+
sessions: [...earliest.keys()],
|
|
22
|
+
firstSeen: first === null ? "" : new Date(first).toISOString(),
|
|
23
|
+
lastSeen: last === null ? "" : new Date(last).toISOString(),
|
|
24
|
+
projects,
|
|
25
|
+
spanDays: first === null || last === null ? 0 : (last - first) / DAY_MS,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function qualifies(r) {
|
|
29
|
+
return r.sessions.length >= MIN_SESSIONS && r.spanDays >= MIN_SPAN_DAYS;
|
|
30
|
+
}
|
|
31
|
+
export function rankCandidates(clusters) {
|
|
32
|
+
return clusters
|
|
33
|
+
.map((members) => ({ members, rec: recurrence(members) }))
|
|
34
|
+
.filter((c) => qualifies(c.rec))
|
|
35
|
+
.sort((a, b) => b.rec.sessions.length - a.rec.sessions.length ||
|
|
36
|
+
b.rec.spanDays - a.rec.spanDays ||
|
|
37
|
+
b.rec.projects.length - a.rec.projects.length);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=qualify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qualify.js","sourceRoot":"","sources":["../../src/connect/qualify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { acquireLock, releaseLock } from "../pipeline/lock.js";
|
|
3
|
+
import { vaultRoot } from "../search/retriever.js";
|
|
4
|
+
import { embedNoteWithProvider } from "../search/provider.js";
|
|
5
|
+
import { thresholdsFor } from "../search/thresholds.js";
|
|
6
|
+
import { clusterLessons } from "./cluster.js";
|
|
7
|
+
import { backfillInsightEmbeddings, embedLessons } from "./embed.js";
|
|
8
|
+
import { collectLessons } from "./extract.js";
|
|
9
|
+
import { matchCandidate } from "./identity.js";
|
|
10
|
+
import { insightSlug, writeInsightFile } from "./insightFile.js";
|
|
11
|
+
import { rankCandidates, recurrence } from "./qualify.js";
|
|
12
|
+
import { buildVerifyPrompt, parseVerdict, validateVerdict } from "./verify.js";
|
|
13
|
+
const VERIFY_OUTPUT_TOKENS = 600;
|
|
14
|
+
function emptySummary() {
|
|
15
|
+
return {
|
|
16
|
+
lessons: 0, clusters: 0, candidates: 0, deferred: 0, proposed: 0, updated: 0, unchanged: 0,
|
|
17
|
+
skippedRejected: 0, unverified: 0, llmFailures: 0, additionsFlagged: 0, llmCalls: 0,
|
|
18
|
+
estCostUsd: null, keptRatios: [],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function evidenceOf(v) {
|
|
22
|
+
return v.evidence.map((e) => ({
|
|
23
|
+
sessionId: e.lesson.sessionId,
|
|
24
|
+
citeSlug: e.lesson.citeSlug,
|
|
25
|
+
project: e.lesson.project,
|
|
26
|
+
date: e.lesson.noteDate,
|
|
27
|
+
quote: e.quote,
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
function reconsider(cfg, db, slug, now) {
|
|
31
|
+
const row = db.getInsightBySlug(slug);
|
|
32
|
+
if (row === null)
|
|
33
|
+
throw new Error(`no rule with slug ${slug}`);
|
|
34
|
+
// Spec §9: the way back for a rejected or declined rule — never a silent
|
|
35
|
+
// demotion of one the owner accepted and promoted.
|
|
36
|
+
if (row.status !== "rejected" && row.promotion !== "declined") {
|
|
37
|
+
throw new Error(`only a rejected or declined rule can be reconsidered — ${slug} is ${row.status}`);
|
|
38
|
+
}
|
|
39
|
+
const next = {
|
|
40
|
+
...row,
|
|
41
|
+
status: "proposed",
|
|
42
|
+
promotion: "none",
|
|
43
|
+
evidenceChanged: false,
|
|
44
|
+
pending: null,
|
|
45
|
+
updatedAt: now.toISOString(),
|
|
46
|
+
};
|
|
47
|
+
db.upsertInsight(next);
|
|
48
|
+
writeInsightFile(vaultRoot(cfg), next);
|
|
49
|
+
return emptySummary();
|
|
50
|
+
}
|
|
51
|
+
// Find lessons the user keeps re-learning and propose them as cited rules.
|
|
52
|
+
// Paid: at most connectMaxCandidates LLM calls. Never run implicitly.
|
|
53
|
+
export async function runConnect(cfg, db, opts, deps) {
|
|
54
|
+
acquireLock(deps.lockPath);
|
|
55
|
+
try {
|
|
56
|
+
if (opts.reconsider !== undefined)
|
|
57
|
+
return reconsider(cfg, db, opts.reconsider, deps.now());
|
|
58
|
+
const provider = deps.provider;
|
|
59
|
+
if (provider === null)
|
|
60
|
+
throw new Error("clustering needs an embedding provider — run vir embed setup");
|
|
61
|
+
const summary = emptySummary();
|
|
62
|
+
const root = vaultRoot(cfg);
|
|
63
|
+
if (!opts.dryRun)
|
|
64
|
+
await backfillInsightEmbeddings(db, provider);
|
|
65
|
+
const lessons = collectLessons(root);
|
|
66
|
+
summary.lessons = lessons.length;
|
|
67
|
+
const vectors = await embedLessons(lessons, db, provider);
|
|
68
|
+
const { connectMinSim, connectCoreSim } = thresholdsFor(provider.modelName);
|
|
69
|
+
const clusters = clusterLessons(lessons, vectors, connectMinSim, connectCoreSim);
|
|
70
|
+
summary.clusters = clusters.length;
|
|
71
|
+
// Free pre-LLM triage: rejected stays rejected, and a known rule with no new
|
|
72
|
+
// session is unchanged — neither earns a paid call.
|
|
73
|
+
const insights = db.listInsights();
|
|
74
|
+
const todo = [];
|
|
75
|
+
for (const c of rankCandidates(clusters)) {
|
|
76
|
+
const hashes = c.members.map((m) => m.contentHash);
|
|
77
|
+
const pre = matchCandidate({ sessionIds: c.rec.sessions, hashes, ruleVector: null }, insights, new Map(), connectCoreSim);
|
|
78
|
+
if (pre.kind === "skip-rejected") {
|
|
79
|
+
summary.skippedRejected += 1;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (pre.kind === "accepted-unchanged") {
|
|
83
|
+
summary.unchanged += 1;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (pre.kind === "update-proposed" || pre.kind === "accepted-additions") {
|
|
87
|
+
// Sessions already flagged as pending additions are known too: the
|
|
88
|
+
// owner hasn't decided on them yet, so asking the model again is waste.
|
|
89
|
+
const known = new Set([
|
|
90
|
+
...pre.insight.memberSessionIds,
|
|
91
|
+
...(pre.insight.pending ?? []).map((e) => e.sessionId),
|
|
92
|
+
]);
|
|
93
|
+
if (c.rec.sessions.every((s) => known.has(s))) {
|
|
94
|
+
summary.unchanged += 1;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
todo.push(c);
|
|
99
|
+
}
|
|
100
|
+
summary.candidates = todo.length;
|
|
101
|
+
const batch = todo.slice(0, cfg.connectMaxCandidates);
|
|
102
|
+
summary.deferred = todo.length - batch.length;
|
|
103
|
+
if (opts.dryRun) {
|
|
104
|
+
let total = 0;
|
|
105
|
+
for (const c of batch) {
|
|
106
|
+
const cost = deps.estimateCostUsd(Math.ceil(buildVerifyPrompt(c.members).length / 4), VERIFY_OUTPUT_TOKENS);
|
|
107
|
+
total = cost === null || total === null ? null : total + cost;
|
|
108
|
+
}
|
|
109
|
+
summary.estCostUsd = total;
|
|
110
|
+
return summary;
|
|
111
|
+
}
|
|
112
|
+
const rejectedVectors = db.getInsightVectors("rejected");
|
|
113
|
+
for (const c of batch) {
|
|
114
|
+
summary.llmCalls += 1;
|
|
115
|
+
let text;
|
|
116
|
+
try {
|
|
117
|
+
text = await deps.llm(buildVerifyPrompt(c.members));
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
summary.llmFailures += 1;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const verdict = parseVerdict(text);
|
|
124
|
+
const v = verdict === null ? null : validateVerdict(c.members, verdict);
|
|
125
|
+
if (v === null) {
|
|
126
|
+
summary.unverified += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
summary.keptRatios.push(v.keptOfTotal);
|
|
130
|
+
const rec = recurrence(v.members);
|
|
131
|
+
const ruleVector = await embedNoteWithProvider(provider, `${v.rule}\n${v.why}`);
|
|
132
|
+
const outcome = matchCandidate({ sessionIds: rec.sessions, hashes: v.members.map((m) => m.contentHash), ruleVector }, db.listInsights(), rejectedVectors, connectCoreSim);
|
|
133
|
+
const now = deps.now().toISOString();
|
|
134
|
+
const evidence = evidenceOf(v);
|
|
135
|
+
const fields = {
|
|
136
|
+
memberSessionIds: rec.sessions,
|
|
137
|
+
memberHashes: v.members.map((m) => m.contentHash),
|
|
138
|
+
sources: [...new Set(evidence.map((e) => e.citeSlug))],
|
|
139
|
+
evidence,
|
|
140
|
+
sessions: rec.sessions.length,
|
|
141
|
+
projects: rec.projects,
|
|
142
|
+
firstSeen: rec.firstSeen,
|
|
143
|
+
lastSeen: rec.lastSeen,
|
|
144
|
+
};
|
|
145
|
+
if (outcome.kind === "skip-rejected") {
|
|
146
|
+
summary.skippedRejected += 1;
|
|
147
|
+
}
|
|
148
|
+
else if (outcome.kind === "accepted-unchanged") {
|
|
149
|
+
summary.unchanged += 1;
|
|
150
|
+
}
|
|
151
|
+
else if (outcome.kind === "accepted-additions") {
|
|
152
|
+
const added = new Set(outcome.addedSessions);
|
|
153
|
+
db.upsertInsight({
|
|
154
|
+
...outcome.insight,
|
|
155
|
+
evidenceChanged: true,
|
|
156
|
+
pending: evidence.filter((e) => added.has(e.sessionId)),
|
|
157
|
+
updatedAt: now,
|
|
158
|
+
});
|
|
159
|
+
summary.additionsFlagged += 1;
|
|
160
|
+
}
|
|
161
|
+
else if (outcome.kind === "update-proposed") {
|
|
162
|
+
const next = { ...outcome.insight, ...fields, scope: v.scope, updatedAt: now };
|
|
163
|
+
db.upsertInsight(next);
|
|
164
|
+
writeInsightFile(root, next);
|
|
165
|
+
summary.updated += 1;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const id = randomUUID();
|
|
169
|
+
const row = {
|
|
170
|
+
id,
|
|
171
|
+
slug: insightSlug(v.rule, id),
|
|
172
|
+
insightType: "recurring-rule",
|
|
173
|
+
status: "proposed",
|
|
174
|
+
promotion: "none",
|
|
175
|
+
scope: v.scope,
|
|
176
|
+
rule: v.rule,
|
|
177
|
+
why: v.why,
|
|
178
|
+
...fields,
|
|
179
|
+
evidenceChanged: false,
|
|
180
|
+
pending: null,
|
|
181
|
+
model: deps.model,
|
|
182
|
+
createdAt: now,
|
|
183
|
+
updatedAt: now,
|
|
184
|
+
};
|
|
185
|
+
db.upsertInsight(row);
|
|
186
|
+
if (ruleVector !== null) {
|
|
187
|
+
db.setInsightEmbedding(id, ruleVector, { model: provider.modelName, dim: ruleVector.length });
|
|
188
|
+
}
|
|
189
|
+
writeInsightFile(root, row);
|
|
190
|
+
summary.proposed += 1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return summary;
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
releaseLock(deps.lockPath);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/connect/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Rule and why text is model-written and owner-editable, then shown in the
|
|
2
|
+
// terminal for approval and written into CLAUDE.md, which agents read as
|
|
3
|
+
// instructions. One normalization, applied at every boundary, so what the
|
|
4
|
+
// owner judges is byte-for-byte what gets stored and written:
|
|
5
|
+
// - no C0/C1 control characters (ANSI escapes could hide or recolor text)
|
|
6
|
+
// - no bidi overrides/isolates (could reorder what the owner reads)
|
|
7
|
+
// - no HTML-comment syntax (no fake VIR markers or rule ids)
|
|
8
|
+
// - one line (no injected headings)
|
|
9
|
+
const CONTROL = /[\u0000-\u001f\u007f-\u009f]/g;
|
|
10
|
+
const BIDI = /[\u202a-\u202e\u2066-\u2069\u200e\u200f\u061c]/g;
|
|
11
|
+
export function ruleText(text) {
|
|
12
|
+
return text
|
|
13
|
+
.replace(/\r\n|\r|\n|\t/g, " ")
|
|
14
|
+
.replace(CONTROL, "")
|
|
15
|
+
.replace(BIDI, "")
|
|
16
|
+
.replace(/<!--|-->/g, " ")
|
|
17
|
+
.replace(/\s+/g, " ")
|
|
18
|
+
.trim();
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/connect/text.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,8DAA8D;AAC9D,2EAA2E;AAC3E,qEAAqE;AACrE,8DAA8D;AAC9D,qCAAqC;AACrC,MAAM,OAAO,GAAG,+BAA+B,CAAC;AAChD,MAAM,IAAI,GAAG,iDAAiD,CAAC;AAE/D,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI;SACR,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;SACjB,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;SACzB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/connect/types.ts"],"names":[],"mappings":""}
|