@codacy/verity-cli 0.32.6-experimental.833e71a → 0.32.6-experimental.8f2b5f7
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/bin/verity.js +546 -933
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -13846,206 +13846,14 @@ async function appendEntry(taskId, entry) {
|
|
|
13846
13846
|
}
|
|
13847
13847
|
|
|
13848
13848
|
// src/lib/memory-retrieval.ts
|
|
13849
|
-
var import_promises8 = require("node:fs/promises");
|
|
13850
|
-
var import_node_fs11 = require("node:fs");
|
|
13851
|
-
var import_node_path11 = require("node:path");
|
|
13852
|
-
|
|
13853
|
-
// src/lib/org-mirror.ts
|
|
13854
|
-
var import_node_fs10 = require("node:fs");
|
|
13855
13849
|
var import_promises7 = require("node:fs/promises");
|
|
13850
|
+
var import_node_fs10 = require("node:fs");
|
|
13856
13851
|
var import_node_path10 = require("node:path");
|
|
13857
|
-
var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
|
|
13858
|
-
var STATE_FILE = ".org-pull-state.json";
|
|
13859
|
-
var BODY_MAX = 8192;
|
|
13860
|
-
function orgMirrorDir(remote = requestRemote()) {
|
|
13861
|
-
const parsed = parseRemote(remote);
|
|
13862
|
-
if (!parsed) return null;
|
|
13863
|
-
return (0, import_node_path10.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
|
|
13864
|
-
}
|
|
13865
|
-
function slugify(s) {
|
|
13866
|
-
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
13867
|
-
}
|
|
13868
|
-
function orgNodePath(node) {
|
|
13869
|
-
const kind = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
|
|
13870
|
-
return `${kind}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
|
|
13871
|
-
}
|
|
13872
|
-
function renderOrgNode(node, orgName) {
|
|
13873
|
-
const fm = [
|
|
13874
|
-
"---",
|
|
13875
|
-
`id: ${JSON.stringify(node.tag_id)}`,
|
|
13876
|
-
`node_id: ${JSON.stringify(node.node_id)}`,
|
|
13877
|
-
'scope: "org"',
|
|
13878
|
-
`org: ${JSON.stringify(orgName)}`,
|
|
13879
|
-
`kind: ${JSON.stringify(node.kind)}`,
|
|
13880
|
-
`title: ${JSON.stringify(node.title)}`,
|
|
13881
|
-
`origin: ${JSON.stringify(node.origin)}`,
|
|
13882
|
-
`signal: ${JSON.stringify(node.signal)}`,
|
|
13883
|
-
`tier: ${node.tier === null ? "null" : JSON.stringify(node.tier)}`,
|
|
13884
|
-
`applies_to: ${JSON.stringify(node.applies_to)}`,
|
|
13885
|
-
`source_repo_count: ${JSON.stringify(node.source_repo_count)}`,
|
|
13886
|
-
`promoted_at: ${JSON.stringify(node.promoted_at)}`,
|
|
13887
|
-
'status: "active"',
|
|
13888
|
-
"---"
|
|
13889
|
-
];
|
|
13890
|
-
return `${fm.join("\n")}
|
|
13891
|
-
|
|
13892
|
-
# ${node.title}
|
|
13893
|
-
|
|
13894
|
-
${node.body.trim()}
|
|
13895
|
-
`;
|
|
13896
|
-
}
|
|
13897
|
-
function parseOrgNode(content) {
|
|
13898
|
-
const m = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
13899
|
-
if (!m) return null;
|
|
13900
|
-
const fm = {};
|
|
13901
|
-
for (const line of m[1].split("\n")) {
|
|
13902
|
-
const kv = line.match(/^([a-z_]+):\s*(.*)$/);
|
|
13903
|
-
if (!kv) continue;
|
|
13904
|
-
try {
|
|
13905
|
-
fm[kv[1]] = JSON.parse(kv[2]);
|
|
13906
|
-
} catch {
|
|
13907
|
-
fm[kv[1]] = kv[2];
|
|
13908
|
-
}
|
|
13909
|
-
}
|
|
13910
|
-
if (fm.scope !== "org" || typeof fm.id !== "string" || typeof fm.title !== "string") return null;
|
|
13911
|
-
if (fm.status && fm.status !== "active") return null;
|
|
13912
|
-
const body = m[2].replace(/^\s*#[^\n]*\n/, "").trim();
|
|
13913
|
-
return {
|
|
13914
|
-
tag_id: fm.id,
|
|
13915
|
-
node_id: typeof fm.node_id === "string" ? fm.node_id : "",
|
|
13916
|
-
kind: typeof fm.kind === "string" ? fm.kind : "domain",
|
|
13917
|
-
title: fm.title,
|
|
13918
|
-
body,
|
|
13919
|
-
origin: typeof fm.origin === "string" ? fm.origin : "",
|
|
13920
|
-
signal: typeof fm.signal === "string" ? fm.signal : "",
|
|
13921
|
-
tier: typeof fm.tier === "number" ? fm.tier : null,
|
|
13922
|
-
applies_to: Array.isArray(fm.applies_to) ? fm.applies_to.filter((v) => typeof v === "string") : [],
|
|
13923
|
-
source_repo_count: typeof fm.source_repo_count === "number" ? fm.source_repo_count : 1,
|
|
13924
|
-
promoted_at: typeof fm.promoted_at === "string" ? fm.promoted_at : ""
|
|
13925
|
-
};
|
|
13926
|
-
}
|
|
13927
|
-
async function readState(dir) {
|
|
13928
|
-
try {
|
|
13929
|
-
const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path10.join)(dir, STATE_FILE), "utf-8"));
|
|
13930
|
-
return {
|
|
13931
|
-
version: typeof parsed?.version === "string" ? parsed.version : null,
|
|
13932
|
-
organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
|
|
13933
|
-
files: Array.isArray(parsed?.files) ? parsed.files.filter((f) => typeof f === "string") : []
|
|
13934
|
-
};
|
|
13935
|
-
} catch {
|
|
13936
|
-
return { version: null, organization: null, files: [] };
|
|
13937
|
-
}
|
|
13938
|
-
}
|
|
13939
|
-
async function writeState(dir, state) {
|
|
13940
|
-
await (0, import_promises7.mkdir)(dir, { recursive: true });
|
|
13941
|
-
await (0, import_promises7.writeFile)((0, import_node_path10.join)(dir, STATE_FILE), JSON.stringify({
|
|
13942
|
-
...state.version ? { version: state.version } : {},
|
|
13943
|
-
organization: state.organization,
|
|
13944
|
-
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13945
|
-
files: state.files
|
|
13946
|
-
}, null, 2) + "\n");
|
|
13947
|
-
}
|
|
13948
|
-
function renderIndex(orgName, nodes) {
|
|
13949
|
-
const lines = [
|
|
13950
|
-
`# Org Knowledge \u2014 ${orgName}`,
|
|
13951
|
-
"",
|
|
13952
|
-
"*Auto-generated by verity CLI from what this organization's repositories learned. Do not hand-edit; `verity memory pull` overwrites it.*",
|
|
13953
|
-
"",
|
|
13954
|
-
'> These claims hold across the organization\'s repositories, not only this one. Each names where it came from. A claim that is wrong for this repository is demoted with `verity memory demote <id> --reason "\u2026"`, for everyone.',
|
|
13955
|
-
""
|
|
13956
|
-
];
|
|
13957
|
-
const byKind = /* @__PURE__ */ new Map();
|
|
13958
|
-
for (const n of nodes) byKind.set(n.kind, [...byKind.get(n.kind) ?? [], n]);
|
|
13959
|
-
for (const kind of ORG_KINDS) {
|
|
13960
|
-
const list2 = byKind.get(kind);
|
|
13961
|
-
if (!list2?.length) continue;
|
|
13962
|
-
lines.push(`## ${kind}/ (${list2.length})`);
|
|
13963
|
-
for (const n of list2) lines.push(`- [[${orgNodePath(n).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n.title} \xB7 ${n.origin}`);
|
|
13964
|
-
lines.push("");
|
|
13965
|
-
}
|
|
13966
|
-
if (nodes.length === 0) lines.push("No org knowledge yet.", "");
|
|
13967
|
-
return lines.join("\n");
|
|
13968
|
-
}
|
|
13969
|
-
async function pullOrgKnowledge(opts) {
|
|
13970
|
-
const dir = orgMirrorDir(opts.remote ?? requestRemote());
|
|
13971
|
-
if (!dir) return { ok: true, status: "no_remote", received: 0, dir: null };
|
|
13972
|
-
const state = await readState(dir);
|
|
13973
|
-
const params = new URLSearchParams({ for: "agent" });
|
|
13974
|
-
if (!opts.force && state.version) params.set("if_version", state.version);
|
|
13975
|
-
const res = await apiRequest({
|
|
13976
|
-
method: "GET",
|
|
13977
|
-
path: `/memory/org?${params.toString()}`,
|
|
13978
|
-
serviceUrl: opts.serviceUrl,
|
|
13979
|
-
token: opts.token,
|
|
13980
|
-
verbose: opts.verbose,
|
|
13981
|
-
timeout: opts.timeoutMs ?? 3e4,
|
|
13982
|
-
cmd: "memory-org-pull"
|
|
13983
|
-
});
|
|
13984
|
-
if (!res.ok) return { ok: false, error: res.error, category: res.category };
|
|
13985
|
-
const page = res.data;
|
|
13986
|
-
if (page.unchanged) return { ok: true, status: "unchanged", received: 0, dir };
|
|
13987
|
-
const org = page.organization;
|
|
13988
|
-
const nodes = org ? (page.nodes ?? []).flatMap((n) => typeof n.tag_id === "string" && typeof n.title === "string" && typeof n.body === "string" ? [{
|
|
13989
|
-
tag_id: n.tag_id,
|
|
13990
|
-
node_id: typeof n.node_id === "string" ? n.node_id : "",
|
|
13991
|
-
kind: typeof n.kind === "string" ? n.kind : "domain",
|
|
13992
|
-
title: n.title,
|
|
13993
|
-
body: n.body.slice(0, BODY_MAX),
|
|
13994
|
-
origin: typeof n.origin === "string" ? n.origin : "",
|
|
13995
|
-
signal: typeof n.signal === "string" ? n.signal : "",
|
|
13996
|
-
tier: typeof n.tier === "number" ? n.tier : null,
|
|
13997
|
-
applies_to: Array.isArray(n.applies_to) ? n.applies_to.filter((v) => typeof v === "string") : [],
|
|
13998
|
-
source_repo_count: typeof n.source_repo_count === "number" ? n.source_repo_count : 1,
|
|
13999
|
-
promoted_at: typeof n.promoted_at === "string" ? n.promoted_at : ""
|
|
14000
|
-
}] : []) : [];
|
|
14001
|
-
const written = /* @__PURE__ */ new Set();
|
|
14002
|
-
await (0, import_promises7.mkdir)(dir, { recursive: true });
|
|
14003
|
-
for (const n of nodes) {
|
|
14004
|
-
const rel = orgNodePath(n);
|
|
14005
|
-
if (written.has(rel)) continue;
|
|
14006
|
-
await (0, import_promises7.mkdir)((0, import_node_path10.join)(dir, rel.split("/")[0]), { recursive: true });
|
|
14007
|
-
await (0, import_promises7.writeFile)((0, import_node_path10.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
|
|
14008
|
-
written.add(rel);
|
|
14009
|
-
}
|
|
14010
|
-
for (const rel of state.files) {
|
|
14011
|
-
if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path10.join)(dir, rel), { force: true });
|
|
14012
|
-
}
|
|
14013
|
-
await (0, import_promises7.writeFile)((0, import_node_path10.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
|
|
14014
|
-
await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
|
|
14015
|
-
return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
|
|
14016
|
-
}
|
|
14017
|
-
async function readOrgMirror(remote = requestRemote()) {
|
|
14018
|
-
const dir = orgMirrorDir(remote);
|
|
14019
|
-
if (!dir || !(0, import_node_fs10.existsSync)(dir)) return [];
|
|
14020
|
-
const out = [];
|
|
14021
|
-
for (const kind of ORG_KINDS) {
|
|
14022
|
-
const kindDir = (0, import_node_path10.join)(dir, kind);
|
|
14023
|
-
if (!(0, import_node_fs10.existsSync)(kindDir)) continue;
|
|
14024
|
-
let files;
|
|
14025
|
-
try {
|
|
14026
|
-
files = await (0, import_promises7.readdir)(kindDir);
|
|
14027
|
-
} catch {
|
|
14028
|
-
continue;
|
|
14029
|
-
}
|
|
14030
|
-
for (const file of files) {
|
|
14031
|
-
if (!file.endsWith(".md")) continue;
|
|
14032
|
-
try {
|
|
14033
|
-
const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path10.join)(kindDir, file), "utf-8"));
|
|
14034
|
-
if (node) out.push(node);
|
|
14035
|
-
} catch {
|
|
14036
|
-
}
|
|
14037
|
-
}
|
|
14038
|
-
}
|
|
14039
|
-
return out;
|
|
14040
|
-
}
|
|
14041
|
-
|
|
14042
|
-
// src/lib/memory-retrieval.ts
|
|
14043
13852
|
var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
|
|
14044
13853
|
var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
|
|
14045
13854
|
var DEFAULT_BUDGET_TOKENS = 2e3;
|
|
14046
13855
|
var MAX_BUDGET_TOKENS = 4e3;
|
|
14047
13856
|
var MIN_SCORE = 0.5;
|
|
14048
|
-
var ORG_MIN_SHARED_TERMS = 2;
|
|
14049
13857
|
function tokenize(text) {
|
|
14050
13858
|
return new Set(
|
|
14051
13859
|
text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
|
|
@@ -14058,26 +13866,6 @@ function jaccardKeywords(a, b) {
|
|
|
14058
13866
|
const union = a.size + b.size - inter;
|
|
14059
13867
|
return union === 0 ? 0 : inter / union;
|
|
14060
13868
|
}
|
|
14061
|
-
function sharedTerms(a, b) {
|
|
14062
|
-
let n = 0;
|
|
14063
|
-
for (const w of a) if (b.has(w)) n++;
|
|
14064
|
-
return n;
|
|
14065
|
-
}
|
|
14066
|
-
function orgNodeToLocal(n) {
|
|
14067
|
-
return {
|
|
14068
|
-
path: `org:${n.tag_id}`,
|
|
14069
|
-
nodeId: n.tag_id,
|
|
14070
|
-
kind: n.kind,
|
|
14071
|
-
title: n.title,
|
|
14072
|
-
body: n.body.slice(0, 2e3),
|
|
14073
|
-
fileGlobs: [],
|
|
14074
|
-
confidence: 0.5,
|
|
14075
|
-
citedCount: 0,
|
|
14076
|
-
tokenEstimate: Math.ceil((n.title.length + n.body.length) / 4) + 20,
|
|
14077
|
-
scope: "org",
|
|
14078
|
-
origin: n.origin
|
|
14079
|
-
};
|
|
14080
|
-
}
|
|
14081
13869
|
function globMatch(glob, filePath) {
|
|
14082
13870
|
if (glob === filePath) return true;
|
|
14083
13871
|
const suffixMatch = glob.match(/^\*\*\/\*(.+)$/);
|
|
@@ -14153,19 +13941,19 @@ function parseFrontmatter(content) {
|
|
|
14153
13941
|
return { fm, body: match[2].trim() };
|
|
14154
13942
|
}
|
|
14155
13943
|
async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
|
|
14156
|
-
|
|
13944
|
+
if (!(0, import_node_fs10.existsSync)(memoryDir())) return null;
|
|
14157
13945
|
const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
|
|
14158
13946
|
const promptTokens = tokenize(promptText);
|
|
14159
13947
|
const nodes = [];
|
|
14160
|
-
for (const domain of
|
|
14161
|
-
const domainDir = (0,
|
|
14162
|
-
if (!(0,
|
|
13948
|
+
for (const domain of DOMAINS) {
|
|
13949
|
+
const domainDir = (0, import_node_path10.join)(memoryDir(), domain);
|
|
13950
|
+
if (!(0, import_node_fs10.existsSync)(domainDir)) continue;
|
|
14163
13951
|
try {
|
|
14164
|
-
const files = await (0,
|
|
13952
|
+
const files = await (0, import_promises7.readdir)(domainDir);
|
|
14165
13953
|
for (const file of files) {
|
|
14166
13954
|
if (!file.endsWith(".md")) continue;
|
|
14167
13955
|
try {
|
|
14168
|
-
const content = await (0,
|
|
13956
|
+
const content = await (0, import_promises7.readFile)((0, import_node_path10.join)(domainDir, file), "utf-8");
|
|
14169
13957
|
const { fm, body } = parseFrontmatter(content);
|
|
14170
13958
|
if (fm.status && fm.status !== "active") continue;
|
|
14171
13959
|
nodes.push({
|
|
@@ -14185,13 +13973,6 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
14185
13973
|
} catch {
|
|
14186
13974
|
}
|
|
14187
13975
|
}
|
|
14188
|
-
try {
|
|
14189
|
-
for (const claim of await readOrgMirror()) {
|
|
14190
|
-
const local = orgNodeToLocal(claim);
|
|
14191
|
-
if (sharedTerms(tokenize(`${local.title} ${local.body}`), promptTokens) >= ORG_MIN_SHARED_TERMS) nodes.push(local);
|
|
14192
|
-
}
|
|
14193
|
-
} catch {
|
|
14194
|
-
}
|
|
14195
13976
|
if (nodes.length === 0) return null;
|
|
14196
13977
|
const scored = nodes.map((n) => ({
|
|
14197
13978
|
...n,
|
|
@@ -14210,13 +13991,12 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
14210
13991
|
const lines = [
|
|
14211
13992
|
"## Project Knowledge (auto-injected)",
|
|
14212
13993
|
"",
|
|
14213
|
-
`*${selected.length} node(s) relevant to your current task. See \`.verity/memory/index.md\` for the full knowledge base
|
|
13994
|
+
`*${selected.length} node(s) relevant to your current task. See \`.verity/memory/index.md\` for the full knowledge base.*`,
|
|
14214
13995
|
""
|
|
14215
13996
|
];
|
|
14216
13997
|
for (const node of selected) {
|
|
14217
13998
|
lines.push(`### ${node.title}`);
|
|
14218
|
-
|
|
14219
|
-
else lines.push(`*${node.kind}* \xB7 confidence ${Math.round(node.confidence * 100)}%`);
|
|
13999
|
+
lines.push(`*${node.kind}* \xB7 confidence ${Math.round(node.confidence * 100)}%`);
|
|
14220
14000
|
lines.push("");
|
|
14221
14001
|
lines.push(node.body.slice(0, 800));
|
|
14222
14002
|
lines.push("");
|
|
@@ -14231,14 +14011,14 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
14231
14011
|
}
|
|
14232
14012
|
|
|
14233
14013
|
// src/lib/memory-sync.ts
|
|
14234
|
-
var
|
|
14235
|
-
var
|
|
14236
|
-
var
|
|
14014
|
+
var import_promises8 = require("node:fs/promises");
|
|
14015
|
+
var import_node_fs13 = require("node:fs");
|
|
14016
|
+
var import_node_path12 = require("node:path");
|
|
14237
14017
|
var import_node_crypto3 = require("node:crypto");
|
|
14238
14018
|
|
|
14239
14019
|
// src/lib/gitignore.ts
|
|
14240
14020
|
var import_node_child_process6 = require("node:child_process");
|
|
14241
|
-
var
|
|
14021
|
+
var import_node_fs11 = require("node:fs");
|
|
14242
14022
|
var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
|
|
14243
14023
|
var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
|
|
14244
14024
|
var VERITY_GITIGNORE_BLOCK = [
|
|
@@ -14322,7 +14102,7 @@ function fenceMemoryLines(lines) {
|
|
|
14322
14102
|
function ensureVerityGitignore() {
|
|
14323
14103
|
let content = "";
|
|
14324
14104
|
try {
|
|
14325
|
-
content = (0,
|
|
14105
|
+
content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
|
|
14326
14106
|
} catch {
|
|
14327
14107
|
}
|
|
14328
14108
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -14349,7 +14129,7 @@ function ensureVerityGitignore() {
|
|
|
14349
14129
|
const sep4 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
14350
14130
|
text = text + sep4 + VERITY_GITIGNORE_BLOCK;
|
|
14351
14131
|
}
|
|
14352
|
-
if (text !== content) (0,
|
|
14132
|
+
if (text !== content) (0, import_node_fs11.writeFileSync)(".gitignore", text);
|
|
14353
14133
|
return verified(
|
|
14354
14134
|
memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
|
|
14355
14135
|
);
|
|
@@ -14369,7 +14149,7 @@ function untrackMemory() {
|
|
|
14369
14149
|
function writeFencedBlock() {
|
|
14370
14150
|
let content = "";
|
|
14371
14151
|
try {
|
|
14372
|
-
content = (0,
|
|
14152
|
+
content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
|
|
14373
14153
|
} catch {
|
|
14374
14154
|
}
|
|
14375
14155
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -14381,7 +14161,7 @@ function writeFencedBlock() {
|
|
|
14381
14161
|
text = text + sep4 + VERITY_GITIGNORE_BLOCK;
|
|
14382
14162
|
}
|
|
14383
14163
|
try {
|
|
14384
|
-
(0,
|
|
14164
|
+
(0, import_node_fs11.writeFileSync)(".gitignore", text);
|
|
14385
14165
|
return true;
|
|
14386
14166
|
} catch {
|
|
14387
14167
|
return false;
|
|
@@ -14390,14 +14170,14 @@ function writeFencedBlock() {
|
|
|
14390
14170
|
function fenceMemory() {
|
|
14391
14171
|
let original = null;
|
|
14392
14172
|
try {
|
|
14393
|
-
original = (0,
|
|
14173
|
+
original = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
|
|
14394
14174
|
} catch {
|
|
14395
14175
|
original = null;
|
|
14396
14176
|
}
|
|
14397
14177
|
const restore = () => {
|
|
14398
14178
|
try {
|
|
14399
|
-
if (original === null) (0,
|
|
14400
|
-
else (0,
|
|
14179
|
+
if (original === null) (0, import_node_fs11.rmSync)(".gitignore", { force: true });
|
|
14180
|
+
else (0, import_node_fs11.writeFileSync)(".gitignore", original);
|
|
14401
14181
|
} catch {
|
|
14402
14182
|
}
|
|
14403
14183
|
};
|
|
@@ -14415,7 +14195,7 @@ function fenceMemory() {
|
|
|
14415
14195
|
}
|
|
14416
14196
|
function memoryOptOut() {
|
|
14417
14197
|
try {
|
|
14418
|
-
return (0,
|
|
14198
|
+
return (0, import_node_fs11.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
|
|
14419
14199
|
} catch {
|
|
14420
14200
|
return false;
|
|
14421
14201
|
}
|
|
@@ -14423,13 +14203,13 @@ function memoryOptOut() {
|
|
|
14423
14203
|
function keepMemoryTracked() {
|
|
14424
14204
|
let content = "";
|
|
14425
14205
|
try {
|
|
14426
|
-
content = (0,
|
|
14206
|
+
content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
|
|
14427
14207
|
} catch {
|
|
14428
14208
|
}
|
|
14429
14209
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
14430
14210
|
try {
|
|
14431
14211
|
const sep4 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
14432
|
-
(0,
|
|
14212
|
+
(0, import_node_fs11.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
|
|
14433
14213
|
} catch {
|
|
14434
14214
|
return "failed";
|
|
14435
14215
|
}
|
|
@@ -14464,26 +14244,26 @@ function untrackVerityState() {
|
|
|
14464
14244
|
}
|
|
14465
14245
|
|
|
14466
14246
|
// src/lib/safe-path.ts
|
|
14467
|
-
var
|
|
14468
|
-
var
|
|
14247
|
+
var import_node_fs12 = require("node:fs");
|
|
14248
|
+
var import_node_path11 = require("node:path");
|
|
14469
14249
|
function resolveInside(baseDir, candidate) {
|
|
14470
14250
|
if (typeof candidate !== "string" || candidate.length === 0) return null;
|
|
14471
|
-
if ((0,
|
|
14472
|
-
const baseAbs = (0,
|
|
14473
|
-
const full = (0,
|
|
14474
|
-
const baseSep = baseAbs.endsWith(
|
|
14251
|
+
if ((0, import_node_path11.isAbsolute)(candidate)) return null;
|
|
14252
|
+
const baseAbs = (0, import_node_path11.resolve)(baseDir);
|
|
14253
|
+
const full = (0, import_node_path11.resolve)(baseAbs, candidate);
|
|
14254
|
+
const baseSep = baseAbs.endsWith(import_node_path11.sep) ? baseAbs : baseAbs + import_node_path11.sep;
|
|
14475
14255
|
if (full !== baseAbs && !full.startsWith(baseSep)) return null;
|
|
14476
14256
|
try {
|
|
14477
|
-
if ((0,
|
|
14478
|
-
const realBase = (0,
|
|
14479
|
-
const realBaseSep = realBase.endsWith(
|
|
14257
|
+
if ((0, import_node_fs12.existsSync)(baseAbs)) {
|
|
14258
|
+
const realBase = (0, import_node_fs12.realpathSync)(baseAbs);
|
|
14259
|
+
const realBaseSep = realBase.endsWith(import_node_path11.sep) ? realBase : realBase + import_node_path11.sep;
|
|
14480
14260
|
let probe = full;
|
|
14481
|
-
while (!(0,
|
|
14482
|
-
const parent = (0,
|
|
14261
|
+
while (!(0, import_node_fs12.existsSync)(probe)) {
|
|
14262
|
+
const parent = (0, import_node_path11.dirname)(probe);
|
|
14483
14263
|
if (parent === probe) break;
|
|
14484
14264
|
probe = parent;
|
|
14485
14265
|
}
|
|
14486
|
-
const realProbe = (0,
|
|
14266
|
+
const realProbe = (0, import_node_fs12.realpathSync)(probe);
|
|
14487
14267
|
if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
|
|
14488
14268
|
}
|
|
14489
14269
|
} catch {
|
|
@@ -14566,36 +14346,36 @@ var memoryDir2 = () => projectPath(`${VERITY_DIR}/memory`);
|
|
|
14566
14346
|
var DOMAINS2 = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations", "_archive"];
|
|
14567
14347
|
var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
14568
14348
|
async function ensureMemoryDir() {
|
|
14569
|
-
await (0,
|
|
14349
|
+
await (0, import_promises8.mkdir)(memoryDir2(), { recursive: true });
|
|
14570
14350
|
for (const domain of DOMAINS2) {
|
|
14571
|
-
await (0,
|
|
14351
|
+
await (0, import_promises8.mkdir)((0, import_node_path12.join)(memoryDir2(), domain), { recursive: true });
|
|
14572
14352
|
}
|
|
14573
|
-
if (!(0,
|
|
14574
|
-
await (0,
|
|
14353
|
+
if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
14354
|
+
await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
14575
14355
|
}
|
|
14576
|
-
if (!(0,
|
|
14577
|
-
await (0,
|
|
14356
|
+
if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "index.md"))) {
|
|
14357
|
+
await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
14578
14358
|
}
|
|
14579
|
-
if (!(0,
|
|
14580
|
-
await (0,
|
|
14359
|
+
if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md"))) {
|
|
14360
|
+
await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
14581
14361
|
}
|
|
14582
14362
|
}
|
|
14583
14363
|
async function buildManifest() {
|
|
14584
|
-
if (!(0,
|
|
14364
|
+
if (!(0, import_node_fs13.existsSync)(memoryDir2())) {
|
|
14585
14365
|
return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
|
|
14586
14366
|
}
|
|
14587
14367
|
const nodes = [];
|
|
14588
14368
|
for (const domain of DOMAINS2) {
|
|
14589
|
-
const domainDir = (0,
|
|
14590
|
-
if (!(0,
|
|
14369
|
+
const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
|
|
14370
|
+
if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
|
|
14591
14371
|
try {
|
|
14592
|
-
const files = await (0,
|
|
14372
|
+
const files = await (0, import_promises8.readdir)(domainDir);
|
|
14593
14373
|
for (const file of files) {
|
|
14594
14374
|
if (!file.endsWith(".md")) continue;
|
|
14595
14375
|
const filePath = `${domain}/${file}`;
|
|
14596
|
-
const fullPath = (0,
|
|
14376
|
+
const fullPath = (0, import_node_path12.join)(memoryDir2(), filePath);
|
|
14597
14377
|
try {
|
|
14598
|
-
const content = await (0,
|
|
14378
|
+
const content = await (0, import_promises8.readFile)(fullPath, "utf-8");
|
|
14599
14379
|
const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
14600
14380
|
nodes.push({ path: filePath, content_hash: `sha256:${hash}` });
|
|
14601
14381
|
} catch {
|
|
@@ -14606,13 +14386,13 @@ async function buildManifest() {
|
|
|
14606
14386
|
}
|
|
14607
14387
|
let indexHash = null;
|
|
14608
14388
|
try {
|
|
14609
|
-
const indexContent = await (0,
|
|
14389
|
+
const indexContent = await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "index.md"), "utf-8");
|
|
14610
14390
|
indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
14611
14391
|
} catch {
|
|
14612
14392
|
}
|
|
14613
14393
|
let logLength = 0;
|
|
14614
14394
|
try {
|
|
14615
|
-
const logContent = await (0,
|
|
14395
|
+
const logContent = await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "utf-8");
|
|
14616
14396
|
logLength = logContent.split("\n").length;
|
|
14617
14397
|
} catch {
|
|
14618
14398
|
}
|
|
@@ -14623,15 +14403,15 @@ function hashContent(content) {
|
|
|
14623
14403
|
}
|
|
14624
14404
|
async function readOnDiskNodes() {
|
|
14625
14405
|
const out = /* @__PURE__ */ new Map();
|
|
14626
|
-
if (!(0,
|
|
14406
|
+
if (!(0, import_node_fs13.existsSync)(memoryDir2())) return out;
|
|
14627
14407
|
for (const domain of DOMAINS2) {
|
|
14628
|
-
const domainDir = (0,
|
|
14629
|
-
if (!(0,
|
|
14408
|
+
const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
|
|
14409
|
+
if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
|
|
14630
14410
|
try {
|
|
14631
|
-
for (const file of await (0,
|
|
14411
|
+
for (const file of await (0, import_promises8.readdir)(domainDir)) {
|
|
14632
14412
|
if (!file.endsWith(".md")) continue;
|
|
14633
14413
|
try {
|
|
14634
|
-
out.set(`${domain}/${file}`, hashContent(await (0,
|
|
14414
|
+
out.set(`${domain}/${file}`, hashContent(await (0, import_promises8.readFile)((0, import_node_path12.join)(domainDir, file), "utf-8")));
|
|
14635
14415
|
} catch {
|
|
14636
14416
|
}
|
|
14637
14417
|
}
|
|
@@ -14643,7 +14423,7 @@ async function readOnDiskNodes() {
|
|
|
14643
14423
|
async function readSyncBaseline() {
|
|
14644
14424
|
const out = /* @__PURE__ */ new Map();
|
|
14645
14425
|
try {
|
|
14646
|
-
const parsed = JSON.parse(await (0,
|
|
14426
|
+
const parsed = JSON.parse(await (0, import_promises8.readFile)(syncStateFile(), "utf-8"));
|
|
14647
14427
|
if (Array.isArray(parsed?.nodes)) {
|
|
14648
14428
|
for (const n of parsed.nodes) if (n?.path) out.set(n.path, n.hash ?? null);
|
|
14649
14429
|
} else if (Array.isArray(parsed?.paths)) {
|
|
@@ -14659,7 +14439,7 @@ async function recordSyncedNodePaths() {
|
|
|
14659
14439
|
const next = JSON.stringify({ schema: 2, nodes }) + "\n";
|
|
14660
14440
|
let existing = "";
|
|
14661
14441
|
try {
|
|
14662
|
-
existing = await (0,
|
|
14442
|
+
existing = await (0, import_promises8.readFile)(syncStateFile(), "utf-8");
|
|
14663
14443
|
} catch {
|
|
14664
14444
|
}
|
|
14665
14445
|
if (existing === next) return;
|
|
@@ -14668,10 +14448,10 @@ async function recordSyncedNodePaths() {
|
|
|
14668
14448
|
}
|
|
14669
14449
|
}
|
|
14670
14450
|
async function writeFileAtomic(path, content) {
|
|
14671
|
-
await (0,
|
|
14451
|
+
await (0, import_promises8.mkdir)((0, import_node_path12.dirname)(path), { recursive: true });
|
|
14672
14452
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
14673
|
-
await (0,
|
|
14674
|
-
await (0,
|
|
14453
|
+
await (0, import_promises8.writeFile)(tmp, content);
|
|
14454
|
+
await (0, import_promises8.rename)(tmp, path);
|
|
14675
14455
|
}
|
|
14676
14456
|
async function recordSyncBaseline() {
|
|
14677
14457
|
await recordSyncedNodePaths();
|
|
@@ -14682,11 +14462,11 @@ async function computeEditedNodeUploads() {
|
|
|
14682
14462
|
const uploads = [];
|
|
14683
14463
|
for (const [path, prevHash] of prev) {
|
|
14684
14464
|
if (prevHash == null) continue;
|
|
14685
|
-
const full = (0,
|
|
14686
|
-
if (!(0,
|
|
14465
|
+
const full = (0, import_node_path12.join)(memoryDir2(), path);
|
|
14466
|
+
if (!(0, import_node_fs13.existsSync)(full)) continue;
|
|
14687
14467
|
let content;
|
|
14688
14468
|
try {
|
|
14689
|
-
content = await (0,
|
|
14469
|
+
content = await (0, import_promises8.readFile)(full, "utf-8");
|
|
14690
14470
|
} catch {
|
|
14691
14471
|
continue;
|
|
14692
14472
|
}
|
|
@@ -14727,8 +14507,8 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
14727
14507
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
14728
14508
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
14729
14509
|
try {
|
|
14730
|
-
const existing = (0,
|
|
14731
|
-
await (0,
|
|
14510
|
+
const existing = (0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
14511
|
+
await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
14732
14512
|
} catch {
|
|
14733
14513
|
}
|
|
14734
14514
|
if (opts.baseline === "written") await mergeSyncBaseline(synced);
|
|
@@ -14738,9 +14518,9 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
14738
14518
|
async function mergeSyncBaseline(entries) {
|
|
14739
14519
|
if (entries.size === 0) return;
|
|
14740
14520
|
try {
|
|
14741
|
-
if ((0,
|
|
14521
|
+
if ((0, import_node_fs13.existsSync)(syncStateFile())) {
|
|
14742
14522
|
try {
|
|
14743
|
-
JSON.parse(await (0,
|
|
14523
|
+
JSON.parse(await (0, import_promises8.readFile)(syncStateFile(), "utf-8"));
|
|
14744
14524
|
} catch {
|
|
14745
14525
|
return;
|
|
14746
14526
|
}
|
|
@@ -14766,10 +14546,10 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
14766
14546
|
notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
|
|
14767
14547
|
}
|
|
14768
14548
|
}
|
|
14769
|
-
if ((0,
|
|
14549
|
+
if ((0, import_node_fs13.existsSync)(fullPath)) {
|
|
14770
14550
|
let existing = "";
|
|
14771
14551
|
try {
|
|
14772
|
-
existing = await (0,
|
|
14552
|
+
existing = await (0, import_promises8.readFile)(fullPath, "utf-8");
|
|
14773
14553
|
} catch {
|
|
14774
14554
|
}
|
|
14775
14555
|
if (existing === content) return { written: false, syncedHash: hashContent(content), notes };
|
|
@@ -14782,8 +14562,8 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
14782
14562
|
notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
|
|
14783
14563
|
}
|
|
14784
14564
|
}
|
|
14785
|
-
await (0,
|
|
14786
|
-
await (0,
|
|
14565
|
+
await (0, import_promises8.mkdir)((0, import_node_path12.dirname)(fullPath), { recursive: true });
|
|
14566
|
+
await (0, import_promises8.writeFile)(fullPath, content);
|
|
14787
14567
|
return { written: true, syncedHash: hashContent(content), notes };
|
|
14788
14568
|
}
|
|
14789
14569
|
function groundFileGlobs(content, treePaths) {
|
|
@@ -14823,10 +14603,10 @@ async function regenerateIndex() {
|
|
|
14823
14603
|
];
|
|
14824
14604
|
let totalNodes = 0;
|
|
14825
14605
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
14826
|
-
const domainDir = (0,
|
|
14827
|
-
if (!(0,
|
|
14606
|
+
const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
|
|
14607
|
+
if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
|
|
14828
14608
|
try {
|
|
14829
|
-
const files = await (0,
|
|
14609
|
+
const files = await (0, import_promises8.readdir)(domainDir);
|
|
14830
14610
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
14831
14611
|
if (mdFiles.length === 0) continue;
|
|
14832
14612
|
lines.push(`## ${domain}/ (${mdFiles.length})`);
|
|
@@ -14834,7 +14614,7 @@ async function regenerateIndex() {
|
|
|
14834
14614
|
for (const file of mdFiles.sort()) {
|
|
14835
14615
|
const slug = file.replace(/\.md$/, "");
|
|
14836
14616
|
try {
|
|
14837
|
-
const content = await (0,
|
|
14617
|
+
const content = await (0, import_promises8.readFile)((0, import_node_path12.join)(domainDir, file), "utf-8");
|
|
14838
14618
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
14839
14619
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
14840
14620
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -14858,14 +14638,14 @@ async function regenerateIndex() {
|
|
|
14858
14638
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
14859
14639
|
}
|
|
14860
14640
|
const next = lines.join("\n") + "\n";
|
|
14861
|
-
const indexPath = (0,
|
|
14641
|
+
const indexPath = (0, import_node_path12.join)(memoryDir2(), "index.md");
|
|
14862
14642
|
let existing = null;
|
|
14863
14643
|
try {
|
|
14864
|
-
existing = await (0,
|
|
14644
|
+
existing = await (0, import_promises8.readFile)(indexPath, "utf-8");
|
|
14865
14645
|
} catch {
|
|
14866
14646
|
}
|
|
14867
14647
|
if (existing === next) return;
|
|
14868
|
-
await (0,
|
|
14648
|
+
await (0, import_promises8.writeFile)(indexPath, next);
|
|
14869
14649
|
}
|
|
14870
14650
|
function pickFrontmatter(content, key) {
|
|
14871
14651
|
const re = new RegExp(`^${key}:\\s*"?([^"\\n]+?)"?\\s*$`, "m");
|
|
@@ -14892,90 +14672,6 @@ var LEGACY_MD_END = "<!-- gate-memory:end -->";
|
|
|
14892
14672
|
var LEGACY_PRESERVE_START = "<!-- gate-memory:preserve -->";
|
|
14893
14673
|
var LEGACY_PRESERVE_END = "<!-- /gate-memory:preserve -->";
|
|
14894
14674
|
var CLAUDE_MD_PROSE = [
|
|
14895
|
-
"## Project Memory",
|
|
14896
|
-
"",
|
|
14897
|
-
"This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
|
|
14898
|
-
"non-trivial work, scan `.verity/memory/index.md` for decisions, gotchas, and patterns",
|
|
14899
|
-
"that may apply to the change you are about to make. Open specific node files via",
|
|
14900
|
-
"the Read tool when the title or scope suggests relevance.",
|
|
14901
|
-
"",
|
|
14902
|
-
"The graph is auto-maintained by Verity. Files at `.verity/memory/_archive/` are",
|
|
14903
|
-
"superseded \u2014 ignore them unless investigating history.",
|
|
14904
|
-
"",
|
|
14905
|
-
"Knowledge the organization's other repositories learned is mirrored outside the",
|
|
14906
|
-
"repo at `~/.verity/orgs/<host>/<owner>/memory/` (`verity memory org` lists it).",
|
|
14907
|
-
"Each claim says where it came from; one that is wrong here is demoted for",
|
|
14908
|
-
'everyone with `verity memory demote <id> --reason "\u2026"`.',
|
|
14909
|
-
"",
|
|
14910
|
-
"## Quality gate: accepted risks",
|
|
14911
|
-
"",
|
|
14912
|
-
"When the Verity pre-commit/pre-push gate FAILs, fix the findings \u2014 that is the",
|
|
14913
|
-
'default. Use `verity waive <pattern-id> --file <path> --reason "\u2026"` ONLY to relay',
|
|
14914
|
-
"a risk a human has explicitly accepted: a named code-review finding, an ADR, or",
|
|
14915
|
-
"the user saying so in this conversation. The --reason must cite that source.",
|
|
14916
|
-
"",
|
|
14917
|
-
"Never waive on your own judgment, to get past a block, or pre-emptively. A waive",
|
|
14918
|
-
"binds to the file's current bytes and voids automatically when the file changes,",
|
|
14919
|
-
"and every waive is recorded in the run ledger. For a pattern-level false positive",
|
|
14920
|
-
"use `verity feedback finding <run-id> <pattern-id> false_positive` instead.",
|
|
14921
|
-
"",
|
|
14922
|
-
"## Post-task reflection",
|
|
14923
|
-
"",
|
|
14924
|
-
`When a task is complete (you've created a PR, the user says "done" or "ship it",`,
|
|
14925
|
-
"or the work is clearly finished), **draft the reflection yourself** \u2014 1\u20133",
|
|
14926
|
-
"concrete things worth remembering (a decision, a gotcha, or a pattern), each",
|
|
14927
|
-
"cited with the files / PR / commands / error-signatures it came from. Skip",
|
|
14928
|
-
"entirely if nothing non-obvious happened \u2014 that judgement is the ONLY filter,",
|
|
14929
|
-
"because nothing reviews the reflection before it lands.",
|
|
14930
|
-
"",
|
|
14931
|
-
"Then record it straight away. There is no confirm step, in any environment:",
|
|
14932
|
-
"",
|
|
14933
|
-
"```bash",
|
|
14934
|
-
'verity reflect --user-input "<your draft>" --kind <kind>',
|
|
14935
|
-
"```",
|
|
14936
|
-
"",
|
|
14937
|
-
"Add `--confirmed` ONLY when the user authored or dictated the words. Without",
|
|
14938
|
-
"it the node is stored as `source: agent` \u2014 Verity thought this, nobody checked",
|
|
14939
|
-
"it. With it, `source: user` at full confidence \u2014 a person stands behind this.",
|
|
14940
|
-
"Never claim the second for your own draft, however good it is.",
|
|
14941
|
-
"",
|
|
14942
|
-
"**Name the files in the text.** Verity scopes the reflection to the paths it",
|
|
14943
|
-
"cites, and a reflection that names no file in this repo is never retrieved for",
|
|
14944
|
-
"a later review \u2014 it is recorded and then invisible. The command says so when it",
|
|
14945
|
-
'happens; `--file-globs "<path or glob>"` is the fix when the prose cannot carry',
|
|
14946
|
-
"the paths.",
|
|
14947
|
-
"",
|
|
14948
|
-
"Then tell the user, in one line, what you recorded and where: the command",
|
|
14949
|
-
"prints the node id, the path under `.verity/memory/`, and a dashboard link.",
|
|
14950
|
-
"They did not agree to it in advance, so say it happened \u2014 editing or deleting",
|
|
14951
|
-
"that file is how they correct it.",
|
|
14952
|
-
"",
|
|
14953
|
-
"> Durable, hand-curated guidance goes in the preserve region below (it survives",
|
|
14954
|
-
"> regeneration) or anywhere OUTSIDE these markers. Everything else between the",
|
|
14955
|
-
"> markers is tool-owned and overwritten on each run.",
|
|
14956
|
-
"",
|
|
14957
|
-
"## Housekeeping Turns",
|
|
14958
|
-
"",
|
|
14959
|
-
"When a turn will be pure housekeeping \u2014 pulling, installing dependencies,",
|
|
14960
|
-
"rebasing, a formatting sweep you are not authoring \u2014 declare it BEFORE doing it:",
|
|
14961
|
-
"",
|
|
14962
|
-
"```bash",
|
|
14963
|
-
'verity ignore --turn --agent --reason "pulling latest before starting"',
|
|
14964
|
-
"```",
|
|
14965
|
-
"",
|
|
14966
|
-
"This skips the review for that turn, which saves the turn Verity would",
|
|
14967
|
-
"otherwise spend saying it had nothing to say. Use `--for 30m` instead of",
|
|
14968
|
-
"`--turn` when a single piece of housekeeping spans several turns.",
|
|
14969
|
-
"",
|
|
14970
|
-
"**It is a claim about the turn, not a way to silence review.** The declaration",
|
|
14971
|
-
"is checked against what the turn actually did: if anything is authored \u2014 by you,",
|
|
14972
|
-
"by a subagent, or by a shell command that can write files \u2014 it voids, the review",
|
|
14973
|
-
"runs anyway, and the broken declaration is reported. So declare housekeeping you",
|
|
14974
|
-
"are about to do, never work you have already done, and never as a way to get past",
|
|
14975
|
-
"a finding. Declarations are budgeted per session and every one is recorded with",
|
|
14976
|
-
"its reason."
|
|
14977
|
-
].join("\n");
|
|
14978
|
-
var CLAUDE_MD_PROSE_PRE_ORG = [
|
|
14979
14675
|
"## Project Memory",
|
|
14980
14676
|
"",
|
|
14981
14677
|
"This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
|
|
@@ -15255,10 +14951,10 @@ function hasLegacyMemoryBlock(text) {
|
|
|
15255
14951
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
15256
14952
|
}
|
|
15257
14953
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
15258
|
-
const claudeMdPath = (0,
|
|
14954
|
+
const claudeMdPath = (0, import_node_path12.join)(cwd, "CLAUDE.md");
|
|
15259
14955
|
let existing = "";
|
|
15260
|
-
if ((0,
|
|
15261
|
-
existing = await (0,
|
|
14956
|
+
if ((0, import_node_fs13.existsSync)(claudeMdPath)) {
|
|
14957
|
+
existing = await (0, import_promises8.readFile)(claudeMdPath, "utf-8");
|
|
15262
14958
|
}
|
|
15263
14959
|
let startTag = CLAUDE_MD_START;
|
|
15264
14960
|
let endTag = CLAUDE_MD_END;
|
|
@@ -15314,7 +15010,7 @@ async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
|
15314
15010
|
next = existing.replace(/\n*$/, "") + "\n\n" + block + "\n";
|
|
15315
15011
|
}
|
|
15316
15012
|
if (next === existing) return;
|
|
15317
|
-
await (0,
|
|
15013
|
+
await (0, import_promises8.writeFile)(claudeMdPath, next);
|
|
15318
15014
|
}
|
|
15319
15015
|
function extractPreserveContent(interior) {
|
|
15320
15016
|
for (const [start, end] of [
|
|
@@ -15333,7 +15029,6 @@ function stripKnownProse(interior) {
|
|
|
15333
15029
|
const trimmed = interior.replace(/^\n+/, "");
|
|
15334
15030
|
for (const prose of [
|
|
15335
15031
|
CLAUDE_MD_PROSE,
|
|
15336
|
-
CLAUDE_MD_PROSE_PRE_ORG,
|
|
15337
15032
|
CLAUDE_MD_PROSE_PRE_AUTORECORD,
|
|
15338
15033
|
CLAUDE_MD_PROSE_PRE_REFLECT,
|
|
15339
15034
|
CLAUDE_MD_PROSE_PRE_WAIVE,
|
|
@@ -15398,9 +15093,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
15398
15093
|
`;
|
|
15399
15094
|
|
|
15400
15095
|
// src/lib/dossier-session.ts
|
|
15401
|
-
var
|
|
15096
|
+
var import_node_fs18 = require("node:fs");
|
|
15402
15097
|
var import_node_crypto7 = require("node:crypto");
|
|
15403
|
-
var
|
|
15098
|
+
var import_node_path15 = require("node:path");
|
|
15404
15099
|
|
|
15405
15100
|
// src/lib/pending-repeat.ts
|
|
15406
15101
|
var STOP = /* @__PURE__ */ new Set([
|
|
@@ -15505,8 +15200,8 @@ function statementAnchorKey(file, patternId) {
|
|
|
15505
15200
|
|
|
15506
15201
|
// src/lib/dossier/log.ts
|
|
15507
15202
|
var import_node_crypto4 = require("node:crypto");
|
|
15508
|
-
var
|
|
15509
|
-
var
|
|
15203
|
+
var import_node_fs14 = require("node:fs");
|
|
15204
|
+
var import_node_path13 = require("node:path");
|
|
15510
15205
|
var CRC_TABLE = (() => {
|
|
15511
15206
|
const t = new Int32Array(256);
|
|
15512
15207
|
for (let i = 0; i < 256; i++) {
|
|
@@ -15525,13 +15220,13 @@ function crc32(s) {
|
|
|
15525
15220
|
function openDossier(identity) {
|
|
15526
15221
|
try {
|
|
15527
15222
|
const dir = dossierDir(identity);
|
|
15528
|
-
(0,
|
|
15223
|
+
(0, import_node_fs14.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
15529
15224
|
return {
|
|
15530
15225
|
dir,
|
|
15531
15226
|
identity,
|
|
15532
|
-
eventsPath: (0,
|
|
15533
|
-
foldPath: (0,
|
|
15534
|
-
rotatedDir: (0,
|
|
15227
|
+
eventsPath: (0, import_node_path13.join)(dir, "events.jsonl"),
|
|
15228
|
+
foldPath: (0, import_node_path13.join)(dir, "fold.json"),
|
|
15229
|
+
rotatedDir: (0, import_node_path13.join)(dir, "rotated")
|
|
15535
15230
|
};
|
|
15536
15231
|
} catch {
|
|
15537
15232
|
return null;
|
|
@@ -15593,7 +15288,7 @@ function appendEvent(d, ev) {
|
|
|
15593
15288
|
at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
15594
15289
|
...ev
|
|
15595
15290
|
});
|
|
15596
|
-
(0,
|
|
15291
|
+
(0, import_node_fs14.appendFileSync)(d.eventsPath, line, { mode: 384 });
|
|
15597
15292
|
return true;
|
|
15598
15293
|
} catch {
|
|
15599
15294
|
return false;
|
|
@@ -15601,14 +15296,14 @@ function appendEvent(d, ev) {
|
|
|
15601
15296
|
}
|
|
15602
15297
|
function rotateIfNeeded2(d) {
|
|
15603
15298
|
try {
|
|
15604
|
-
if (!(0,
|
|
15605
|
-
if ((0,
|
|
15606
|
-
(0,
|
|
15607
|
-
(0,
|
|
15608
|
-
const kept = (0,
|
|
15299
|
+
if (!(0, import_node_fs14.existsSync)(d.eventsPath)) return;
|
|
15300
|
+
if ((0, import_node_fs14.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
|
|
15301
|
+
(0, import_node_fs14.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
|
|
15302
|
+
(0, import_node_fs14.renameSync)(d.eventsPath, (0, import_node_path13.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
|
|
15303
|
+
const kept = (0, import_node_fs14.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
15609
15304
|
for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
|
|
15610
15305
|
try {
|
|
15611
|
-
(0,
|
|
15306
|
+
(0, import_node_fs14.renameSync)((0, import_node_path13.join)(d.rotatedDir, stale), (0, import_node_path13.join)(d.rotatedDir, `${stale}.pruned`));
|
|
15612
15307
|
} catch {
|
|
15613
15308
|
}
|
|
15614
15309
|
}
|
|
@@ -15618,8 +15313,8 @@ function rotateIfNeeded2(d) {
|
|
|
15618
15313
|
|
|
15619
15314
|
// src/lib/dossier/fold-dossier.ts
|
|
15620
15315
|
var import_node_crypto5 = require("node:crypto");
|
|
15621
|
-
var
|
|
15622
|
-
var
|
|
15316
|
+
var import_node_fs15 = require("node:fs");
|
|
15317
|
+
var import_node_path14 = require("node:path");
|
|
15623
15318
|
var EMPTY_CAPABILITIES = () => ({
|
|
15624
15319
|
human_reachable: { value: "unknown", tier: "unknown" },
|
|
15625
15320
|
authorship_observability: { value: "unknown", tier: "unknown" },
|
|
@@ -15670,12 +15365,12 @@ function foldDossier(d, opts = {}) {
|
|
|
15670
15365
|
}
|
|
15671
15366
|
};
|
|
15672
15367
|
try {
|
|
15673
|
-
if ((0,
|
|
15674
|
-
const files = (0,
|
|
15368
|
+
if ((0, import_node_fs15.existsSync)(d.rotatedDir)) {
|
|
15369
|
+
const files = (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
15675
15370
|
state.meta.rotations = files.length;
|
|
15676
15371
|
for (const f of files) {
|
|
15677
15372
|
try {
|
|
15678
|
-
ingest((0,
|
|
15373
|
+
ingest((0, import_node_fs15.readFileSync)((0, import_node_path14.join)(d.rotatedDir, f), "utf8"));
|
|
15679
15374
|
} catch {
|
|
15680
15375
|
state.meta.dropped_lines++;
|
|
15681
15376
|
}
|
|
@@ -15684,9 +15379,9 @@ function foldDossier(d, opts = {}) {
|
|
|
15684
15379
|
} catch {
|
|
15685
15380
|
}
|
|
15686
15381
|
try {
|
|
15687
|
-
if ((0,
|
|
15688
|
-
state.meta.upto_offset = (0,
|
|
15689
|
-
ingest((0,
|
|
15382
|
+
if ((0, import_node_fs15.existsSync)(d.eventsPath)) {
|
|
15383
|
+
state.meta.upto_offset = (0, import_node_fs15.statSync)(d.eventsPath).size;
|
|
15384
|
+
ingest((0, import_node_fs15.readFileSync)(d.eventsPath, "utf8"));
|
|
15690
15385
|
}
|
|
15691
15386
|
} catch {
|
|
15692
15387
|
}
|
|
@@ -15957,7 +15652,7 @@ function applyBounds(state, input) {
|
|
|
15957
15652
|
}
|
|
15958
15653
|
|
|
15959
15654
|
// src/lib/dossier/cache.ts
|
|
15960
|
-
var
|
|
15655
|
+
var import_node_fs16 = require("node:fs");
|
|
15961
15656
|
function compactState(s) {
|
|
15962
15657
|
const ms = (iso) => Date.parse(iso) || 0;
|
|
15963
15658
|
return {
|
|
@@ -16086,20 +15781,20 @@ function encodeState(s) {
|
|
|
16086
15781
|
function writeFoldCache(d, state) {
|
|
16087
15782
|
try {
|
|
16088
15783
|
const tmp = `${d.foldPath}.${process.pid}.tmp`;
|
|
16089
|
-
(0,
|
|
16090
|
-
(0,
|
|
15784
|
+
(0, import_node_fs16.writeFileSync)(tmp, encodeState(state), { mode: 384 });
|
|
15785
|
+
(0, import_node_fs16.renameSync)(tmp, d.foldPath);
|
|
16091
15786
|
} catch {
|
|
16092
15787
|
}
|
|
16093
15788
|
}
|
|
16094
15789
|
function readFoldCache(d) {
|
|
16095
15790
|
try {
|
|
16096
|
-
if (!(0,
|
|
16097
|
-
const raw = JSON.parse((0,
|
|
15791
|
+
if (!(0, import_node_fs16.existsSync)(d.foldPath)) return null;
|
|
15792
|
+
const raw = JSON.parse((0, import_node_fs16.readFileSync)(d.foldPath, "utf8"));
|
|
16098
15793
|
if (raw?.v !== 1) return null;
|
|
16099
15794
|
const cached2 = expandState(raw);
|
|
16100
15795
|
if (!cached2?.meta) return null;
|
|
16101
|
-
const size = (0,
|
|
16102
|
-
const rotations = (0,
|
|
15796
|
+
const size = (0, import_node_fs16.existsSync)(d.eventsPath) ? (0, import_node_fs16.statSync)(d.eventsPath).size : 0;
|
|
15797
|
+
const rotations = (0, import_node_fs16.existsSync)(d.rotatedDir) ? (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
|
|
16103
15798
|
if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
|
|
16104
15799
|
return cached2;
|
|
16105
15800
|
} catch {
|
|
@@ -16150,13 +15845,13 @@ function assessContinuity(i) {
|
|
|
16150
15845
|
|
|
16151
15846
|
// src/lib/dossier/reanchor.ts
|
|
16152
15847
|
var import_node_crypto6 = require("node:crypto");
|
|
16153
|
-
var
|
|
15848
|
+
var import_node_fs17 = require("node:fs");
|
|
16154
15849
|
function lineSha(text) {
|
|
16155
15850
|
return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
16156
15851
|
}
|
|
16157
15852
|
function fileHash(path) {
|
|
16158
15853
|
try {
|
|
16159
|
-
return (0, import_node_crypto6.createHash)("sha256").update((0,
|
|
15854
|
+
return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs17.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
16160
15855
|
} catch {
|
|
16161
15856
|
return null;
|
|
16162
15857
|
}
|
|
@@ -16528,20 +16223,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
|
|
|
16528
16223
|
let sessions = 0;
|
|
16529
16224
|
try {
|
|
16530
16225
|
const dir = treeDir(identity);
|
|
16531
|
-
if (!(0,
|
|
16532
|
-
for (const entry of (0,
|
|
16226
|
+
if (!(0, import_node_fs18.existsSync)(dir)) return { paths: [], sessions: 0 };
|
|
16227
|
+
for (const entry of (0, import_node_fs18.readdirSync)(dir, { withFileTypes: true })) {
|
|
16533
16228
|
if (!entry.isDirectory()) continue;
|
|
16534
16229
|
if (entry.name === identity.sessionKey) continue;
|
|
16535
|
-
const log = (0,
|
|
16230
|
+
const log = (0, import_node_path15.join)(dir, entry.name, "events.jsonl");
|
|
16536
16231
|
try {
|
|
16537
|
-
if (!(0,
|
|
16538
|
-
if (now - (0,
|
|
16232
|
+
if (!(0, import_node_fs18.existsSync)(log)) continue;
|
|
16233
|
+
if (now - (0, import_node_fs18.statSync)(log).mtimeMs > windowMs) continue;
|
|
16539
16234
|
const sib = {
|
|
16540
|
-
dir: (0,
|
|
16235
|
+
dir: (0, import_node_path15.join)(dir, entry.name),
|
|
16541
16236
|
identity,
|
|
16542
16237
|
eventsPath: log,
|
|
16543
|
-
foldPath: (0,
|
|
16544
|
-
rotatedDir: (0,
|
|
16238
|
+
foldPath: (0, import_node_path15.join)(dir, entry.name, "fold.json"),
|
|
16239
|
+
rotatedDir: (0, import_node_path15.join)(dir, entry.name, "rotated")
|
|
16545
16240
|
};
|
|
16546
16241
|
const state = readFoldCache(sib) ?? foldDossier(sib);
|
|
16547
16242
|
sessions++;
|
|
@@ -16569,25 +16264,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
16569
16264
|
let removed = 0;
|
|
16570
16265
|
try {
|
|
16571
16266
|
const mine = dossierDir(identity);
|
|
16572
|
-
const userDir = (0,
|
|
16573
|
-
if (!(0,
|
|
16267
|
+
const userDir = (0, import_node_path15.dirname)((0, import_node_path15.dirname)(mine));
|
|
16268
|
+
if (!(0, import_node_fs18.existsSync)(userDir)) return 0;
|
|
16574
16269
|
const cutoff = Date.now() - maxAgeMs;
|
|
16575
|
-
for (const tree of (0,
|
|
16270
|
+
for (const tree of (0, import_node_fs18.readdirSync)(userDir, { withFileTypes: true })) {
|
|
16576
16271
|
if (!tree.isDirectory()) continue;
|
|
16577
|
-
const treePath = (0,
|
|
16272
|
+
const treePath = (0, import_node_path15.join)(userDir, tree.name);
|
|
16578
16273
|
let live = 0;
|
|
16579
|
-
for (const entry of (0,
|
|
16274
|
+
for (const entry of (0, import_node_fs18.readdirSync)(treePath, { withFileTypes: true })) {
|
|
16580
16275
|
if (!entry.isDirectory()) continue;
|
|
16581
|
-
const dir = (0,
|
|
16276
|
+
const dir = (0, import_node_path15.join)(treePath, entry.name);
|
|
16582
16277
|
if (dir === mine) {
|
|
16583
16278
|
live++;
|
|
16584
16279
|
continue;
|
|
16585
16280
|
}
|
|
16586
16281
|
try {
|
|
16587
|
-
const log = (0,
|
|
16588
|
-
const at = (0,
|
|
16282
|
+
const log = (0, import_node_path15.join)(dir, "events.jsonl");
|
|
16283
|
+
const at = (0, import_node_fs18.existsSync)(log) ? (0, import_node_fs18.statSync)(log).mtimeMs : (0, import_node_fs18.statSync)(dir).mtimeMs;
|
|
16589
16284
|
if (at < cutoff) {
|
|
16590
|
-
(0,
|
|
16285
|
+
(0, import_node_fs18.rmSync)(dir, { recursive: true, force: true });
|
|
16591
16286
|
removed++;
|
|
16592
16287
|
} else {
|
|
16593
16288
|
live++;
|
|
@@ -16597,7 +16292,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
16597
16292
|
}
|
|
16598
16293
|
if (live === 0) {
|
|
16599
16294
|
try {
|
|
16600
|
-
(0,
|
|
16295
|
+
(0, import_node_fs18.rmSync)(treePath, { recursive: false, force: false });
|
|
16601
16296
|
} catch {
|
|
16602
16297
|
}
|
|
16603
16298
|
}
|
|
@@ -16614,8 +16309,8 @@ function sessionDossier(token, sessionId) {
|
|
|
16614
16309
|
}
|
|
16615
16310
|
function hasActiveGoal(d) {
|
|
16616
16311
|
try {
|
|
16617
|
-
if (!(0,
|
|
16618
|
-
return (0,
|
|
16312
|
+
if (!(0, import_node_fs18.existsSync)(d.eventsPath)) return false;
|
|
16313
|
+
return (0, import_node_fs18.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
|
|
16619
16314
|
} catch {
|
|
16620
16315
|
return false;
|
|
16621
16316
|
}
|
|
@@ -16639,7 +16334,7 @@ function recordTurn(d, t) {
|
|
|
16639
16334
|
for (const a of t.authored) {
|
|
16640
16335
|
const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
|
|
16641
16336
|
const prior = t.known?.authored?.get(a.p);
|
|
16642
|
-
const hash = fileHash((0,
|
|
16337
|
+
const hash = fileHash((0, import_node_path15.join)(root, a.p));
|
|
16643
16338
|
const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
|
|
16644
16339
|
const adds = Math.max(0, a.a - (prior?.adds ?? 0));
|
|
16645
16340
|
const dels = Math.max(0, a.d - (prior?.dels ?? 0));
|
|
@@ -16672,7 +16367,7 @@ function recordTurn(d, t) {
|
|
|
16672
16367
|
}
|
|
16673
16368
|
const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
|
|
16674
16369
|
for (const u of t.unobserved) {
|
|
16675
|
-
const hash = fileHash((0,
|
|
16370
|
+
const hash = fileHash((0, import_node_path15.join)(root, u.p));
|
|
16676
16371
|
if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
|
|
16677
16372
|
appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
|
|
16678
16373
|
}
|
|
@@ -16707,8 +16402,8 @@ function recordVerdict(d, v) {
|
|
|
16707
16402
|
if (!sent.has(f.file)) continue;
|
|
16708
16403
|
if (!lines.has(f.file)) {
|
|
16709
16404
|
try {
|
|
16710
|
-
const abs = (0,
|
|
16711
|
-
lines.set(f.file, (0,
|
|
16405
|
+
const abs = (0, import_node_path15.join)(root, f.file);
|
|
16406
|
+
lines.set(f.file, (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null);
|
|
16712
16407
|
} catch {
|
|
16713
16408
|
lines.set(f.file, null);
|
|
16714
16409
|
}
|
|
@@ -16808,8 +16503,8 @@ function recallMemory(d, identity, opts) {
|
|
|
16808
16503
|
budgetBytes: opts.budgetBytes,
|
|
16809
16504
|
readFileLines: (file) => {
|
|
16810
16505
|
try {
|
|
16811
|
-
const abs = (0,
|
|
16812
|
-
return (0,
|
|
16506
|
+
const abs = (0, import_node_path15.join)(root, file);
|
|
16507
|
+
return (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null;
|
|
16813
16508
|
} catch {
|
|
16814
16509
|
return null;
|
|
16815
16510
|
}
|
|
@@ -16953,46 +16648,46 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
16953
16648
|
}
|
|
16954
16649
|
|
|
16955
16650
|
// src/commands/lifecycle.ts
|
|
16956
|
-
var import_node_fs23 = require("node:fs");
|
|
16957
|
-
var import_node_path21 = require("node:path");
|
|
16958
|
-
|
|
16959
|
-
// src/lib/baseline.ts
|
|
16960
16651
|
var import_node_fs22 = require("node:fs");
|
|
16961
16652
|
var import_node_path20 = require("node:path");
|
|
16962
|
-
var import_node_crypto9 = require("node:crypto");
|
|
16963
16653
|
|
|
16964
|
-
// src/lib/
|
|
16654
|
+
// src/lib/baseline.ts
|
|
16965
16655
|
var import_node_fs21 = require("node:fs");
|
|
16966
16656
|
var import_node_path19 = require("node:path");
|
|
16657
|
+
var import_node_crypto9 = require("node:crypto");
|
|
16658
|
+
|
|
16659
|
+
// src/lib/snapshot.ts
|
|
16660
|
+
var import_node_fs20 = require("node:fs");
|
|
16661
|
+
var import_node_path18 = require("node:path");
|
|
16967
16662
|
var import_node_child_process7 = require("node:child_process");
|
|
16968
16663
|
|
|
16969
16664
|
// src/lib/files.ts
|
|
16970
|
-
var
|
|
16665
|
+
var import_node_path17 = require("node:path");
|
|
16971
16666
|
|
|
16972
16667
|
// src/lib/safe-read.ts
|
|
16973
|
-
var
|
|
16974
|
-
var
|
|
16975
|
-
var FLAGS =
|
|
16668
|
+
var import_node_fs19 = require("node:fs");
|
|
16669
|
+
var import_node_path16 = require("node:path");
|
|
16670
|
+
var FLAGS = import_node_fs19.constants;
|
|
16976
16671
|
var NOFOLLOW = FLAGS.O_NOFOLLOW;
|
|
16977
16672
|
var NONBLOCK = FLAGS.O_NONBLOCK;
|
|
16978
16673
|
function closeOpened(fd) {
|
|
16979
16674
|
try {
|
|
16980
|
-
(0,
|
|
16675
|
+
(0, import_node_fs19.closeSync)(fd);
|
|
16981
16676
|
} catch {
|
|
16982
16677
|
}
|
|
16983
16678
|
}
|
|
16984
16679
|
function isInsideRoot(realRoot, realPath) {
|
|
16985
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
16680
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path16.sep) ? realRoot : realRoot + import_node_path16.sep);
|
|
16986
16681
|
}
|
|
16987
16682
|
function sameOpenedFile(opened, current, nofollowAvailable) {
|
|
16988
16683
|
if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
|
|
16989
16684
|
return opened.ino === current.ino && opened.dev === current.dev;
|
|
16990
16685
|
}
|
|
16991
16686
|
function openRegularInRoot(root, path) {
|
|
16992
|
-
const full = (0,
|
|
16687
|
+
const full = (0, import_node_path16.isAbsolute)(path) ? path : (0, import_node_path16.join)(root, path);
|
|
16993
16688
|
let fd;
|
|
16994
16689
|
try {
|
|
16995
|
-
fd = (0,
|
|
16690
|
+
fd = (0, import_node_fs19.openSync)(full, import_node_fs19.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
|
|
16996
16691
|
} catch (err) {
|
|
16997
16692
|
const code = err.code;
|
|
16998
16693
|
if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
|
|
@@ -17000,18 +16695,18 @@ function openRegularInRoot(root, path) {
|
|
|
17000
16695
|
return { ok: false, reason: "unreadable" };
|
|
17001
16696
|
}
|
|
17002
16697
|
try {
|
|
17003
|
-
const opened = (0,
|
|
16698
|
+
const opened = (0, import_node_fs19.fstatSync)(fd, { bigint: true });
|
|
17004
16699
|
if (!opened.isFile()) {
|
|
17005
16700
|
closeOpened(fd);
|
|
17006
16701
|
return { ok: false, reason: "not-regular" };
|
|
17007
16702
|
}
|
|
17008
|
-
const realRoot =
|
|
17009
|
-
const realPath =
|
|
16703
|
+
const realRoot = import_node_fs19.realpathSync.native(root);
|
|
16704
|
+
const realPath = import_node_fs19.realpathSync.native(full);
|
|
17010
16705
|
if (!isInsideRoot(realRoot, realPath)) {
|
|
17011
16706
|
closeOpened(fd);
|
|
17012
16707
|
return { ok: false, reason: "outside-root" };
|
|
17013
16708
|
}
|
|
17014
|
-
const current = (0,
|
|
16709
|
+
const current = (0, import_node_fs19.statSync)(realPath, { bigint: true });
|
|
17015
16710
|
if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
|
|
17016
16711
|
closeOpened(fd);
|
|
17017
16712
|
return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
|
|
@@ -17033,7 +16728,7 @@ function readOpened(fd, size) {
|
|
|
17033
16728
|
const buffer = Buffer.alloc(size);
|
|
17034
16729
|
let offset = 0;
|
|
17035
16730
|
while (offset < size) {
|
|
17036
|
-
const n = (0,
|
|
16731
|
+
const n = (0, import_node_fs19.readSync)(fd, buffer, offset, size - offset, offset);
|
|
17037
16732
|
if (n === 0) break;
|
|
17038
16733
|
offset += n;
|
|
17039
16734
|
}
|
|
@@ -17127,7 +16822,7 @@ var LANG_MAP = {
|
|
|
17127
16822
|
mk: "make"
|
|
17128
16823
|
};
|
|
17129
16824
|
function detectLanguage(filepath) {
|
|
17130
|
-
const ext = (0,
|
|
16825
|
+
const ext = (0, import_node_path17.extname)(filepath).slice(1);
|
|
17131
16826
|
return LANG_MAP[ext] ?? ext;
|
|
17132
16827
|
}
|
|
17133
16828
|
function sortByMtime(files) {
|
|
@@ -17218,16 +16913,16 @@ function collectCodeDelta(files, opts) {
|
|
|
17218
16913
|
|
|
17219
16914
|
// src/lib/snapshot.ts
|
|
17220
16915
|
function generateSnapshotDiffs(files) {
|
|
17221
|
-
if (!(0,
|
|
16916
|
+
if (!(0, import_node_fs20.existsSync)(SNAPSHOT_DIR)) {
|
|
17222
16917
|
return { diffs: [], has_snapshots: false };
|
|
17223
16918
|
}
|
|
17224
16919
|
const diffs = [];
|
|
17225
16920
|
for (const file of files) {
|
|
17226
16921
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
17227
|
-
const snapshotPath = (0,
|
|
16922
|
+
const snapshotPath = (0, import_node_path18.join)(SNAPSHOT_DIR, file.path);
|
|
17228
16923
|
const language = file.language ?? detectLanguage(file.path);
|
|
17229
|
-
if ((0,
|
|
17230
|
-
const oldContent = (0,
|
|
16924
|
+
if ((0, import_node_fs20.existsSync)(snapshotPath)) {
|
|
16925
|
+
const oldContent = (0, import_node_fs20.readFileSync)(snapshotPath, "utf-8");
|
|
17231
16926
|
if (oldContent === file.content) continue;
|
|
17232
16927
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
17233
16928
|
if (diff) {
|
|
@@ -17252,20 +16947,20 @@ function saveSnapshots(files) {
|
|
|
17252
16947
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
17253
16948
|
for (const file of files) {
|
|
17254
16949
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
17255
|
-
const snapshotPath = (0,
|
|
16950
|
+
const snapshotPath = (0, import_node_path18.join)(SNAPSHOT_DIR, file.path);
|
|
17256
16951
|
snapshotPaths.add(snapshotPath);
|
|
17257
|
-
(0,
|
|
17258
|
-
(0,
|
|
16952
|
+
(0, import_node_fs20.mkdirSync)((0, import_node_path18.dirname)(snapshotPath), { recursive: true });
|
|
16953
|
+
(0, import_node_fs20.writeFileSync)(snapshotPath, file.content);
|
|
17259
16954
|
}
|
|
17260
16955
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
17261
16956
|
}
|
|
17262
16957
|
function computeDiff(oldContent, newContent, filePath) {
|
|
17263
|
-
const tmpOld = (0,
|
|
17264
|
-
const tmpNew = (0,
|
|
16958
|
+
const tmpOld = (0, import_node_path18.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
16959
|
+
const tmpNew = (0, import_node_path18.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
17265
16960
|
try {
|
|
17266
|
-
(0,
|
|
17267
|
-
(0,
|
|
17268
|
-
(0,
|
|
16961
|
+
(0, import_node_fs20.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
16962
|
+
(0, import_node_fs20.writeFileSync)(tmpOld, oldContent);
|
|
16963
|
+
(0, import_node_fs20.writeFileSync)(tmpNew, newContent);
|
|
17269
16964
|
const result = (0, import_node_child_process7.execSync)(
|
|
17270
16965
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
17271
16966
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -17279,32 +16974,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
17279
16974
|
return null;
|
|
17280
16975
|
} finally {
|
|
17281
16976
|
try {
|
|
17282
|
-
(0,
|
|
16977
|
+
(0, import_node_fs20.unlinkSync)(tmpOld);
|
|
17283
16978
|
} catch {
|
|
17284
16979
|
}
|
|
17285
16980
|
try {
|
|
17286
|
-
(0,
|
|
16981
|
+
(0, import_node_fs20.unlinkSync)(tmpNew);
|
|
17287
16982
|
} catch {
|
|
17288
16983
|
}
|
|
17289
16984
|
}
|
|
17290
16985
|
}
|
|
17291
16986
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
17292
|
-
if (!(0,
|
|
16987
|
+
if (!(0, import_node_fs20.existsSync)(dir)) return;
|
|
17293
16988
|
try {
|
|
17294
|
-
const entries = (0,
|
|
16989
|
+
const entries = (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true });
|
|
17295
16990
|
for (const entry of entries) {
|
|
17296
16991
|
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
17297
|
-
const fullPath = (0,
|
|
16992
|
+
const fullPath = (0, import_node_path18.join)(dir, entry.name);
|
|
17298
16993
|
if (entry.isDirectory()) {
|
|
17299
16994
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
17300
16995
|
try {
|
|
17301
|
-
const remaining = (0,
|
|
17302
|
-
if (remaining.length === 0) (0,
|
|
16996
|
+
const remaining = (0, import_node_fs20.readdirSync)(fullPath);
|
|
16997
|
+
if (remaining.length === 0) (0, import_node_fs20.rmdirSync)(fullPath);
|
|
17303
16998
|
} catch {
|
|
17304
16999
|
}
|
|
17305
17000
|
} else if (!keepSet.has(fullPath)) {
|
|
17306
17001
|
try {
|
|
17307
|
-
(0,
|
|
17002
|
+
(0, import_node_fs20.unlinkSync)(fullPath);
|
|
17308
17003
|
} catch {
|
|
17309
17004
|
}
|
|
17310
17005
|
}
|
|
@@ -17323,20 +17018,20 @@ function sessionKey(sessionId) {
|
|
|
17323
17018
|
return (0, import_node_crypto9.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
17324
17019
|
}
|
|
17325
17020
|
function sessionDir(key) {
|
|
17326
|
-
return (0,
|
|
17021
|
+
return (0, import_node_path19.join)(projectPath(BASELINE_DIR), key);
|
|
17327
17022
|
}
|
|
17328
17023
|
function manifestPath(dir) {
|
|
17329
|
-
return (0,
|
|
17024
|
+
return (0, import_node_path19.join)(dir, "manifest.json");
|
|
17330
17025
|
}
|
|
17331
17026
|
function mirrorPath(dir, repoRelPath) {
|
|
17332
|
-
return (0,
|
|
17027
|
+
return (0, import_node_path19.join)(dir, "files", repoRelPath);
|
|
17333
17028
|
}
|
|
17334
17029
|
var CARRY_FILE = `${BASELINE_DIR}/.carry`;
|
|
17335
17030
|
var CARRY_WINDOW_MS = 12e4;
|
|
17336
17031
|
function writeCarry(sessionId, headSha) {
|
|
17337
17032
|
try {
|
|
17338
|
-
(0,
|
|
17339
|
-
(0,
|
|
17033
|
+
(0, import_node_fs21.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
|
|
17034
|
+
(0, import_node_fs21.writeFileSync)(
|
|
17340
17035
|
projectPath(CARRY_FILE),
|
|
17341
17036
|
JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
|
|
17342
17037
|
);
|
|
@@ -17346,10 +17041,10 @@ function writeCarry(sessionId, headSha) {
|
|
|
17346
17041
|
function claimCarry(newKey) {
|
|
17347
17042
|
const carryPath = projectPath(CARRY_FILE);
|
|
17348
17043
|
try {
|
|
17349
|
-
if (!(0,
|
|
17350
|
-
const carry = JSON.parse((0,
|
|
17044
|
+
if (!(0, import_node_fs21.existsSync)(carryPath)) return null;
|
|
17045
|
+
const carry = JSON.parse((0, import_node_fs21.readFileSync)(carryPath, "utf-8"));
|
|
17351
17046
|
try {
|
|
17352
|
-
(0,
|
|
17047
|
+
(0, import_node_fs21.rmSync)(carryPath, { force: true });
|
|
17353
17048
|
} catch {
|
|
17354
17049
|
}
|
|
17355
17050
|
if (!carry?.from_key || typeof carry.ts !== "number") return null;
|
|
@@ -17360,11 +17055,11 @@ function claimCarry(newKey) {
|
|
|
17360
17055
|
if (!prior) return null;
|
|
17361
17056
|
const toDir = sessionDir(newKey);
|
|
17362
17057
|
try {
|
|
17363
|
-
(0,
|
|
17058
|
+
(0, import_node_fs21.rmSync)(toDir, { recursive: true, force: true });
|
|
17364
17059
|
} catch {
|
|
17365
17060
|
}
|
|
17366
|
-
(0,
|
|
17367
|
-
(0,
|
|
17061
|
+
(0, import_node_fs21.renameSync)(fromDir, toDir);
|
|
17062
|
+
(0, import_node_fs21.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
|
|
17368
17063
|
return readManifest(toDir);
|
|
17369
17064
|
} catch {
|
|
17370
17065
|
return null;
|
|
@@ -17388,21 +17083,21 @@ function captureBaseline(opts = {}) {
|
|
|
17388
17083
|
const head_sha = getCurrentCommit();
|
|
17389
17084
|
const dirty = getDirtyFiles();
|
|
17390
17085
|
try {
|
|
17391
|
-
(0,
|
|
17086
|
+
(0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
|
|
17392
17087
|
} catch {
|
|
17393
17088
|
}
|
|
17394
|
-
const filesDir = (0,
|
|
17089
|
+
const filesDir = (0, import_node_path19.join)(dir, "files");
|
|
17395
17090
|
const mirrored = [];
|
|
17396
17091
|
try {
|
|
17397
|
-
(0,
|
|
17092
|
+
(0, import_node_fs21.mkdirSync)(filesDir, { recursive: true });
|
|
17398
17093
|
for (const p of dirty) {
|
|
17399
17094
|
if (p.includes("..")) continue;
|
|
17400
17095
|
const content = safeReadForMirror(projectPath(p));
|
|
17401
17096
|
if (content === null) continue;
|
|
17402
17097
|
const dest = mirrorPath(dir, p);
|
|
17403
17098
|
try {
|
|
17404
|
-
(0,
|
|
17405
|
-
(0,
|
|
17099
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path19.dirname)(dest), { recursive: true });
|
|
17100
|
+
(0, import_node_fs21.writeFileSync)(dest, content);
|
|
17406
17101
|
mirrored.push(p);
|
|
17407
17102
|
} catch {
|
|
17408
17103
|
}
|
|
@@ -17417,8 +17112,8 @@ function captureBaseline(opts = {}) {
|
|
|
17417
17112
|
version: BASELINE_VERSION
|
|
17418
17113
|
};
|
|
17419
17114
|
try {
|
|
17420
|
-
(0,
|
|
17421
|
-
(0,
|
|
17115
|
+
(0, import_node_fs21.mkdirSync)(dir, { recursive: true });
|
|
17116
|
+
(0, import_node_fs21.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
|
|
17422
17117
|
} catch {
|
|
17423
17118
|
}
|
|
17424
17119
|
pruneOldBaselines();
|
|
@@ -17429,9 +17124,9 @@ function readBaseline(sessionId) {
|
|
|
17429
17124
|
}
|
|
17430
17125
|
function readManifest(dir) {
|
|
17431
17126
|
const mp = manifestPath(dir);
|
|
17432
|
-
if (!(0,
|
|
17127
|
+
if (!(0, import_node_fs21.existsSync)(mp)) return null;
|
|
17433
17128
|
try {
|
|
17434
|
-
const parsed = JSON.parse((0,
|
|
17129
|
+
const parsed = JSON.parse((0, import_node_fs21.readFileSync)(mp, "utf-8"));
|
|
17435
17130
|
if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
|
|
17436
17131
|
return null;
|
|
17437
17132
|
}
|
|
@@ -17462,9 +17157,9 @@ function preImage(repoRelPath, baseline) {
|
|
|
17462
17157
|
function resolvePreImage(repoRelPath, baseline) {
|
|
17463
17158
|
if (baseline.dirty_paths.includes(repoRelPath)) {
|
|
17464
17159
|
const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
|
|
17465
|
-
if ((0,
|
|
17160
|
+
if ((0, import_node_fs21.existsSync)(mp)) {
|
|
17466
17161
|
try {
|
|
17467
|
-
return { content: (0,
|
|
17162
|
+
return { content: (0, import_node_fs21.readFileSync)(mp, "utf-8"), existed: true };
|
|
17468
17163
|
} catch {
|
|
17469
17164
|
}
|
|
17470
17165
|
}
|
|
@@ -17509,8 +17204,8 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
17509
17204
|
const content = safeReadForMirror(projectPath(p));
|
|
17510
17205
|
if (content === null) continue;
|
|
17511
17206
|
const dest = mirrorPath(dir, p);
|
|
17512
|
-
(0,
|
|
17513
|
-
(0,
|
|
17207
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path19.dirname)(dest), { recursive: true });
|
|
17208
|
+
(0, import_node_fs21.writeFileSync)(dest, content);
|
|
17514
17209
|
dirty.add(p);
|
|
17515
17210
|
adopted++;
|
|
17516
17211
|
} catch {
|
|
@@ -17519,7 +17214,7 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
17519
17214
|
if (adopted === 0) return 0;
|
|
17520
17215
|
try {
|
|
17521
17216
|
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
17522
|
-
(0,
|
|
17217
|
+
(0, import_node_fs21.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
17523
17218
|
preImageCache.delete(baseline);
|
|
17524
17219
|
} catch {
|
|
17525
17220
|
return 0;
|
|
@@ -17530,7 +17225,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
17530
17225
|
const pre = preImage(repoRelPath, baseline);
|
|
17531
17226
|
let current;
|
|
17532
17227
|
try {
|
|
17533
|
-
current = (0,
|
|
17228
|
+
current = (0, import_node_fs21.readFileSync)(projectPath(repoRelPath), "utf-8");
|
|
17534
17229
|
} catch {
|
|
17535
17230
|
return pre.existed;
|
|
17536
17231
|
}
|
|
@@ -17539,8 +17234,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
17539
17234
|
}
|
|
17540
17235
|
function safeReadForMirror(absPath) {
|
|
17541
17236
|
try {
|
|
17542
|
-
if ((0,
|
|
17543
|
-
const buf = (0,
|
|
17237
|
+
if ((0, import_node_fs21.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
|
|
17238
|
+
const buf = (0, import_node_fs21.readFileSync)(absPath);
|
|
17544
17239
|
if (buf.includes(0)) return null;
|
|
17545
17240
|
return buf.toString("utf-8");
|
|
17546
17241
|
} catch {
|
|
@@ -17551,18 +17246,18 @@ function pruneOldBaselines() {
|
|
|
17551
17246
|
const root = projectPath(BASELINE_DIR);
|
|
17552
17247
|
let entries;
|
|
17553
17248
|
try {
|
|
17554
|
-
entries = (0,
|
|
17249
|
+
entries = (0, import_node_fs21.readdirSync)(root);
|
|
17555
17250
|
} catch {
|
|
17556
17251
|
return;
|
|
17557
17252
|
}
|
|
17558
17253
|
const now = Date.now();
|
|
17559
17254
|
for (const name of entries) {
|
|
17560
|
-
const dir = (0,
|
|
17255
|
+
const dir = (0, import_node_path19.join)(root, name);
|
|
17561
17256
|
const manifest = readManifest(dir);
|
|
17562
17257
|
if (!manifest) {
|
|
17563
17258
|
try {
|
|
17564
|
-
if (now - (0,
|
|
17565
|
-
(0,
|
|
17259
|
+
if (now - (0, import_node_fs21.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
|
|
17260
|
+
(0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
|
|
17566
17261
|
}
|
|
17567
17262
|
} catch {
|
|
17568
17263
|
}
|
|
@@ -17570,7 +17265,7 @@ function pruneOldBaselines() {
|
|
|
17570
17265
|
}
|
|
17571
17266
|
if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
|
|
17572
17267
|
try {
|
|
17573
|
-
(0,
|
|
17268
|
+
(0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
|
|
17574
17269
|
} catch {
|
|
17575
17270
|
}
|
|
17576
17271
|
}
|
|
@@ -17745,8 +17440,8 @@ function buildCompactionContext(session) {
|
|
|
17745
17440
|
commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
|
|
17746
17441
|
readFileLines: (file) => {
|
|
17747
17442
|
try {
|
|
17748
|
-
const abs = (0,
|
|
17749
|
-
return (0,
|
|
17443
|
+
const abs = (0, import_node_path20.join)(root, file);
|
|
17444
|
+
return (0, import_node_fs22.existsSync)(abs) ? (0, import_node_fs22.readFileSync)(abs, "utf8").split("\n") : null;
|
|
17750
17445
|
} catch {
|
|
17751
17446
|
return null;
|
|
17752
17447
|
}
|
|
@@ -17802,25 +17497,25 @@ async function readHookStdin() {
|
|
|
17802
17497
|
}
|
|
17803
17498
|
|
|
17804
17499
|
// src/commands/standard.ts
|
|
17805
|
-
var
|
|
17806
|
-
var
|
|
17500
|
+
var import_promises12 = require("node:fs/promises");
|
|
17501
|
+
var import_node_fs29 = require("node:fs");
|
|
17807
17502
|
var import_yaml3 = __toESM(require_dist());
|
|
17808
17503
|
|
|
17809
17504
|
// src/lib/synthesize.ts
|
|
17810
17505
|
var import_node_child_process9 = require("node:child_process");
|
|
17811
|
-
var
|
|
17812
|
-
var
|
|
17813
|
-
var
|
|
17506
|
+
var import_node_fs25 = require("node:fs");
|
|
17507
|
+
var import_promises9 = require("node:fs/promises");
|
|
17508
|
+
var import_node_path23 = require("node:path");
|
|
17814
17509
|
var import_yaml = __toESM(require_dist());
|
|
17815
17510
|
|
|
17816
17511
|
// src/lib/data-dir.ts
|
|
17817
|
-
var
|
|
17818
|
-
var
|
|
17512
|
+
var import_node_fs23 = require("node:fs");
|
|
17513
|
+
var import_node_path21 = require("node:path");
|
|
17819
17514
|
function resolveDataDir() {
|
|
17820
17515
|
const candidates2 = [
|
|
17821
|
-
(0,
|
|
17516
|
+
(0, import_node_path21.join)(__dirname, "..", "data"),
|
|
17822
17517
|
// installed: node_modules/@codacy/verity-cli/data
|
|
17823
|
-
(0,
|
|
17518
|
+
(0, import_node_path21.join)(__dirname, "..", "..", "data"),
|
|
17824
17519
|
// edge case: nested resolution
|
|
17825
17520
|
// THE COMMITTED SOURCE, for a source checkout that has not been built.
|
|
17826
17521
|
// cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
|
|
@@ -17829,14 +17524,14 @@ function resolveDataDir() {
|
|
|
17829
17524
|
// without this the synthesizer throws "Could not find Verity skill data"
|
|
17830
17525
|
// for every test and every `verity` run from source. Resolved from this
|
|
17831
17526
|
// module's own location, never the cwd: see the warning below.
|
|
17832
|
-
(0,
|
|
17527
|
+
(0, import_node_path21.join)(__dirname, "..", "..", "client"),
|
|
17833
17528
|
// bundled: cli/bin/ → ../../client
|
|
17834
|
-
(0,
|
|
17529
|
+
(0, import_node_path21.join)(__dirname, "..", "..", "..", "client"),
|
|
17835
17530
|
// tsx: cli/src/lib/ → ../../../client
|
|
17836
17531
|
...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
|
|
17837
17532
|
];
|
|
17838
17533
|
for (const candidate of candidates2) {
|
|
17839
|
-
if ((0,
|
|
17534
|
+
if ((0, import_node_fs23.existsSync)((0, import_node_path21.join)(candidate, "skills"))) {
|
|
17840
17535
|
return candidate;
|
|
17841
17536
|
}
|
|
17842
17537
|
}
|
|
@@ -17845,13 +17540,13 @@ function resolveDataDir() {
|
|
|
17845
17540
|
);
|
|
17846
17541
|
}
|
|
17847
17542
|
function setupDataPath(file) {
|
|
17848
|
-
return (0,
|
|
17543
|
+
return (0, import_node_path21.join)(resolveDataDir(), "skills", "verity-setup", file);
|
|
17849
17544
|
}
|
|
17850
17545
|
|
|
17851
17546
|
// src/lib/detect.ts
|
|
17852
17547
|
var import_node_child_process8 = require("node:child_process");
|
|
17853
|
-
var
|
|
17854
|
-
var
|
|
17548
|
+
var import_node_fs24 = require("node:fs");
|
|
17549
|
+
var import_node_path22 = require("node:path");
|
|
17855
17550
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
17856
17551
|
"typescript",
|
|
17857
17552
|
"javascript",
|
|
@@ -17908,25 +17603,25 @@ function walk(root) {
|
|
|
17908
17603
|
if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
|
|
17909
17604
|
let entries;
|
|
17910
17605
|
try {
|
|
17911
|
-
entries = (0,
|
|
17606
|
+
entries = (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true });
|
|
17912
17607
|
} catch {
|
|
17913
17608
|
return;
|
|
17914
17609
|
}
|
|
17915
17610
|
for (const entry of entries) {
|
|
17916
17611
|
if (found.length >= WALK_MAX_FILES) return;
|
|
17917
17612
|
if (IGNORED_SEGMENTS.includes(entry.name)) continue;
|
|
17918
|
-
const full = (0,
|
|
17613
|
+
const full = (0, import_node_path22.join)(dir, entry.name);
|
|
17919
17614
|
if (entry.isDirectory()) visit(full, depth + 1);
|
|
17920
|
-
else if (entry.isFile()) found.push((0,
|
|
17615
|
+
else if (entry.isFile()) found.push((0, import_node_path22.relative)(root, full));
|
|
17921
17616
|
}
|
|
17922
17617
|
};
|
|
17923
17618
|
visit(root, 0);
|
|
17924
17619
|
return found;
|
|
17925
17620
|
}
|
|
17926
17621
|
function languageOf(path) {
|
|
17927
|
-
const name = (0,
|
|
17622
|
+
const name = (0, import_node_path22.basename)(path);
|
|
17928
17623
|
if (/^Dockerfile(\..+)?$/i.test(name)) return "dockerfile";
|
|
17929
|
-
if (!(0,
|
|
17624
|
+
if (!(0, import_node_path22.extname)(name)) return null;
|
|
17930
17625
|
const lang = detectLanguage(path);
|
|
17931
17626
|
return lang || null;
|
|
17932
17627
|
}
|
|
@@ -17983,7 +17678,7 @@ var TOOL_CONFIG_MARKERS = [
|
|
|
17983
17678
|
];
|
|
17984
17679
|
function readJson(path) {
|
|
17985
17680
|
try {
|
|
17986
|
-
return JSON.parse((0,
|
|
17681
|
+
return JSON.parse((0, import_node_fs24.readFileSync)(path, "utf-8"));
|
|
17987
17682
|
} catch {
|
|
17988
17683
|
return null;
|
|
17989
17684
|
}
|
|
@@ -18008,17 +17703,17 @@ function declaredDependencies(root, files) {
|
|
|
18008
17703
|
if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
|
|
18009
17704
|
}
|
|
18010
17705
|
};
|
|
18011
|
-
readPackageJson((0,
|
|
18012
|
-
const nested = files.filter((f) => f.includes("/") && (0,
|
|
18013
|
-
for (const rel of nested) readPackageJson((0,
|
|
17706
|
+
readPackageJson((0, import_node_path22.join)(root, "package.json"));
|
|
17707
|
+
const nested = files.filter((f) => f.includes("/") && (0, import_node_path22.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
|
|
17708
|
+
for (const rel of nested) readPackageJson((0, import_node_path22.join)(root, rel));
|
|
18014
17709
|
const pythonManifests = [
|
|
18015
|
-
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0,
|
|
18016
|
-
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0,
|
|
17710
|
+
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path22.join)(root, f)),
|
|
17711
|
+
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path22.join)(root, f))
|
|
18017
17712
|
];
|
|
18018
17713
|
for (const path of pythonManifests) {
|
|
18019
|
-
if (!(0,
|
|
17714
|
+
if (!(0, import_node_fs24.existsSync)(path)) continue;
|
|
18020
17715
|
try {
|
|
18021
|
-
const text = (0,
|
|
17716
|
+
const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
|
|
18022
17717
|
for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
18023
17718
|
for (const line of text.split("\n")) {
|
|
18024
17719
|
if (!/dependencies\s*=/.test(line)) continue;
|
|
@@ -18028,13 +17723,13 @@ function declaredDependencies(root, files) {
|
|
|
18028
17723
|
}
|
|
18029
17724
|
}
|
|
18030
17725
|
const goMods = [
|
|
18031
|
-
(0,
|
|
18032
|
-
...files.filter((f) => f.includes("/") && (0,
|
|
17726
|
+
(0, import_node_path22.join)(root, "go.mod"),
|
|
17727
|
+
...files.filter((f) => f.includes("/") && (0, import_node_path22.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path22.join)(root, f))
|
|
18033
17728
|
];
|
|
18034
17729
|
for (const path of goMods) {
|
|
18035
|
-
if (!(0,
|
|
17730
|
+
if (!(0, import_node_fs24.existsSync)(path)) continue;
|
|
18036
17731
|
try {
|
|
18037
|
-
const text = (0,
|
|
17732
|
+
const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
|
|
18038
17733
|
for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
18039
17734
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
18040
17735
|
}
|
|
@@ -18042,10 +17737,10 @@ function declaredDependencies(root, files) {
|
|
|
18042
17737
|
}
|
|
18043
17738
|
}
|
|
18044
17739
|
for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
|
|
18045
|
-
const path = (0,
|
|
18046
|
-
if (!(0,
|
|
17740
|
+
const path = (0, import_node_path22.join)(root, file);
|
|
17741
|
+
if (!(0, import_node_fs24.existsSync)(path)) continue;
|
|
18047
17742
|
try {
|
|
18048
|
-
const text = (0,
|
|
17743
|
+
const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
|
|
18049
17744
|
for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
18050
17745
|
} catch {
|
|
18051
17746
|
}
|
|
@@ -18053,7 +17748,7 @@ function declaredDependencies(root, files) {
|
|
|
18053
17748
|
return names2;
|
|
18054
17749
|
}
|
|
18055
17750
|
function detectBuildSystem(root, files) {
|
|
18056
|
-
const has = (f) => (0,
|
|
17751
|
+
const has = (f) => (0, import_node_fs24.existsSync)((0, import_node_path22.join)(root, f)) || files.some((p) => (0, import_node_path22.basename)(p) === f);
|
|
18057
17752
|
if (has("pnpm-lock.yaml")) return "pnpm";
|
|
18058
17753
|
if (has("yarn.lock")) return "yarn";
|
|
18059
17754
|
if (has("bun.lock") || has("bun.lockb")) return "bun";
|
|
@@ -18070,8 +17765,8 @@ function detectBuildSystem(root, files) {
|
|
|
18070
17765
|
}
|
|
18071
17766
|
function detectArchitecture(root, files) {
|
|
18072
17767
|
const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
|
|
18073
|
-
if (workspaceMarkers.some((m) => (0,
|
|
18074
|
-
const pkg = readJson((0,
|
|
17768
|
+
if (workspaceMarkers.some((m) => (0, import_node_fs24.existsSync)((0, import_node_path22.join)(root, m)))) return "monorepo";
|
|
17769
|
+
const pkg = readJson((0, import_node_path22.join)(root, "package.json"));
|
|
18075
17770
|
if (pkg && "workspaces" in pkg) return "monorepo";
|
|
18076
17771
|
const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
|
|
18077
17772
|
const nested = manifests.filter((f) => f.includes("/"));
|
|
@@ -18093,10 +17788,10 @@ function measureAvgFileLength(root, files, languages) {
|
|
|
18093
17788
|
let total = 0;
|
|
18094
17789
|
let counted = 0;
|
|
18095
17790
|
for (let i = 0; i < candidates2.length; i += stride) {
|
|
18096
|
-
const path = (0,
|
|
17791
|
+
const path = (0, import_node_path22.join)(root, candidates2[i]);
|
|
18097
17792
|
try {
|
|
18098
|
-
if ((0,
|
|
18099
|
-
total += (0,
|
|
17793
|
+
if ((0, import_node_fs24.statSync)(path).size > 2 * 1024 * 1024) continue;
|
|
17794
|
+
total += (0, import_node_fs24.readFileSync)(path, "utf-8").split("\n").length;
|
|
18100
17795
|
counted++;
|
|
18101
17796
|
} catch {
|
|
18102
17797
|
}
|
|
@@ -18126,14 +17821,14 @@ function detectProject(root = repoRoot()) {
|
|
|
18126
17821
|
const existingToolConfigs = [];
|
|
18127
17822
|
for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
|
|
18128
17823
|
for (const marker of markers) {
|
|
18129
|
-
if ((0,
|
|
17824
|
+
if ((0, import_node_fs24.existsSync)((0, import_node_path22.join)(root, marker))) {
|
|
18130
17825
|
existingToolConfigs.push({ tool, path: `./${marker}` });
|
|
18131
17826
|
break;
|
|
18132
17827
|
}
|
|
18133
17828
|
}
|
|
18134
17829
|
}
|
|
18135
17830
|
return {
|
|
18136
|
-
projectName: (0,
|
|
17831
|
+
projectName: (0, import_node_path22.basename)(root),
|
|
18137
17832
|
languages,
|
|
18138
17833
|
languageCounts,
|
|
18139
17834
|
frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
|
|
@@ -18231,8 +17926,8 @@ ${closingNote(input.origin)}
|
|
|
18231
17926
|
|
|
18232
17927
|
// src/lib/synthesize.ts
|
|
18233
17928
|
function loadCatalog() {
|
|
18234
|
-
const catalog = (0, import_yaml.parse)((0,
|
|
18235
|
-
const template = (0, import_yaml.parse)((0,
|
|
17929
|
+
const catalog = (0, import_yaml.parse)((0, import_node_fs25.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
|
|
17930
|
+
const template = (0, import_yaml.parse)((0, import_node_fs25.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
|
|
18236
17931
|
return { catalog, template };
|
|
18237
17932
|
}
|
|
18238
17933
|
function selectTools(languages, intensity, catalog) {
|
|
@@ -18510,7 +18205,7 @@ function validatePatternIds() {
|
|
|
18510
18205
|
}
|
|
18511
18206
|
async function runSynthesis(opts) {
|
|
18512
18207
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18513
|
-
if ((0,
|
|
18208
|
+
if ((0, import_node_fs25.existsSync)(standardPath) && !opts.force) {
|
|
18514
18209
|
return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
|
|
18515
18210
|
}
|
|
18516
18211
|
const detected = opts.detected ?? detectProject();
|
|
@@ -18579,8 +18274,8 @@ async function correctVerityMdVersion(opts) {
|
|
|
18579
18274
|
}
|
|
18580
18275
|
async function writeFileTo(relative2, body) {
|
|
18581
18276
|
const target = projectPath(relative2);
|
|
18582
|
-
await (0,
|
|
18583
|
-
await (0,
|
|
18277
|
+
await (0, import_promises9.mkdir)((0, import_node_path23.dirname)(target), { recursive: true });
|
|
18278
|
+
await (0, import_promises9.writeFile)(target, body);
|
|
18584
18279
|
}
|
|
18585
18280
|
async function deriveConfigForStandard(standard) {
|
|
18586
18281
|
const spec = standard.knowledge_spec ?? {};
|
|
@@ -18637,14 +18332,14 @@ ${validation.detail}`);
|
|
|
18637
18332
|
}
|
|
18638
18333
|
|
|
18639
18334
|
// src/lib/setup-state.ts
|
|
18640
|
-
var
|
|
18641
|
-
var
|
|
18335
|
+
var import_promises10 = require("node:fs/promises");
|
|
18336
|
+
var import_node_fs26 = require("node:fs");
|
|
18642
18337
|
var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
|
|
18643
18338
|
async function readSetupState() {
|
|
18644
18339
|
const path = projectPath(SETUP_STATE_FILE);
|
|
18645
|
-
if (!(0,
|
|
18340
|
+
if (!(0, import_node_fs26.existsSync)(path)) return null;
|
|
18646
18341
|
try {
|
|
18647
|
-
const parsed = JSON.parse(await (0,
|
|
18342
|
+
const parsed = JSON.parse(await (0, import_promises10.readFile)(path, "utf-8"));
|
|
18648
18343
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
18649
18344
|
} catch {
|
|
18650
18345
|
return null;
|
|
@@ -18658,12 +18353,12 @@ async function writeSetupState(patch) {
|
|
|
18658
18353
|
}
|
|
18659
18354
|
|
|
18660
18355
|
// src/lib/push-setup.ts
|
|
18661
|
-
var
|
|
18662
|
-
var
|
|
18356
|
+
var import_node_fs28 = require("node:fs");
|
|
18357
|
+
var import_promises11 = require("node:fs/promises");
|
|
18663
18358
|
var import_yaml2 = __toESM(require_dist());
|
|
18664
18359
|
|
|
18665
18360
|
// src/lib/verityignore.ts
|
|
18666
|
-
var
|
|
18361
|
+
var import_node_fs27 = require("node:fs");
|
|
18667
18362
|
var EMPTY = { rules: [], securityOverlap: [], problems: [] };
|
|
18668
18363
|
var SECURITY_PROBES = [
|
|
18669
18364
|
".env",
|
|
@@ -18756,9 +18451,9 @@ function isIgnored3(ig, path) {
|
|
|
18756
18451
|
}
|
|
18757
18452
|
function loadVerityIgnore() {
|
|
18758
18453
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
18759
|
-
if (!(0,
|
|
18454
|
+
if (!(0, import_node_fs27.existsSync)(file)) return EMPTY;
|
|
18760
18455
|
try {
|
|
18761
|
-
return parseVerityIgnore((0,
|
|
18456
|
+
return parseVerityIgnore((0, import_node_fs27.readFileSync)(file, "utf-8"));
|
|
18762
18457
|
} catch {
|
|
18763
18458
|
return EMPTY;
|
|
18764
18459
|
}
|
|
@@ -18796,9 +18491,9 @@ function buildStandardUpload(standard, ignoreRaw) {
|
|
|
18796
18491
|
}
|
|
18797
18492
|
function readVerityIgnoreRaw() {
|
|
18798
18493
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
18799
|
-
if (!(0,
|
|
18494
|
+
if (!(0, import_node_fs27.existsSync)(file)) return null;
|
|
18800
18495
|
try {
|
|
18801
|
-
return (0,
|
|
18496
|
+
return (0, import_node_fs27.readFileSync)(file, "utf-8");
|
|
18802
18497
|
} catch {
|
|
18803
18498
|
return null;
|
|
18804
18499
|
}
|
|
@@ -18826,9 +18521,9 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
18826
18521
|
}
|
|
18827
18522
|
let standardVersion = null;
|
|
18828
18523
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18829
|
-
if (pushStandard && (0,
|
|
18524
|
+
if (pushStandard && (0, import_node_fs28.existsSync)(standardPath)) {
|
|
18830
18525
|
try {
|
|
18831
|
-
const content = (0, import_yaml2.parse)(await (0,
|
|
18526
|
+
const content = (0, import_yaml2.parse)(await (0, import_promises11.readFile)(standardPath, "utf-8"));
|
|
18832
18527
|
const upload = buildStandardUpload(content, readVerityIgnoreRaw());
|
|
18833
18528
|
if (upload.warning) lines.push(upload.warning);
|
|
18834
18529
|
const result = await apiRequest({
|
|
@@ -18851,9 +18546,9 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
18851
18546
|
}
|
|
18852
18547
|
let configPushed = false;
|
|
18853
18548
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
18854
|
-
if (pushConfig && (0,
|
|
18549
|
+
if (pushConfig && (0, import_node_fs28.existsSync)(configPath)) {
|
|
18855
18550
|
try {
|
|
18856
|
-
const content = JSON.parse(await (0,
|
|
18551
|
+
const content = JSON.parse(await (0, import_promises11.readFile)(configPath, "utf-8"));
|
|
18857
18552
|
const result = await apiRequest({
|
|
18858
18553
|
method: "POST",
|
|
18859
18554
|
path: "/analysis-configs",
|
|
@@ -18883,11 +18578,11 @@ function registerStandardCommands(program2) {
|
|
|
18883
18578
|
const state = await readSetupState();
|
|
18884
18579
|
if (opts.configOnly) {
|
|
18885
18580
|
const standardPath = projectPath(STANDARD_FILE);
|
|
18886
|
-
if (!(0,
|
|
18581
|
+
if (!(0, import_node_fs29.existsSync)(standardPath)) {
|
|
18887
18582
|
printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
|
|
18888
18583
|
process.exit(1);
|
|
18889
18584
|
}
|
|
18890
|
-
const content = (0, import_yaml3.parse)(await (0,
|
|
18585
|
+
const content = (0, import_yaml3.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
|
|
18891
18586
|
const derived = await deriveConfigForStandard(content);
|
|
18892
18587
|
for (const path of derived.written) printInfo(` ${path} \u2713`);
|
|
18893
18588
|
for (const note of derived.notes) printWarn(` ${note}`);
|
|
@@ -18943,7 +18638,7 @@ function registerStandardCommands(program2) {
|
|
|
18943
18638
|
}
|
|
18944
18639
|
let yamlContent;
|
|
18945
18640
|
try {
|
|
18946
|
-
yamlContent = await (0,
|
|
18641
|
+
yamlContent = await (0, import_promises12.readFile)(opts.file, "utf-8");
|
|
18947
18642
|
} catch {
|
|
18948
18643
|
printError(`Cannot read ${opts.file}`);
|
|
18949
18644
|
process.exit(1);
|
|
@@ -19040,7 +18735,7 @@ function parseIntensity(value) {
|
|
|
19040
18735
|
}
|
|
19041
18736
|
|
|
19042
18737
|
// src/commands/config.ts
|
|
19043
|
-
var
|
|
18738
|
+
var import_promises13 = require("node:fs/promises");
|
|
19044
18739
|
function registerConfigCommands(program2) {
|
|
19045
18740
|
const config = program2.command("config").description("Manage analysis configuration");
|
|
19046
18741
|
config.command("service-url").description("Print the resolved service URL (used by the shipped skills)").action(async () => {
|
|
@@ -19086,7 +18781,7 @@ function registerConfigCommands(program2) {
|
|
|
19086
18781
|
}
|
|
19087
18782
|
let content;
|
|
19088
18783
|
try {
|
|
19089
|
-
const raw = await (0,
|
|
18784
|
+
const raw = await (0, import_promises13.readFile)(opts.file, "utf-8");
|
|
19090
18785
|
content = JSON.parse(raw);
|
|
19091
18786
|
} catch {
|
|
19092
18787
|
printError(`Cannot read or parse ${opts.file}`);
|
|
@@ -19214,10 +18909,10 @@ function formatRunDetail(run2) {
|
|
|
19214
18909
|
}
|
|
19215
18910
|
|
|
19216
18911
|
// src/lib/ignore-declaration.ts
|
|
19217
|
-
var
|
|
18912
|
+
var import_node_fs31 = require("node:fs");
|
|
19218
18913
|
|
|
19219
18914
|
// src/lib/debounce.ts
|
|
19220
|
-
var
|
|
18915
|
+
var import_node_fs30 = require("node:fs");
|
|
19221
18916
|
var import_node_crypto10 = require("node:crypto");
|
|
19222
18917
|
function scopedFile(base, sessionId) {
|
|
19223
18918
|
if (!sessionId) return base;
|
|
@@ -19225,9 +18920,9 @@ function scopedFile(base, sessionId) {
|
|
|
19225
18920
|
}
|
|
19226
18921
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
19227
18922
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19228
|
-
if (!(0,
|
|
18923
|
+
if (!(0, import_node_fs30.existsSync)(file)) return null;
|
|
19229
18924
|
try {
|
|
19230
|
-
const lastTs = parseInt((0,
|
|
18925
|
+
const lastTs = parseInt((0, import_node_fs30.readFileSync)(file, "utf-8").trim(), 10);
|
|
19231
18926
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
19232
18927
|
const elapsed = nowTs - lastTs;
|
|
19233
18928
|
if (elapsed < debounceSeconds) {
|
|
@@ -19240,10 +18935,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
|
19240
18935
|
function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
19241
18936
|
if (bypassForRecentCommits) return null;
|
|
19242
18937
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19243
|
-
if (!(0,
|
|
18938
|
+
if (!(0, import_node_fs30.existsSync)(file)) return null;
|
|
19244
18939
|
let debounceTime;
|
|
19245
18940
|
try {
|
|
19246
|
-
debounceTime = (0,
|
|
18941
|
+
debounceTime = (0, import_node_fs30.statSync)(file).mtimeMs;
|
|
19247
18942
|
} catch {
|
|
19248
18943
|
return null;
|
|
19249
18944
|
}
|
|
@@ -19251,7 +18946,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
19251
18946
|
const resolved = resolveFile(f);
|
|
19252
18947
|
if (!resolved) continue;
|
|
19253
18948
|
try {
|
|
19254
|
-
const stat3 = (0,
|
|
18949
|
+
const stat3 = (0, import_node_fs30.statSync)(resolved);
|
|
19255
18950
|
if (stat3.mtimeMs > debounceTime) {
|
|
19256
18951
|
return null;
|
|
19257
18952
|
}
|
|
@@ -19267,8 +18962,8 @@ function computeContentHash(files) {
|
|
|
19267
18962
|
for (const f of sorted) {
|
|
19268
18963
|
const resolved = resolveFile(f) ?? f;
|
|
19269
18964
|
try {
|
|
19270
|
-
if ((0,
|
|
19271
|
-
hash.update((0,
|
|
18965
|
+
if ((0, import_node_fs30.existsSync)(resolved)) {
|
|
18966
|
+
hash.update((0, import_node_fs30.readFileSync)(resolved));
|
|
19272
18967
|
}
|
|
19273
18968
|
} catch {
|
|
19274
18969
|
}
|
|
@@ -19278,9 +18973,9 @@ function computeContentHash(files) {
|
|
|
19278
18973
|
function checkContentHash(files, sessionId) {
|
|
19279
18974
|
const hash = computeContentHash(files);
|
|
19280
18975
|
const file = scopedFile(HASH_FILE, sessionId);
|
|
19281
|
-
if ((0,
|
|
18976
|
+
if ((0, import_node_fs30.existsSync)(file)) {
|
|
19282
18977
|
try {
|
|
19283
|
-
const storedHash = (0,
|
|
18978
|
+
const storedHash = (0, import_node_fs30.readFileSync)(file, "utf-8").trim();
|
|
19284
18979
|
if (hash === storedHash) {
|
|
19285
18980
|
return { skip: "No source changes since last analysis", hash };
|
|
19286
18981
|
}
|
|
@@ -19290,24 +18985,24 @@ function checkContentHash(files, sessionId) {
|
|
|
19290
18985
|
return { skip: null, hash };
|
|
19291
18986
|
}
|
|
19292
18987
|
function recordAnalysisStart(sessionId) {
|
|
19293
|
-
(0,
|
|
19294
|
-
(0,
|
|
18988
|
+
(0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
18989
|
+
(0, import_node_fs30.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
|
|
19295
18990
|
}
|
|
19296
18991
|
function recordPassHash(hash, sessionId) {
|
|
19297
|
-
(0,
|
|
18992
|
+
(0, import_node_fs30.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
|
|
19298
18993
|
}
|
|
19299
18994
|
function narrowToRecent(files, sessionId) {
|
|
19300
18995
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
19301
|
-
if (!(0,
|
|
18996
|
+
if (!(0, import_node_fs30.existsSync)(file)) return files;
|
|
19302
18997
|
let debounceTime;
|
|
19303
18998
|
try {
|
|
19304
|
-
debounceTime = (0,
|
|
18999
|
+
debounceTime = (0, import_node_fs30.statSync)(file).mtimeMs;
|
|
19305
19000
|
} catch {
|
|
19306
19001
|
return files;
|
|
19307
19002
|
}
|
|
19308
19003
|
const recent = files.filter((f) => {
|
|
19309
19004
|
try {
|
|
19310
|
-
return (0,
|
|
19005
|
+
return (0, import_node_fs30.existsSync)(f) && (0, import_node_fs30.statSync)(f).mtimeMs > debounceTime;
|
|
19311
19006
|
} catch {
|
|
19312
19007
|
return false;
|
|
19313
19008
|
}
|
|
@@ -19320,9 +19015,9 @@ function readIteration(currentCommit, _contentHash) {
|
|
|
19320
19015
|
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
19321
19016
|
function readBlockState(currentCommit, opts) {
|
|
19322
19017
|
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
19323
|
-
if (!(0,
|
|
19018
|
+
if (!(0, import_node_fs30.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
19324
19019
|
try {
|
|
19325
|
-
const stored = (0,
|
|
19020
|
+
const stored = (0, import_node_fs30.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
19326
19021
|
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
19327
19022
|
if (!parsed) return NO_BLOCKS;
|
|
19328
19023
|
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
@@ -19368,8 +19063,8 @@ function isSameProblem(previous, current) {
|
|
|
19368
19063
|
return current.split(",").some((k) => prev.has(k));
|
|
19369
19064
|
}
|
|
19370
19065
|
function writeBlockState(commit, state) {
|
|
19371
|
-
(0,
|
|
19372
|
-
(0,
|
|
19066
|
+
(0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
19067
|
+
(0, import_node_fs30.writeFileSync)(
|
|
19373
19068
|
ITERATION_FILE,
|
|
19374
19069
|
JSON.stringify({
|
|
19375
19070
|
v: 2,
|
|
@@ -19474,9 +19169,9 @@ function resolveIgnoreState(keys) {
|
|
|
19474
19169
|
}
|
|
19475
19170
|
function readIgnoreState(sessionId) {
|
|
19476
19171
|
const file = stateFile(sessionId);
|
|
19477
|
-
if (!(0,
|
|
19172
|
+
if (!(0, import_node_fs31.existsSync)(file)) return null;
|
|
19478
19173
|
try {
|
|
19479
|
-
const o = JSON.parse((0,
|
|
19174
|
+
const o = JSON.parse((0, import_node_fs31.readFileSync)(file, "utf-8")) ?? {};
|
|
19480
19175
|
const spent = typeof o.spent === "number" ? o.spent : 0;
|
|
19481
19176
|
const raw = o.active;
|
|
19482
19177
|
let active = null;
|
|
@@ -19500,8 +19195,8 @@ function readIgnoreState(sessionId) {
|
|
|
19500
19195
|
}
|
|
19501
19196
|
function writeIgnoreState(state, sessionId) {
|
|
19502
19197
|
try {
|
|
19503
|
-
(0,
|
|
19504
|
-
(0,
|
|
19198
|
+
(0, import_node_fs31.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
19199
|
+
(0, import_node_fs31.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
|
|
19505
19200
|
} catch {
|
|
19506
19201
|
}
|
|
19507
19202
|
}
|
|
@@ -19884,7 +19579,7 @@ function createRun(opts, globals) {
|
|
|
19884
19579
|
}
|
|
19885
19580
|
|
|
19886
19581
|
// src/commands/analyze/index.ts
|
|
19887
|
-
var
|
|
19582
|
+
var import_node_fs44 = require("node:fs");
|
|
19888
19583
|
|
|
19889
19584
|
// src/lib/repo-context.ts
|
|
19890
19585
|
var import_node_child_process10 = require("node:child_process");
|
|
@@ -20712,10 +20407,10 @@ function installRunEvidence(run2) {
|
|
|
20712
20407
|
}
|
|
20713
20408
|
|
|
20714
20409
|
// src/lib/git-frame.ts
|
|
20715
|
-
var
|
|
20410
|
+
var import_node_fs32 = require("node:fs");
|
|
20716
20411
|
var import_node_os5 = require("node:os");
|
|
20412
|
+
var import_node_path24 = require("node:path");
|
|
20717
20413
|
var import_node_path25 = require("node:path");
|
|
20718
|
-
var import_node_path26 = require("node:path");
|
|
20719
20414
|
|
|
20720
20415
|
// src/lib/hardened-git.ts
|
|
20721
20416
|
var import_node_child_process11 = require("node:child_process");
|
|
@@ -20877,8 +20572,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
20877
20572
|
if (SHELL_DYNAMIC.test(raw) || raw === "-") {
|
|
20878
20573
|
return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
|
|
20879
20574
|
}
|
|
20880
|
-
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0,
|
|
20881
|
-
dir = (0,
|
|
20575
|
+
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path25.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
|
|
20576
|
+
dir = (0, import_node_path24.isAbsolute)(expanded) ? expanded : (0, import_node_path24.resolve)(dir, expanded);
|
|
20882
20577
|
}
|
|
20883
20578
|
const seg = segments[segmentIndex];
|
|
20884
20579
|
const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
|
|
@@ -20896,8 +20591,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
20896
20591
|
if (SHELL_DYNAMIC.test(raw)) {
|
|
20897
20592
|
return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
|
|
20898
20593
|
}
|
|
20899
|
-
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0,
|
|
20900
|
-
dir = (0,
|
|
20594
|
+
const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path25.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
|
|
20595
|
+
dir = (0, import_node_path24.isAbsolute)(expanded) ? expanded : (0, import_node_path24.resolve)(dir, expanded);
|
|
20901
20596
|
}
|
|
20902
20597
|
}
|
|
20903
20598
|
return { dir, named, unresolvable: null };
|
|
@@ -20957,14 +20652,14 @@ function gitAt(dir, args) {
|
|
|
20957
20652
|
}
|
|
20958
20653
|
function realpathOr2(p) {
|
|
20959
20654
|
try {
|
|
20960
|
-
return
|
|
20655
|
+
return import_node_fs32.realpathSync.native(p);
|
|
20961
20656
|
} catch {
|
|
20962
|
-
return (0,
|
|
20657
|
+
return (0, import_node_path24.resolve)(p);
|
|
20963
20658
|
}
|
|
20964
20659
|
}
|
|
20965
20660
|
function resolveFrame(input) {
|
|
20966
20661
|
const found = findMomentSegment(input.command, input.on);
|
|
20967
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
20662
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs32.existsSync)(input.hookCwd);
|
|
20968
20663
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
20969
20664
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
20970
20665
|
const refuse = (refusal) => ({
|
|
@@ -20987,7 +20682,7 @@ function resolveFrame(input) {
|
|
|
20987
20682
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
20988
20683
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
20989
20684
|
if (targetDir !== baseDir) {
|
|
20990
|
-
if (!(0,
|
|
20685
|
+
if (!(0, import_node_fs32.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
20991
20686
|
dir = targetDir;
|
|
20992
20687
|
}
|
|
20993
20688
|
}
|
|
@@ -20998,7 +20693,7 @@ function resolveFrame(input) {
|
|
|
20998
20693
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
20999
20694
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
21000
20695
|
const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
|
|
21001
|
-
const commonDir = commonRaw ? realpathOr2((0,
|
|
20696
|
+
const commonDir = commonRaw ? realpathOr2((0, import_node_path24.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path24.resolve)(dir, commonRaw)) : null;
|
|
21002
20697
|
const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
21003
20698
|
return {
|
|
21004
20699
|
moment: found?.moment ?? null,
|
|
@@ -21173,8 +20868,8 @@ function stagedRange(frame, command) {
|
|
|
21173
20868
|
if (plan.kind === "unpredictable") {
|
|
21174
20869
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
|
|
21175
20870
|
}
|
|
21176
|
-
const mergeHead = frame.gitDir ? (0,
|
|
21177
|
-
if (mergeHead && (0,
|
|
20871
|
+
const mergeHead = frame.gitDir ? (0, import_node_path25.join)(frame.gitDir, "MERGE_HEAD") : null;
|
|
20872
|
+
if (mergeHead && (0, import_node_fs32.existsSync)(mergeHead)) {
|
|
21178
20873
|
const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
|
|
21179
20874
|
const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
|
|
21180
20875
|
const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
|
|
@@ -21308,7 +21003,7 @@ function truthy(v) {
|
|
|
21308
21003
|
}
|
|
21309
21004
|
|
|
21310
21005
|
// src/lib/transcript.ts
|
|
21311
|
-
var
|
|
21006
|
+
var import_node_fs33 = require("node:fs");
|
|
21312
21007
|
var MAX_READ_BYTES = 256 * 1024;
|
|
21313
21008
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
21314
21009
|
var MAX_FILES_LIST = 20;
|
|
@@ -21335,7 +21030,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
21335
21030
|
function readTurnLines(transcriptPath) {
|
|
21336
21031
|
let size;
|
|
21337
21032
|
try {
|
|
21338
|
-
size = (0,
|
|
21033
|
+
size = (0, import_node_fs33.statSync)(transcriptPath).size;
|
|
21339
21034
|
} catch {
|
|
21340
21035
|
return null;
|
|
21341
21036
|
}
|
|
@@ -21343,7 +21038,7 @@ function readTurnLines(transcriptPath) {
|
|
|
21343
21038
|
let raw;
|
|
21344
21039
|
let windowed = false;
|
|
21345
21040
|
if (size <= SMALL_FILE_BYTES) {
|
|
21346
|
-
raw = (0,
|
|
21041
|
+
raw = (0, import_node_fs33.readFileSync)(transcriptPath, "utf-8");
|
|
21347
21042
|
} else {
|
|
21348
21043
|
windowed = true;
|
|
21349
21044
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -21851,7 +21546,7 @@ function channelSilence(input) {
|
|
|
21851
21546
|
// src/lib/cli-version.ts
|
|
21852
21547
|
function cliVersion() {
|
|
21853
21548
|
try {
|
|
21854
|
-
return true ? "0.32.6-experimental.
|
|
21549
|
+
return true ? "0.32.6-experimental.8f2b5f7" : "dev";
|
|
21855
21550
|
} catch {
|
|
21856
21551
|
return "dev";
|
|
21857
21552
|
}
|
|
@@ -21892,7 +21587,7 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
21892
21587
|
|
|
21893
21588
|
// src/lib/static-analysis.ts
|
|
21894
21589
|
var import_node_child_process12 = require("node:child_process");
|
|
21895
|
-
var
|
|
21590
|
+
var import_node_fs34 = require("node:fs");
|
|
21896
21591
|
var SEVERITY_ORDER = {
|
|
21897
21592
|
Error: 0,
|
|
21898
21593
|
Critical: 0,
|
|
@@ -21940,7 +21635,7 @@ function runCodacyAnalysis(files) {
|
|
|
21940
21635
|
if (files.length === 0) return empty;
|
|
21941
21636
|
const existingFiles = files.filter((f) => {
|
|
21942
21637
|
try {
|
|
21943
|
-
return (0,
|
|
21638
|
+
return (0, import_node_fs34.existsSync)(f);
|
|
21944
21639
|
} catch {
|
|
21945
21640
|
return false;
|
|
21946
21641
|
}
|
|
@@ -22209,8 +21904,8 @@ async function scope(run2) {
|
|
|
22209
21904
|
}
|
|
22210
21905
|
|
|
22211
21906
|
// src/lib/specs.ts
|
|
22212
|
-
var
|
|
22213
|
-
var
|
|
21907
|
+
var import_node_fs35 = require("node:fs");
|
|
21908
|
+
var import_node_path26 = require("node:path");
|
|
22214
21909
|
var SPEC_CANDIDATES = [
|
|
22215
21910
|
"CLAUDE.md",
|
|
22216
21911
|
"AGENTS.md",
|
|
@@ -22241,7 +21936,7 @@ function discoverSpecs(consulted = []) {
|
|
|
22241
21936
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
22242
21937
|
if (totalBytes >= totalCap) return false;
|
|
22243
21938
|
if (seen.has(specPath)) return true;
|
|
22244
|
-
if (!(0,
|
|
21939
|
+
if (!(0, import_node_fs35.existsSync)(specPath)) return true;
|
|
22245
21940
|
seen.add(specPath);
|
|
22246
21941
|
const remaining = totalCap - totalBytes;
|
|
22247
21942
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
@@ -22264,7 +21959,7 @@ function discoverSpecs(consulted = []) {
|
|
|
22264
21959
|
if (!addSpec(candidate)) break;
|
|
22265
21960
|
}
|
|
22266
21961
|
for (const dir of ["spec", "docs"]) {
|
|
22267
|
-
if (!(0,
|
|
21962
|
+
if (!(0, import_node_fs35.existsSync)(dir)) continue;
|
|
22268
21963
|
try {
|
|
22269
21964
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
22270
21965
|
for (const mdFile of mdFiles) {
|
|
@@ -22279,9 +21974,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
22279
21974
|
if (depth >= maxDepth) return [];
|
|
22280
21975
|
const result = [];
|
|
22281
21976
|
try {
|
|
22282
|
-
const entries = (0,
|
|
21977
|
+
const entries = (0, import_node_fs35.readdirSync)(dir, { withFileTypes: true });
|
|
22283
21978
|
for (const entry of entries) {
|
|
22284
|
-
const fullPath = (0,
|
|
21979
|
+
const fullPath = (0, import_node_path26.join)(dir, entry.name);
|
|
22285
21980
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
22286
21981
|
result.push(fullPath);
|
|
22287
21982
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -22294,25 +21989,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
22294
21989
|
}
|
|
22295
21990
|
function discoverPlans() {
|
|
22296
21991
|
const home = process.env.HOME ?? "";
|
|
22297
|
-
const homePlansDir = (0,
|
|
21992
|
+
const homePlansDir = (0, import_node_path26.join)(home, ".claude", "plans");
|
|
22298
21993
|
const sources = [];
|
|
22299
21994
|
if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
|
|
22300
|
-
sources.push({ root: process.cwd(), prefix: (0,
|
|
21995
|
+
sources.push({ root: process.cwd(), prefix: (0, import_node_path26.join)(".claude", "plans") });
|
|
22301
21996
|
}
|
|
22302
|
-
if (home && (0,
|
|
21997
|
+
if (home && (0, import_node_fs35.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
|
|
22303
21998
|
const candidates2 = [];
|
|
22304
21999
|
const seen = /* @__PURE__ */ new Set();
|
|
22305
22000
|
for (const source of sources) {
|
|
22306
22001
|
let names2;
|
|
22307
22002
|
try {
|
|
22308
|
-
names2 = (0,
|
|
22003
|
+
names2 = (0, import_node_fs35.readdirSync)(source.prefix ? (0, import_node_path26.join)(source.root, source.prefix) : source.root);
|
|
22309
22004
|
} catch {
|
|
22310
22005
|
continue;
|
|
22311
22006
|
}
|
|
22312
22007
|
for (const f of names2) {
|
|
22313
22008
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
22314
22009
|
seen.add(f);
|
|
22315
|
-
const relPath = source.prefix ? (0,
|
|
22010
|
+
const relPath = source.prefix ? (0, import_node_path26.join)(source.prefix, f) : f;
|
|
22316
22011
|
const stat3 = statRegularInRoot(source.root, relPath);
|
|
22317
22012
|
if (!stat3.ok) continue;
|
|
22318
22013
|
candidates2.push({ name: f, root: source.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -22330,9 +22025,9 @@ function discoverPlans() {
|
|
|
22330
22025
|
function isRealDirectoryChain(root, parts) {
|
|
22331
22026
|
let current = root;
|
|
22332
22027
|
for (const part of parts) {
|
|
22333
|
-
current = (0,
|
|
22028
|
+
current = (0, import_node_path26.join)(current, part);
|
|
22334
22029
|
try {
|
|
22335
|
-
if (!(0,
|
|
22030
|
+
if (!(0, import_node_fs35.lstatSync)(current).isDirectory()) return false;
|
|
22336
22031
|
} catch {
|
|
22337
22032
|
return false;
|
|
22338
22033
|
}
|
|
@@ -22347,7 +22042,7 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
22347
22042
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
22348
22043
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
22349
22044
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
22350
|
-
if (!(0,
|
|
22045
|
+
if (!(0, import_node_fs35.existsSync)(path)) continue;
|
|
22351
22046
|
const opened = openRegularInRoot(process.cwd(), path);
|
|
22352
22047
|
if (!opened.ok) continue;
|
|
22353
22048
|
if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
|
|
@@ -22533,8 +22228,8 @@ async function mode(run2) {
|
|
|
22533
22228
|
}
|
|
22534
22229
|
|
|
22535
22230
|
// src/lib/fold.ts
|
|
22536
|
-
var
|
|
22537
|
-
var
|
|
22231
|
+
var import_node_fs36 = require("node:fs");
|
|
22232
|
+
var import_node_path27 = require("node:path");
|
|
22538
22233
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
22539
22234
|
"user",
|
|
22540
22235
|
"assistant",
|
|
@@ -22671,7 +22366,7 @@ function candidateRoots(repoRoot2) {
|
|
|
22671
22366
|
const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
22672
22367
|
const out = [norm];
|
|
22673
22368
|
try {
|
|
22674
|
-
const real =
|
|
22369
|
+
const real = import_node_fs36.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
22675
22370
|
if (real !== norm) out.push(real);
|
|
22676
22371
|
} catch {
|
|
22677
22372
|
}
|
|
@@ -22759,31 +22454,31 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22759
22454
|
}
|
|
22760
22455
|
};
|
|
22761
22456
|
try {
|
|
22762
|
-
if (!(0,
|
|
22763
|
-
ingest((0,
|
|
22457
|
+
if (!(0, import_node_fs36.existsSync)(transcriptPath)) return result;
|
|
22458
|
+
ingest((0, import_node_fs36.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
22764
22459
|
result.coverage.complete = true;
|
|
22765
22460
|
} catch {
|
|
22766
22461
|
return result;
|
|
22767
22462
|
}
|
|
22768
22463
|
try {
|
|
22769
|
-
const sidecarDir = (0,
|
|
22770
|
-
(0,
|
|
22771
|
-
(0,
|
|
22464
|
+
const sidecarDir = (0, import_node_path27.join)(
|
|
22465
|
+
(0, import_node_path27.dirname)(transcriptPath),
|
|
22466
|
+
(0, import_node_path27.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
22772
22467
|
"subagents"
|
|
22773
22468
|
);
|
|
22774
|
-
if ((0,
|
|
22469
|
+
if ((0, import_node_fs36.existsSync)(sidecarDir)) {
|
|
22775
22470
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
22776
22471
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
22777
22472
|
const found = [];
|
|
22778
22473
|
const walk2 = (d, depth) => {
|
|
22779
22474
|
if (depth > 4) return;
|
|
22780
|
-
for (const e of (0,
|
|
22781
|
-
const p = (0,
|
|
22475
|
+
for (const e of (0, import_node_fs36.readdirSync)(d, { withFileTypes: true })) {
|
|
22476
|
+
const p = (0, import_node_path27.join)(d, e.name);
|
|
22782
22477
|
if (e.isDirectory()) {
|
|
22783
22478
|
walk2(p, depth + 1);
|
|
22784
22479
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
22785
22480
|
try {
|
|
22786
|
-
const st = (0,
|
|
22481
|
+
const st = (0, import_node_fs36.statSync)(p);
|
|
22787
22482
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
22788
22483
|
} catch {
|
|
22789
22484
|
result.coverage.malformed++;
|
|
@@ -22800,7 +22495,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22800
22495
|
continue;
|
|
22801
22496
|
}
|
|
22802
22497
|
try {
|
|
22803
|
-
ingest((0,
|
|
22498
|
+
ingest((0, import_node_fs36.readFileSync)(f.path, "utf8"), "subagent");
|
|
22804
22499
|
bytes += f.size;
|
|
22805
22500
|
result.coverage.subagentFiles++;
|
|
22806
22501
|
} catch {
|
|
@@ -22835,7 +22530,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
22835
22530
|
}
|
|
22836
22531
|
function classifyUnobserved(path) {
|
|
22837
22532
|
try {
|
|
22838
|
-
const st = (0,
|
|
22533
|
+
const st = (0, import_node_fs36.statSync)(path);
|
|
22839
22534
|
if (!st.isFile()) return "unreadable";
|
|
22840
22535
|
} catch {
|
|
22841
22536
|
return "unreadable";
|
|
@@ -23152,20 +22847,20 @@ async function evidence(run2) {
|
|
|
23152
22847
|
}
|
|
23153
22848
|
|
|
23154
22849
|
// src/lib/cache-cleanup.ts
|
|
23155
|
-
var
|
|
23156
|
-
var
|
|
22850
|
+
var import_node_fs37 = require("node:fs");
|
|
22851
|
+
var import_node_path28 = require("node:path");
|
|
23157
22852
|
var CACHE_TTL_DAYS = 7;
|
|
23158
22853
|
function pruneStaleCache() {
|
|
23159
22854
|
try {
|
|
23160
22855
|
const dir = projectPath(CACHE_DIR);
|
|
23161
22856
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
23162
|
-
for (const entry of (0,
|
|
22857
|
+
for (const entry of (0, import_node_fs37.readdirSync)(dir)) {
|
|
23163
22858
|
if (!entry.startsWith("pending-")) continue;
|
|
23164
|
-
const path = (0,
|
|
22859
|
+
const path = (0, import_node_path28.join)(dir, entry);
|
|
23165
22860
|
try {
|
|
23166
|
-
const stat3 = (0,
|
|
22861
|
+
const stat3 = (0, import_node_fs37.statSync)(path);
|
|
23167
22862
|
if (stat3.mtimeMs < cutoff) {
|
|
23168
|
-
(0,
|
|
22863
|
+
(0, import_node_fs37.unlinkSync)(path);
|
|
23169
22864
|
logEvent("cache_entry_pruned", {
|
|
23170
22865
|
path: entry,
|
|
23171
22866
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -23179,7 +22874,7 @@ function pruneStaleCache() {
|
|
|
23179
22874
|
}
|
|
23180
22875
|
|
|
23181
22876
|
// src/lib/context-files.ts
|
|
23182
|
-
var
|
|
22877
|
+
var import_node_fs38 = require("node:fs");
|
|
23183
22878
|
var import_node_os6 = require("node:os");
|
|
23184
22879
|
var MAX_CONTEXT_FILES = 10;
|
|
23185
22880
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
@@ -23237,7 +22932,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
23237
22932
|
continue;
|
|
23238
22933
|
}
|
|
23239
22934
|
try {
|
|
23240
|
-
const content = (0,
|
|
22935
|
+
const content = (0, import_node_fs38.readFileSync)(safePath, "utf8");
|
|
23241
22936
|
const bytes = Buffer.byteLength(content);
|
|
23242
22937
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
23243
22938
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -23327,9 +23022,9 @@ async function repoContext(run2) {
|
|
|
23327
23022
|
}
|
|
23328
23023
|
|
|
23329
23024
|
// src/lib/seed-runner.ts
|
|
23330
|
-
var
|
|
23331
|
-
var
|
|
23332
|
-
var
|
|
23025
|
+
var import_promises14 = require("node:fs/promises");
|
|
23026
|
+
var import_node_fs39 = require("node:fs");
|
|
23027
|
+
var import_node_path29 = require("node:path");
|
|
23333
23028
|
var import_yaml4 = __toESM(require_dist());
|
|
23334
23029
|
|
|
23335
23030
|
// src/lib/seed.ts
|
|
@@ -23405,7 +23100,7 @@ function classifyClaudeSection(heading) {
|
|
|
23405
23100
|
if (hasAny(["integration", "webhook", "third-party", "third party", "provider"])) return "integration";
|
|
23406
23101
|
return "domain";
|
|
23407
23102
|
}
|
|
23408
|
-
function
|
|
23103
|
+
function slugify(s) {
|
|
23409
23104
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
23410
23105
|
}
|
|
23411
23106
|
var FRAMEWORK_GLOBS = [
|
|
@@ -23502,7 +23197,7 @@ _Extracted from README on setup. Update when project direction changes._`,
|
|
|
23502
23197
|
for (const fwRaw of frameworks) {
|
|
23503
23198
|
const fw = fwRaw.trim();
|
|
23504
23199
|
if (!fw) continue;
|
|
23505
|
-
const slug =
|
|
23200
|
+
const slug = slugify(fw);
|
|
23506
23201
|
if (!slug || seenFrameworkSlugs.has(slug)) continue;
|
|
23507
23202
|
seenFrameworkSlugs.add(slug);
|
|
23508
23203
|
out.push({
|
|
@@ -23568,29 +23263,29 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
23568
23263
|
return fm;
|
|
23569
23264
|
}
|
|
23570
23265
|
async function runSeed(opts) {
|
|
23571
|
-
if (!(0,
|
|
23266
|
+
if (!(0, import_node_fs39.existsSync)(STANDARD_FILE)) {
|
|
23572
23267
|
return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
23573
23268
|
}
|
|
23574
23269
|
let standardDoc;
|
|
23575
23270
|
try {
|
|
23576
|
-
const raw = await (0,
|
|
23271
|
+
const raw = await (0, import_promises14.readFile)(STANDARD_FILE, "utf-8");
|
|
23577
23272
|
standardDoc = (0, import_yaml4.parse)(raw);
|
|
23578
23273
|
} catch {
|
|
23579
23274
|
return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
23580
23275
|
}
|
|
23581
23276
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
23582
23277
|
let readmeContent;
|
|
23583
|
-
if ((0,
|
|
23278
|
+
if ((0, import_node_fs39.existsSync)("README.md")) {
|
|
23584
23279
|
try {
|
|
23585
|
-
readmeContent = await (0,
|
|
23280
|
+
readmeContent = await (0, import_promises14.readFile)("README.md", "utf-8");
|
|
23586
23281
|
} catch {
|
|
23587
23282
|
}
|
|
23588
23283
|
}
|
|
23589
23284
|
let claudeMdContent;
|
|
23590
23285
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
23591
|
-
if ((0,
|
|
23286
|
+
if ((0, import_node_fs39.existsSync)(p)) {
|
|
23592
23287
|
try {
|
|
23593
|
-
claudeMdContent = await (0,
|
|
23288
|
+
claudeMdContent = await (0, import_promises14.readFile)(p, "utf-8");
|
|
23594
23289
|
break;
|
|
23595
23290
|
} catch {
|
|
23596
23291
|
}
|
|
@@ -23611,8 +23306,8 @@ async function runSeed(opts) {
|
|
|
23611
23306
|
if (candidates2.length === 0) {
|
|
23612
23307
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
23613
23308
|
}
|
|
23614
|
-
const overviewPath = (0,
|
|
23615
|
-
if ((0,
|
|
23309
|
+
const overviewPath = (0, import_node_path29.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
23310
|
+
if ((0, import_node_fs39.existsSync)(overviewPath) && !opts.force) {
|
|
23616
23311
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
|
|
23617
23312
|
}
|
|
23618
23313
|
if (opts.dryRun) {
|
|
@@ -23654,8 +23349,8 @@ async function runSeed(opts) {
|
|
|
23654
23349
|
continue;
|
|
23655
23350
|
}
|
|
23656
23351
|
try {
|
|
23657
|
-
await (0,
|
|
23658
|
-
await (0,
|
|
23352
|
+
await (0, import_promises14.mkdir)((0, import_node_path29.dirname)(targetPath), { recursive: true });
|
|
23353
|
+
await (0, import_promises14.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
|
|
23659
23354
|
created++;
|
|
23660
23355
|
opts.onCreated?.(nodeId, filePathRel, c);
|
|
23661
23356
|
} catch (err) {
|
|
@@ -23667,8 +23362,8 @@ async function runSeed(opts) {
|
|
|
23667
23362
|
}
|
|
23668
23363
|
|
|
23669
23364
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
23670
|
-
var
|
|
23671
|
-
var
|
|
23365
|
+
var import_node_fs40 = require("node:fs");
|
|
23366
|
+
var import_node_path30 = require("node:path");
|
|
23672
23367
|
async function memoryManifest(run2) {
|
|
23673
23368
|
const { globals } = run2;
|
|
23674
23369
|
const { serviceUrl, token } = run2;
|
|
@@ -23678,9 +23373,9 @@ async function memoryManifest(run2) {
|
|
|
23678
23373
|
let autoSeedNotice = null;
|
|
23679
23374
|
try {
|
|
23680
23375
|
await ensureMemoryDir();
|
|
23681
|
-
const seedMarker = (0,
|
|
23682
|
-
const hasStandard = (0,
|
|
23683
|
-
const alreadyTried = (0,
|
|
23376
|
+
const seedMarker = (0, import_node_path30.join)(VERITY_DIR, ".seeded");
|
|
23377
|
+
const hasStandard = (0, import_node_fs40.existsSync)(STANDARD_FILE);
|
|
23378
|
+
const alreadyTried = (0, import_node_fs40.existsSync)(seedMarker);
|
|
23684
23379
|
if (hasStandard && !alreadyTried) {
|
|
23685
23380
|
const preManifest = await buildManifest();
|
|
23686
23381
|
if (preManifest.nodes.length === 0) {
|
|
@@ -23693,7 +23388,7 @@ async function memoryManifest(run2) {
|
|
|
23693
23388
|
dryRun: false
|
|
23694
23389
|
});
|
|
23695
23390
|
if (seedResult.created > 0) {
|
|
23696
|
-
(0,
|
|
23391
|
+
(0, import_node_fs40.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
|
|
23697
23392
|
`);
|
|
23698
23393
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
23699
23394
|
logEvent("auto_seed_ran", {
|
|
@@ -23701,7 +23396,7 @@ async function memoryManifest(run2) {
|
|
|
23701
23396
|
failed: seedResult.failed
|
|
23702
23397
|
});
|
|
23703
23398
|
} else if (seedResult.skipped === "already_seeded") {
|
|
23704
|
-
(0,
|
|
23399
|
+
(0, import_node_fs40.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
23705
23400
|
`);
|
|
23706
23401
|
} else {
|
|
23707
23402
|
logEvent("auto_seed_noop", {
|
|
@@ -23796,7 +23491,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
|
|
|
23796
23491
|
}
|
|
23797
23492
|
|
|
23798
23493
|
// src/commands/analyze/phases/10-working-memory.ts
|
|
23799
|
-
var
|
|
23494
|
+
var import_node_path31 = require("node:path");
|
|
23800
23495
|
async function workingMemory(run2) {
|
|
23801
23496
|
const { opts } = run2;
|
|
23802
23497
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run2;
|
|
@@ -23808,7 +23503,7 @@ async function workingMemory(run2) {
|
|
|
23808
23503
|
const priorState = foldForMarks(memorySession.d);
|
|
23809
23504
|
incrementReport = computeIncrement(
|
|
23810
23505
|
allForReview,
|
|
23811
|
-
(p) => fileHash((0,
|
|
23506
|
+
(p) => fileHash((0, import_node_path31.join)(repoRoot(), p)),
|
|
23812
23507
|
priorState.authored_all.map((a) => ({
|
|
23813
23508
|
path: a.path,
|
|
23814
23509
|
hash_at_last_verdict: a.hash_at_last_verdict
|
|
@@ -23890,7 +23585,7 @@ async function workingMemory(run2) {
|
|
|
23890
23585
|
}
|
|
23891
23586
|
|
|
23892
23587
|
// src/lib/note-budget.ts
|
|
23893
|
-
var
|
|
23588
|
+
var import_node_fs41 = require("node:fs");
|
|
23894
23589
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
23895
23590
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
23896
23591
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -23912,9 +23607,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
23912
23607
|
}
|
|
23913
23608
|
function readAdvisoryEpisode(sessionId) {
|
|
23914
23609
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
23915
|
-
if (!(0,
|
|
23610
|
+
if (!(0, import_node_fs41.existsSync)(file)) return null;
|
|
23916
23611
|
try {
|
|
23917
|
-
const o = JSON.parse((0,
|
|
23612
|
+
const o = JSON.parse((0, import_node_fs41.readFileSync)(file, "utf-8")) ?? {};
|
|
23918
23613
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
23919
23614
|
if (isNaN(delivered)) return null;
|
|
23920
23615
|
return {
|
|
@@ -23928,8 +23623,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
23928
23623
|
}
|
|
23929
23624
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
23930
23625
|
try {
|
|
23931
|
-
(0,
|
|
23932
|
-
(0,
|
|
23626
|
+
(0, import_node_fs41.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
23627
|
+
(0, import_node_fs41.writeFileSync)(
|
|
23933
23628
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
23934
23629
|
JSON.stringify({ v: 1, ...episode })
|
|
23935
23630
|
);
|
|
@@ -24237,14 +23932,14 @@ async function buildRequest(run2) {
|
|
|
24237
23932
|
}
|
|
24238
23933
|
|
|
24239
23934
|
// src/lib/offline.ts
|
|
24240
|
-
var
|
|
23935
|
+
var import_node_fs42 = require("node:fs");
|
|
24241
23936
|
var import_node_crypto11 = require("node:crypto");
|
|
24242
23937
|
function cacheRequest(body) {
|
|
24243
23938
|
try {
|
|
24244
|
-
(0,
|
|
23939
|
+
(0, import_node_fs42.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
24245
23940
|
const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
|
|
24246
23941
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
24247
|
-
(0,
|
|
23942
|
+
(0, import_node_fs42.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
|
|
24248
23943
|
} catch {
|
|
24249
23944
|
}
|
|
24250
23945
|
}
|
|
@@ -24363,8 +24058,8 @@ async function transmit(run2) {
|
|
|
24363
24058
|
}
|
|
24364
24059
|
|
|
24365
24060
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
24366
|
-
var
|
|
24367
|
-
var
|
|
24061
|
+
var import_node_fs43 = require("node:fs");
|
|
24062
|
+
var import_node_path32 = require("node:path");
|
|
24368
24063
|
async function reconcile(run2) {
|
|
24369
24064
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
|
|
24370
24065
|
const sentPaths = codeDelta.files.map((f) => f.path);
|
|
@@ -24393,7 +24088,7 @@ async function reconcile(run2) {
|
|
|
24393
24088
|
const st = foldDossier(memorySession.d);
|
|
24394
24089
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
|
|
24395
24090
|
try {
|
|
24396
|
-
const src = (0,
|
|
24091
|
+
const src = (0, import_node_fs43.readFileSync)((0, import_node_path32.join)(repoRoot(), file), "utf8").split("\n");
|
|
24397
24092
|
const at = src[line - 1];
|
|
24398
24093
|
return at === void 0 ? null : lineSha(at);
|
|
24399
24094
|
} catch {
|
|
@@ -24658,7 +24353,7 @@ function describeRelease(release, input) {
|
|
|
24658
24353
|
|
|
24659
24354
|
// src/lib/memory-pull.ts
|
|
24660
24355
|
var import_node_child_process14 = require("node:child_process");
|
|
24661
|
-
var
|
|
24356
|
+
var import_promises15 = require("node:fs/promises");
|
|
24662
24357
|
var pullStateFile = () => projectPath(`${VERITY_DIR}/.memory-pull-state.json`);
|
|
24663
24358
|
var PAGE_SIZE = 200;
|
|
24664
24359
|
var MAX_PAGES = 500;
|
|
@@ -24742,7 +24437,7 @@ async function recordServedFiles(served) {
|
|
|
24742
24437
|
}
|
|
24743
24438
|
async function readPullState() {
|
|
24744
24439
|
try {
|
|
24745
|
-
const parsed = JSON.parse(await (0,
|
|
24440
|
+
const parsed = JSON.parse(await (0, import_promises15.readFile)(pullStateFile(), "utf-8"));
|
|
24746
24441
|
const served = /* @__PURE__ */ new Map();
|
|
24747
24442
|
if (parsed?.served && typeof parsed.served === "object") {
|
|
24748
24443
|
for (const [path, hash] of Object.entries(parsed.served)) {
|
|
@@ -24756,8 +24451,8 @@ async function readPullState() {
|
|
|
24756
24451
|
}
|
|
24757
24452
|
async function writePullState(state) {
|
|
24758
24453
|
try {
|
|
24759
|
-
await (0,
|
|
24760
|
-
await (0,
|
|
24454
|
+
await (0, import_promises15.mkdir)(projectPath(VERITY_DIR), { recursive: true });
|
|
24455
|
+
await (0, import_promises15.writeFile)(pullStateFile(), JSON.stringify({
|
|
24761
24456
|
...state.version ? { version: state.version } : {},
|
|
24762
24457
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24763
24458
|
served: Object.fromEntries(state.served)
|
|
@@ -25200,7 +24895,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
25200
24895
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
25201
24896
|
async function runAnalyze(opts, globals) {
|
|
25202
24897
|
if (!verityConfigured()) {
|
|
25203
|
-
(0,
|
|
24898
|
+
(0, import_node_fs44.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
25204
24899
|
process.exit(0);
|
|
25205
24900
|
}
|
|
25206
24901
|
const run2 = createRun(opts, globals);
|
|
@@ -25221,11 +24916,11 @@ async function runAnalyze(opts, globals) {
|
|
|
25221
24916
|
}
|
|
25222
24917
|
|
|
25223
24918
|
// src/commands/baseline.ts
|
|
25224
|
-
var
|
|
24919
|
+
var import_node_fs46 = require("node:fs");
|
|
25225
24920
|
|
|
25226
24921
|
// src/lib/project-skills.ts
|
|
25227
|
-
var
|
|
25228
|
-
var
|
|
24922
|
+
var import_node_fs45 = require("node:fs");
|
|
24923
|
+
var import_node_path33 = require("node:path");
|
|
25229
24924
|
var PROJECT_SKILL_NAMES = [
|
|
25230
24925
|
"verity-setup",
|
|
25231
24926
|
"verity-analyze",
|
|
@@ -25250,14 +24945,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
25250
24945
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
25251
24946
|
function staleProjectSkills() {
|
|
25252
24947
|
const root = projectPath(".claude/skills");
|
|
25253
|
-
if (!(0,
|
|
25254
|
-
return ALL.filter((name) => (0,
|
|
24948
|
+
if (!(0, import_node_fs45.existsSync)(root)) return [];
|
|
24949
|
+
return ALL.filter((name) => (0, import_node_fs45.existsSync)((0, import_node_path33.join)(root, name)));
|
|
25255
24950
|
}
|
|
25256
24951
|
function removeProjectSkills() {
|
|
25257
24952
|
const root = projectPath(".claude/skills");
|
|
25258
24953
|
const removed = [];
|
|
25259
24954
|
for (const name of staleProjectSkills()) {
|
|
25260
|
-
(0,
|
|
24955
|
+
(0, import_node_fs45.rmSync)((0, import_node_path33.join)(root, name), { recursive: true, force: true });
|
|
25261
24956
|
removed.push(name);
|
|
25262
24957
|
}
|
|
25263
24958
|
return removed;
|
|
@@ -25322,13 +25017,13 @@ function registerBaselineCommands(program2) {
|
|
|
25322
25017
|
let memoryMsg = null;
|
|
25323
25018
|
let memoryAgentLine = null;
|
|
25324
25019
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
25325
|
-
if (realStart && !(0,
|
|
25020
|
+
if (realStart && !(0, import_node_fs46.existsSync)(memoryNotice)) {
|
|
25326
25021
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
25327
25022
|
if (trackedGraph > 0) {
|
|
25328
25023
|
memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
|
|
25329
25024
|
memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
|
|
25330
25025
|
try {
|
|
25331
|
-
(0,
|
|
25026
|
+
(0, import_node_fs46.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
25332
25027
|
} catch {
|
|
25333
25028
|
}
|
|
25334
25029
|
}
|
|
@@ -25429,7 +25124,7 @@ function hookSource(value) {
|
|
|
25429
25124
|
}
|
|
25430
25125
|
|
|
25431
25126
|
// src/commands/review.ts
|
|
25432
|
-
var
|
|
25127
|
+
var import_node_fs47 = require("node:fs");
|
|
25433
25128
|
function registerReviewCommand(program2) {
|
|
25434
25129
|
program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars)").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
|
|
25435
25130
|
const globals = program2.opts();
|
|
@@ -25448,7 +25143,7 @@ async function runReview(opts, globals) {
|
|
|
25448
25143
|
const securityFiles = filterSecurity(allFiles);
|
|
25449
25144
|
let staticResults;
|
|
25450
25145
|
if (isCodacyAvailable()) {
|
|
25451
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
25146
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs47.existsSync)(f) || resolveFile(f) !== null);
|
|
25452
25147
|
staticResults = runCodacyAnalysis(scannable);
|
|
25453
25148
|
} else {
|
|
25454
25149
|
staticResults = {
|
|
@@ -25474,7 +25169,7 @@ async function runReview(opts, globals) {
|
|
|
25474
25169
|
const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
|
|
25475
25170
|
specs = [];
|
|
25476
25171
|
for (const p of specPaths) {
|
|
25477
|
-
if (!(0,
|
|
25172
|
+
if (!(0, import_node_fs47.existsSync)(p)) continue;
|
|
25478
25173
|
try {
|
|
25479
25174
|
const { readFileSync: readFileSync26 } = await import("node:fs");
|
|
25480
25175
|
const content = readFileSync26(p, "utf-8");
|
|
@@ -25534,8 +25229,8 @@ async function runReview(opts, globals) {
|
|
|
25534
25229
|
}
|
|
25535
25230
|
|
|
25536
25231
|
// src/commands/guard.ts
|
|
25537
|
-
var
|
|
25538
|
-
var
|
|
25232
|
+
var import_node_fs48 = require("node:fs");
|
|
25233
|
+
var import_node_path34 = require("node:path");
|
|
25539
25234
|
|
|
25540
25235
|
// src/lib/terminal-text.ts
|
|
25541
25236
|
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
|
|
@@ -25910,7 +25605,7 @@ async function buildAgentDiffs(ctx, paths, limits = { perFileChars: 24e3, totalC
|
|
|
25910
25605
|
// src/commands/guard.ts
|
|
25911
25606
|
var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
25912
25607
|
var GUARD_BLOCK_CAP = 2;
|
|
25913
|
-
var GUARD_ITER_FILE = (0,
|
|
25608
|
+
var GUARD_ITER_FILE = (0, import_node_path34.join)(VERITY_DIR, ".guard-iteration");
|
|
25914
25609
|
function readPreToolUseStdin() {
|
|
25915
25610
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
25916
25611
|
return new Promise((resolve6) => {
|
|
@@ -25955,7 +25650,7 @@ function readPreToolUseStdin() {
|
|
|
25955
25650
|
}
|
|
25956
25651
|
function readIterMap() {
|
|
25957
25652
|
try {
|
|
25958
|
-
const raw = JSON.parse((0,
|
|
25653
|
+
const raw = JSON.parse((0, import_node_fs48.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
25959
25654
|
if (raw && typeof raw === "object") {
|
|
25960
25655
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
25961
25656
|
return { [raw.moment]: raw.count };
|
|
@@ -25975,10 +25670,10 @@ function readIter(moment) {
|
|
|
25975
25670
|
}
|
|
25976
25671
|
function writeIter(moment, count) {
|
|
25977
25672
|
try {
|
|
25978
|
-
(0,
|
|
25673
|
+
(0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
25979
25674
|
const map = readIterMap();
|
|
25980
25675
|
map[moment] = count;
|
|
25981
|
-
(0,
|
|
25676
|
+
(0, import_node_fs48.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
25982
25677
|
} catch {
|
|
25983
25678
|
}
|
|
25984
25679
|
}
|
|
@@ -25988,10 +25683,10 @@ function resetIter(moment) {
|
|
|
25988
25683
|
if (!(moment in map)) return;
|
|
25989
25684
|
delete map[moment];
|
|
25990
25685
|
if (Object.keys(map).length === 0) {
|
|
25991
|
-
if ((0,
|
|
25686
|
+
if ((0, import_node_fs48.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs48.unlinkSync)(GUARD_ITER_FILE);
|
|
25992
25687
|
} else {
|
|
25993
|
-
(0,
|
|
25994
|
-
(0,
|
|
25688
|
+
(0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
25689
|
+
(0, import_node_fs48.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
25995
25690
|
}
|
|
25996
25691
|
} catch {
|
|
25997
25692
|
}
|
|
@@ -26063,7 +25758,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
|
|
|
26063
25758
|
const securityFiles = filterSecurity(files);
|
|
26064
25759
|
let staticResults;
|
|
26065
25760
|
if (isCodacyAvailable()) {
|
|
26066
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
25761
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs48.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
26067
25762
|
staticResults = runCodacyAnalysis(scannable);
|
|
26068
25763
|
} else {
|
|
26069
25764
|
staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
|
|
@@ -26566,7 +26261,7 @@ function registerIgnoreCommand(program2) {
|
|
|
26566
26261
|
|
|
26567
26262
|
// src/commands/waive.ts
|
|
26568
26263
|
var import_node_crypto12 = require("node:crypto");
|
|
26569
|
-
var
|
|
26264
|
+
var import_node_fs49 = require("node:fs");
|
|
26570
26265
|
function registerWaiveCommand(program2) {
|
|
26571
26266
|
program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
|
|
26572
26267
|
const globals = program2.opts();
|
|
@@ -26595,7 +26290,7 @@ function registerWaiveCommand(program2) {
|
|
|
26595
26290
|
if (opts.file) {
|
|
26596
26291
|
body.file = opts.file;
|
|
26597
26292
|
try {
|
|
26598
|
-
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0,
|
|
26293
|
+
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs49.readFileSync)(opts.file)).digest("hex");
|
|
26599
26294
|
} catch {
|
|
26600
26295
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
26601
26296
|
process.exit(1);
|
|
@@ -26620,10 +26315,10 @@ function registerWaiveCommand(program2) {
|
|
|
26620
26315
|
}
|
|
26621
26316
|
|
|
26622
26317
|
// src/commands/init.ts
|
|
26623
|
-
var
|
|
26624
|
-
var
|
|
26318
|
+
var import_node_fs53 = require("node:fs");
|
|
26319
|
+
var import_promises18 = require("node:fs/promises");
|
|
26625
26320
|
var import_yaml6 = __toESM(require_dist());
|
|
26626
|
-
var
|
|
26321
|
+
var import_node_path37 = require("node:path");
|
|
26627
26322
|
var import_node_child_process17 = require("node:child_process");
|
|
26628
26323
|
|
|
26629
26324
|
// src/lib/banner.ts
|
|
@@ -26702,7 +26397,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
26702
26397
|
}
|
|
26703
26398
|
|
|
26704
26399
|
// src/commands/doctor.ts
|
|
26705
|
-
var
|
|
26400
|
+
var import_node_fs50 = require("node:fs");
|
|
26706
26401
|
|
|
26707
26402
|
// src/lib/prereqs.ts
|
|
26708
26403
|
var import_node_child_process15 = require("node:child_process");
|
|
@@ -26818,7 +26513,7 @@ async function checkPrereqs(opts = {}) {
|
|
|
26818
26513
|
}
|
|
26819
26514
|
|
|
26820
26515
|
// src/lib/telemetry.ts
|
|
26821
|
-
var
|
|
26516
|
+
var import_promises16 = require("node:fs/promises");
|
|
26822
26517
|
var SETTINGS_LOCAL_FILE2 = ".claude/settings.local.json";
|
|
26823
26518
|
var GITIGNORE_FILE = ".gitignore";
|
|
26824
26519
|
var GITIGNORE_ENTRY = SETTINGS_LOCAL_IGNORE_ENTRY;
|
|
@@ -26848,7 +26543,7 @@ function buildTelemetryEnv(serviceUrl) {
|
|
|
26848
26543
|
var VERITY_TELEMETRY_KEYS = Object.keys(buildTelemetryEnv(""));
|
|
26849
26544
|
async function readSettingsLocal() {
|
|
26850
26545
|
try {
|
|
26851
|
-
return JSON.parse(await (0,
|
|
26546
|
+
return JSON.parse(await (0, import_promises16.readFile)(projectPath(SETTINGS_LOCAL_FILE2), "utf-8"));
|
|
26852
26547
|
} catch {
|
|
26853
26548
|
return {};
|
|
26854
26549
|
}
|
|
@@ -26860,7 +26555,7 @@ async function ensureGitignore() {
|
|
|
26860
26555
|
const file = projectPath(GITIGNORE_FILE);
|
|
26861
26556
|
let content = "";
|
|
26862
26557
|
try {
|
|
26863
|
-
content = await (0,
|
|
26558
|
+
content = await (0, import_promises16.readFile)(file, "utf-8");
|
|
26864
26559
|
} catch {
|
|
26865
26560
|
}
|
|
26866
26561
|
const lines = content.split("\n").map((l) => l.trim());
|
|
@@ -26869,7 +26564,7 @@ async function ensureGitignore() {
|
|
|
26869
26564
|
}
|
|
26870
26565
|
const block = "# Verity telemetry \u2014 machine-local Claude Code settings\n" + GITIGNORE_ENTRY + "\n";
|
|
26871
26566
|
const next = content ? content + (content.endsWith("\n") ? "" : "\n") + "\n" + block : block;
|
|
26872
|
-
await (0,
|
|
26567
|
+
await (0, import_promises16.writeFile)(file, next);
|
|
26873
26568
|
}
|
|
26874
26569
|
async function installTelemetry(serviceUrl) {
|
|
26875
26570
|
const env = buildTelemetryEnv(serviceUrl);
|
|
@@ -26914,11 +26609,11 @@ async function buildReport() {
|
|
|
26914
26609
|
const wiring = await resolveHookWiring();
|
|
26915
26610
|
const hooks = wiring.status;
|
|
26916
26611
|
const telemetry = await checkTelemetry();
|
|
26917
|
-
const hasConfig = (0,
|
|
26612
|
+
const hasConfig = (0, import_node_fs50.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
26918
26613
|
const artifacts = {
|
|
26919
|
-
standard: (0,
|
|
26614
|
+
standard: (0, import_node_fs50.existsSync)(projectPath(STANDARD_FILE)),
|
|
26920
26615
|
analysisConfig: hasConfig,
|
|
26921
|
-
verityMd: (0,
|
|
26616
|
+
verityMd: (0, import_node_fs50.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
26922
26617
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
26923
26618
|
};
|
|
26924
26619
|
const next = [];
|
|
@@ -27049,8 +26744,8 @@ function registerDoctorCommand(program2) {
|
|
|
27049
26744
|
}
|
|
27050
26745
|
|
|
27051
26746
|
// src/commands/migrate.ts
|
|
27052
|
-
var
|
|
27053
|
-
var
|
|
26747
|
+
var import_node_fs51 = require("node:fs");
|
|
26748
|
+
var import_node_path35 = require("node:path");
|
|
27054
26749
|
var import_node_child_process16 = require("node:child_process");
|
|
27055
26750
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
27056
26751
|
function defaultNpmRemover(pkg) {
|
|
@@ -27087,12 +26782,12 @@ async function runMigration(opts = {}) {
|
|
|
27087
26782
|
return { actions, migrated: actions.length > 0 };
|
|
27088
26783
|
}
|
|
27089
26784
|
function migrateProjectDir(root, actions) {
|
|
27090
|
-
const gateDir = (0,
|
|
27091
|
-
const verityDir = (0,
|
|
27092
|
-
if ((0,
|
|
26785
|
+
const gateDir = (0, import_node_path35.join)(root, ".gate");
|
|
26786
|
+
const verityDir = (0, import_node_path35.join)(root, ".verity");
|
|
26787
|
+
if ((0, import_node_fs51.existsSync)(gateDir) && !(0, import_node_fs51.existsSync)(verityDir)) {
|
|
27093
26788
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
27094
26789
|
}
|
|
27095
|
-
if ((0,
|
|
26790
|
+
if ((0, import_node_fs51.existsSync)(gateDir) && (0, import_node_fs51.existsSync)(verityDir)) {
|
|
27096
26791
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
27097
26792
|
}
|
|
27098
26793
|
return false;
|
|
@@ -27113,13 +26808,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
27113
26808
|
}
|
|
27114
26809
|
}
|
|
27115
26810
|
if (moved) {
|
|
27116
|
-
if ((0,
|
|
26811
|
+
if ((0, import_node_fs51.existsSync)(gateDir)) {
|
|
27117
26812
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
27118
26813
|
if (carried > 0) {
|
|
27119
26814
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
27120
26815
|
}
|
|
27121
26816
|
try {
|
|
27122
|
-
(0,
|
|
26817
|
+
(0, import_node_fs51.rmSync)(gateDir, { recursive: true, force: true });
|
|
27123
26818
|
} catch {
|
|
27124
26819
|
}
|
|
27125
26820
|
}
|
|
@@ -27135,18 +26830,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
27135
26830
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
27136
26831
|
}
|
|
27137
26832
|
try {
|
|
27138
|
-
(0,
|
|
26833
|
+
(0, import_node_fs51.rmSync)(gateDir, { recursive: true, force: true });
|
|
27139
26834
|
} catch {
|
|
27140
26835
|
}
|
|
27141
26836
|
return carried > 0;
|
|
27142
26837
|
}
|
|
27143
26838
|
function migrateGlobalCredentials(home, actions) {
|
|
27144
26839
|
if (!home) return;
|
|
27145
|
-
const gateCreds = (0,
|
|
27146
|
-
const verityCreds = (0,
|
|
27147
|
-
if (!(0,
|
|
27148
|
-
if (!(0,
|
|
27149
|
-
(0,
|
|
26840
|
+
const gateCreds = (0, import_node_path35.join)(home, ".gate", "credentials");
|
|
26841
|
+
const verityCreds = (0, import_node_path35.join)(home, ".verity", "credentials");
|
|
26842
|
+
if (!(0, import_node_fs51.existsSync)(gateCreds)) return;
|
|
26843
|
+
if (!(0, import_node_fs51.existsSync)(verityCreds)) {
|
|
26844
|
+
(0, import_node_fs51.mkdirSync)((0, import_node_path35.join)(home, ".verity"), { recursive: true });
|
|
27150
26845
|
moveFile(gateCreds, verityCreds);
|
|
27151
26846
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
27152
26847
|
return;
|
|
@@ -27168,8 +26863,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
27168
26863
|
}
|
|
27169
26864
|
}
|
|
27170
26865
|
async function migrateClaudeMd(root, actions) {
|
|
27171
|
-
const claudeMd = (0,
|
|
27172
|
-
const hadLegacyBlock = (0,
|
|
26866
|
+
const claudeMd = (0, import_node_path35.join)(root, "CLAUDE.md");
|
|
26867
|
+
const hadLegacyBlock = (0, import_node_fs51.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
27173
26868
|
if (!hadLegacyBlock) return;
|
|
27174
26869
|
try {
|
|
27175
26870
|
await ensureClaudeMdPointer(root);
|
|
@@ -27179,9 +26874,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
27179
26874
|
}
|
|
27180
26875
|
}
|
|
27181
26876
|
function migrateStandardFile(root, actions) {
|
|
27182
|
-
const gateMd = (0,
|
|
27183
|
-
const verityMd = (0,
|
|
27184
|
-
if (!(0,
|
|
26877
|
+
const gateMd = (0, import_node_path35.join)(root, "GATE.md");
|
|
26878
|
+
const verityMd = (0, import_node_path35.join)(root, "VERITY.md");
|
|
26879
|
+
if (!(0, import_node_fs51.existsSync)(gateMd) || (0, import_node_fs51.existsSync)(verityMd)) return;
|
|
27185
26880
|
let moved = false;
|
|
27186
26881
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
27187
26882
|
try {
|
|
@@ -27193,12 +26888,12 @@ function migrateStandardFile(root, actions) {
|
|
|
27193
26888
|
if (!moved) moveFile(gateMd, verityMd);
|
|
27194
26889
|
const content = readFileSyncSafe(verityMd);
|
|
27195
26890
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
27196
|
-
if (refreshed !== content) (0,
|
|
26891
|
+
if (refreshed !== content) (0, import_node_fs51.writeFileSync)(verityMd, refreshed);
|
|
27197
26892
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
27198
26893
|
}
|
|
27199
26894
|
async function migrateTelemetryHeaders(root, actions) {
|
|
27200
|
-
const file = (0,
|
|
27201
|
-
if (!(0,
|
|
26895
|
+
const file = (0, import_node_path35.join)(root, ".claude", "settings.local.json");
|
|
26896
|
+
if (!(0, import_node_fs51.existsSync)(file)) return;
|
|
27202
26897
|
let settings;
|
|
27203
26898
|
try {
|
|
27204
26899
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -27246,14 +26941,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
27246
26941
|
}
|
|
27247
26942
|
if (toAppend.length > 0) {
|
|
27248
26943
|
const sep4 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
27249
|
-
(0,
|
|
26944
|
+
(0, import_node_fs51.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
|
|
27250
26945
|
}
|
|
27251
|
-
(0,
|
|
26946
|
+
(0, import_node_fs51.rmSync)(gateCreds, { force: true });
|
|
27252
26947
|
return toAppend.length;
|
|
27253
26948
|
}
|
|
27254
26949
|
function readFileSyncSafe(path) {
|
|
27255
26950
|
try {
|
|
27256
|
-
return (0,
|
|
26951
|
+
return (0, import_node_fs51.readFileSync)(path, "utf-8");
|
|
27257
26952
|
} catch {
|
|
27258
26953
|
return "";
|
|
27259
26954
|
}
|
|
@@ -27268,35 +26963,35 @@ function hasStagedChanges(root) {
|
|
|
27268
26963
|
}
|
|
27269
26964
|
function moveDir(from, to) {
|
|
27270
26965
|
try {
|
|
27271
|
-
(0,
|
|
26966
|
+
(0, import_node_fs51.renameSync)(from, to);
|
|
27272
26967
|
} catch (err) {
|
|
27273
26968
|
if (err.code !== "EXDEV") throw err;
|
|
27274
|
-
(0,
|
|
27275
|
-
(0,
|
|
26969
|
+
(0, import_node_fs51.cpSync)(from, to, { recursive: true });
|
|
26970
|
+
(0, import_node_fs51.rmSync)(from, { recursive: true, force: true });
|
|
27276
26971
|
}
|
|
27277
26972
|
}
|
|
27278
26973
|
function moveFile(from, to) {
|
|
27279
26974
|
try {
|
|
27280
|
-
(0,
|
|
26975
|
+
(0, import_node_fs51.renameSync)(from, to);
|
|
27281
26976
|
} catch (err) {
|
|
27282
26977
|
if (err.code !== "EXDEV") throw err;
|
|
27283
|
-
(0,
|
|
27284
|
-
(0,
|
|
26978
|
+
(0, import_node_fs51.cpSync)(from, to);
|
|
26979
|
+
(0, import_node_fs51.rmSync)(from, { force: true });
|
|
27285
26980
|
}
|
|
27286
26981
|
}
|
|
27287
26982
|
function carryLegacyContents(gateDir, verityDir) {
|
|
27288
26983
|
let copied = 0;
|
|
27289
26984
|
const walk2 = (relDir) => {
|
|
27290
|
-
const srcDir = (0,
|
|
27291
|
-
for (const entry of (0,
|
|
27292
|
-
const rel = relDir ? (0,
|
|
27293
|
-
const src = (0,
|
|
27294
|
-
const dest = (0,
|
|
27295
|
-
if ((0,
|
|
26985
|
+
const srcDir = (0, import_node_path35.join)(gateDir, relDir);
|
|
26986
|
+
for (const entry of (0, import_node_fs51.readdirSync)(srcDir)) {
|
|
26987
|
+
const rel = relDir ? (0, import_node_path35.join)(relDir, entry) : entry;
|
|
26988
|
+
const src = (0, import_node_path35.join)(gateDir, rel);
|
|
26989
|
+
const dest = (0, import_node_path35.join)(verityDir, rel);
|
|
26990
|
+
if ((0, import_node_fs51.statSync)(src).isDirectory()) {
|
|
27296
26991
|
walk2(rel);
|
|
27297
|
-
} else if (!(0,
|
|
27298
|
-
(0,
|
|
27299
|
-
(0,
|
|
26992
|
+
} else if (!(0, import_node_fs51.existsSync)(dest)) {
|
|
26993
|
+
(0, import_node_fs51.mkdirSync)((0, import_node_path35.dirname)(dest), { recursive: true });
|
|
26994
|
+
(0, import_node_fs51.cpSync)(src, dest);
|
|
27300
26995
|
copied++;
|
|
27301
26996
|
}
|
|
27302
26997
|
}
|
|
@@ -27305,22 +27000,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
27305
27000
|
return copied;
|
|
27306
27001
|
}
|
|
27307
27002
|
async function needsMigration(root = repoRoot()) {
|
|
27308
|
-
const gateDir = (0,
|
|
27309
|
-
const verityDir = (0,
|
|
27310
|
-
if ((0,
|
|
27311
|
-
if ((0,
|
|
27312
|
-
if ((0,
|
|
27003
|
+
const gateDir = (0, import_node_path35.join)(root, ".gate");
|
|
27004
|
+
const verityDir = (0, import_node_path35.join)(root, ".verity");
|
|
27005
|
+
if ((0, import_node_fs51.existsSync)(gateDir) && !(0, import_node_fs51.existsSync)(verityDir)) return true;
|
|
27006
|
+
if ((0, import_node_fs51.existsSync)(gateDir) && (0, import_node_fs51.existsSync)(verityDir)) {
|
|
27007
|
+
if ((0, import_node_fs51.existsSync)((0, import_node_path35.join)(gateDir, "credentials")) && !(0, import_node_fs51.existsSync)((0, import_node_path35.join)(verityDir, "credentials"))) {
|
|
27313
27008
|
return true;
|
|
27314
27009
|
}
|
|
27315
|
-
if ((0,
|
|
27010
|
+
if ((0, import_node_fs51.existsSync)((0, import_node_path35.join)(gateDir, "memory")) && !(0, import_node_fs51.existsSync)((0, import_node_path35.join)(verityDir, "memory"))) {
|
|
27316
27011
|
return true;
|
|
27317
27012
|
}
|
|
27318
27013
|
}
|
|
27319
|
-
const claudeMd = (0,
|
|
27320
|
-
if ((0,
|
|
27014
|
+
const claudeMd = (0, import_node_path35.join)(root, "CLAUDE.md");
|
|
27015
|
+
if ((0, import_node_fs51.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
27321
27016
|
return true;
|
|
27322
27017
|
}
|
|
27323
|
-
if ((0,
|
|
27018
|
+
if ((0, import_node_fs51.existsSync)((0, import_node_path35.join)(root, "GATE.md")) && !(0, import_node_fs51.existsSync)((0, import_node_path35.join)(root, "VERITY.md"))) {
|
|
27324
27019
|
return true;
|
|
27325
27020
|
}
|
|
27326
27021
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -27601,9 +27296,9 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
27601
27296
|
}
|
|
27602
27297
|
|
|
27603
27298
|
// src/lib/remote-config.ts
|
|
27604
|
-
var
|
|
27605
|
-
var
|
|
27606
|
-
var
|
|
27299
|
+
var import_node_fs52 = require("node:fs");
|
|
27300
|
+
var import_promises17 = require("node:fs/promises");
|
|
27301
|
+
var import_node_path36 = require("node:path");
|
|
27607
27302
|
var import_yaml5 = __toESM(require_dist());
|
|
27608
27303
|
var IGNORE_RIDER = "verityignore";
|
|
27609
27304
|
async function fetchRemoteSetup(opts) {
|
|
@@ -27648,11 +27343,11 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
27648
27343
|
written.push(STANDARD_FILE);
|
|
27649
27344
|
if (rider !== null) {
|
|
27650
27345
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
27651
|
-
if (!(0,
|
|
27346
|
+
if (!(0, import_node_fs52.existsSync)(localIgnore)) {
|
|
27652
27347
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
27653
27348
|
written.push(VERITYIGNORE_FILE);
|
|
27654
27349
|
} else {
|
|
27655
|
-
const local = await (0,
|
|
27350
|
+
const local = await (0, import_promises17.readFile)(localIgnore, "utf-8").catch(() => null);
|
|
27656
27351
|
if (local !== null && local !== rider) {
|
|
27657
27352
|
notes.push(`${VERITYIGNORE_FILE} already exists here and differs from the pushed copy \u2014 kept yours.`);
|
|
27658
27353
|
}
|
|
@@ -27681,8 +27376,8 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
27681
27376
|
}
|
|
27682
27377
|
async function writeOut(relative2, body) {
|
|
27683
27378
|
const target = projectPath(relative2);
|
|
27684
|
-
await (0,
|
|
27685
|
-
await (0,
|
|
27379
|
+
await (0, import_promises17.mkdir)((0, import_node_path36.dirname)(target), { recursive: true });
|
|
27380
|
+
await (0, import_promises17.writeFile)(target, body);
|
|
27686
27381
|
}
|
|
27687
27382
|
function describeRemote(found) {
|
|
27688
27383
|
const when = found.standard.createdAt.slice(0, 10);
|
|
@@ -27798,15 +27493,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
27798
27493
|
}
|
|
27799
27494
|
function resolveDataDir2() {
|
|
27800
27495
|
const candidates2 = [
|
|
27801
|
-
(0,
|
|
27496
|
+
(0, import_node_path37.join)(__dirname, "..", "data"),
|
|
27802
27497
|
// installed: node_modules/@codacy/verity-cli/data
|
|
27803
|
-
(0,
|
|
27498
|
+
(0, import_node_path37.join)(__dirname, "..", "..", "data"),
|
|
27804
27499
|
// edge case: nested resolution
|
|
27805
|
-
(0,
|
|
27500
|
+
(0, import_node_path37.join)(process.cwd(), "cli", "data")
|
|
27806
27501
|
// local dev: running from repo root
|
|
27807
27502
|
];
|
|
27808
27503
|
for (const candidate of candidates2) {
|
|
27809
|
-
if ((0,
|
|
27504
|
+
if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(candidate, "skills"))) {
|
|
27810
27505
|
return candidate;
|
|
27811
27506
|
}
|
|
27812
27507
|
}
|
|
@@ -27815,16 +27510,16 @@ function resolveDataDir2() {
|
|
|
27815
27510
|
);
|
|
27816
27511
|
}
|
|
27817
27512
|
async function copyDir(src, dest) {
|
|
27818
|
-
await (0,
|
|
27819
|
-
await (0,
|
|
27513
|
+
await (0, import_promises18.mkdir)(dest, { recursive: true });
|
|
27514
|
+
await (0, import_promises18.cp)(src, dest, { recursive: true, force: true });
|
|
27820
27515
|
}
|
|
27821
27516
|
async function skillIsCurrent(src, dest) {
|
|
27822
27517
|
const list2 = (dir) => {
|
|
27823
27518
|
const out = [];
|
|
27824
27519
|
const walk2 = (d, prefix) => {
|
|
27825
|
-
for (const e of (0,
|
|
27520
|
+
for (const e of (0, import_node_fs53.readdirSync)(d, { withFileTypes: true })) {
|
|
27826
27521
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
27827
|
-
if (e.isDirectory()) walk2((0,
|
|
27522
|
+
if (e.isDirectory()) walk2((0, import_node_path37.join)(d, e.name), rel);
|
|
27828
27523
|
else if (e.isFile()) out.push(rel);
|
|
27829
27524
|
}
|
|
27830
27525
|
};
|
|
@@ -27835,8 +27530,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
27835
27530
|
const shipped = list2(src);
|
|
27836
27531
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
27837
27532
|
for (const rel of shipped) {
|
|
27838
|
-
const a = await (0,
|
|
27839
|
-
const b = await (0,
|
|
27533
|
+
const a = await (0, import_promises18.readFile)((0, import_node_path37.join)(src, rel), "utf-8");
|
|
27534
|
+
const b = await (0, import_promises18.readFile)((0, import_node_path37.join)(dest, rel), "utf-8");
|
|
27840
27535
|
if (a !== b) return false;
|
|
27841
27536
|
}
|
|
27842
27537
|
return true;
|
|
@@ -28017,13 +27712,13 @@ async function synthesizeLocally(opts) {
|
|
|
28017
27712
|
async function healStaleAnalysisConfig(globals) {
|
|
28018
27713
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
28019
27714
|
const standardPath = projectPath(STANDARD_FILE);
|
|
28020
|
-
if (!(0,
|
|
27715
|
+
if (!(0, import_node_fs53.existsSync)(configPath) || !(0, import_node_fs53.existsSync)(standardPath)) return;
|
|
28021
27716
|
const validation = validatePatternIds();
|
|
28022
27717
|
if (validation.status !== "invalid") return;
|
|
28023
27718
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
28024
27719
|
printWarn(" running silently with nothing enabled. Re-deriving it from your Standard\u2026");
|
|
28025
27720
|
try {
|
|
28026
|
-
const content = (0, import_yaml6.parse)(await (0,
|
|
27721
|
+
const content = (0, import_yaml6.parse)(await (0, import_promises18.readFile)(standardPath, "utf-8"));
|
|
28027
27722
|
const derived = await deriveConfigForStandard(content);
|
|
28028
27723
|
for (const path of derived.written) printInfo(` ${path} \u2713 (re-derived)`);
|
|
28029
27724
|
for (const note of derived.notes) printWarn(` ${note}`);
|
|
@@ -28114,17 +27809,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
28114
27809
|
async function installSkills(force, step) {
|
|
28115
27810
|
step("Installing skills");
|
|
28116
27811
|
const dataDir = resolveDataDir2();
|
|
28117
|
-
const skillsSource = (0,
|
|
27812
|
+
const skillsSource = (0, import_node_path37.join)(dataDir, "skills");
|
|
28118
27813
|
const skillsDest = ".claude/skills";
|
|
28119
27814
|
let skillsInstalled = 0;
|
|
28120
27815
|
for (const skill of SKILLS) {
|
|
28121
|
-
const src = (0,
|
|
28122
|
-
const dest = (0,
|
|
28123
|
-
if (!(0,
|
|
27816
|
+
const src = (0, import_node_path37.join)(skillsSource, skill);
|
|
27817
|
+
const dest = (0, import_node_path37.join)(skillsDest, skill);
|
|
27818
|
+
if (!(0, import_node_fs53.existsSync)(src)) {
|
|
28124
27819
|
printWarn(` Skill data not found: ${skill}`);
|
|
28125
27820
|
continue;
|
|
28126
27821
|
}
|
|
28127
|
-
if ((0,
|
|
27822
|
+
if ((0, import_node_fs53.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
28128
27823
|
skillsInstalled++;
|
|
28129
27824
|
continue;
|
|
28130
27825
|
}
|
|
@@ -28188,7 +27883,7 @@ async function checkPrerequisites(step) {
|
|
|
28188
27883
|
}
|
|
28189
27884
|
async function scaffoldProject(step, defaultsOnly) {
|
|
28190
27885
|
step("Knowledge base, .gitignore and CLAUDE.md");
|
|
28191
|
-
await (0,
|
|
27886
|
+
await (0, import_promises18.mkdir)(VERITY_DIR, { recursive: true });
|
|
28192
27887
|
await ensureMemoryDir();
|
|
28193
27888
|
const ignoreResult = ensureVerityGitignore();
|
|
28194
27889
|
if (ignoreResult === "failed") {
|
|
@@ -28263,7 +27958,7 @@ function registerInitCommand(program2) {
|
|
|
28263
27958
|
const staleMarker = clearStalePluginMarker();
|
|
28264
27959
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
28265
27960
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
28266
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
27961
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs53.existsSync)(m));
|
|
28267
27962
|
if (!isProject) {
|
|
28268
27963
|
printError("No project detected in the current directory.");
|
|
28269
27964
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -28353,8 +28048,8 @@ function registerInitCommand(program2) {
|
|
|
28353
28048
|
printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
|
|
28354
28049
|
}
|
|
28355
28050
|
await scaffoldProject(step, defaultsOnly);
|
|
28356
|
-
const globalVerityDir = (0,
|
|
28357
|
-
await (0,
|
|
28051
|
+
const globalVerityDir = (0, import_node_path37.join)(process.env.HOME ?? "", ".verity");
|
|
28052
|
+
await (0, import_promises18.mkdir)(globalVerityDir, { recursive: true });
|
|
28358
28053
|
console.log("");
|
|
28359
28054
|
step("Wiring Claude Code hooks");
|
|
28360
28055
|
const gitMoments = [
|
|
@@ -28422,7 +28117,7 @@ function registerInitCommand(program2) {
|
|
|
28422
28117
|
}
|
|
28423
28118
|
step("Your project's Standard");
|
|
28424
28119
|
let haveStandard = false;
|
|
28425
|
-
if ((0,
|
|
28120
|
+
if ((0, import_node_fs53.existsSync)(projectPath(STANDARD_FILE))) {
|
|
28426
28121
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
28427
28122
|
haveStandard = true;
|
|
28428
28123
|
} else {
|
|
@@ -28452,7 +28147,7 @@ function registerInitCommand(program2) {
|
|
|
28452
28147
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
28453
28148
|
init: {
|
|
28454
28149
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28455
|
-
cli_version: true ? "0.32.6-experimental.
|
|
28150
|
+
cli_version: true ? "0.32.6-experimental.8f2b5f7" : "dev"
|
|
28456
28151
|
}
|
|
28457
28152
|
});
|
|
28458
28153
|
} catch (err) {
|
|
@@ -28502,8 +28197,8 @@ function registerInitCommand(program2) {
|
|
|
28502
28197
|
}
|
|
28503
28198
|
|
|
28504
28199
|
// src/commands/uninstall.ts
|
|
28505
|
-
var
|
|
28506
|
-
var
|
|
28200
|
+
var import_node_fs54 = require("node:fs");
|
|
28201
|
+
var import_node_path38 = require("node:path");
|
|
28507
28202
|
function registerUninstallCommand(program2) {
|
|
28508
28203
|
program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
|
|
28509
28204
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -28512,11 +28207,11 @@ function registerUninstallCommand(program2) {
|
|
|
28512
28207
|
const actions = [];
|
|
28513
28208
|
const skillsRoot = projectPath(".claude/skills");
|
|
28514
28209
|
for (const name of PROJECT_SKILL_NAMES) {
|
|
28515
|
-
const dir = (0,
|
|
28516
|
-
if ((0,
|
|
28210
|
+
const dir = (0, import_node_path38.join)(skillsRoot, name);
|
|
28211
|
+
if ((0, import_node_fs54.existsSync)(dir)) {
|
|
28517
28212
|
actions.push({
|
|
28518
28213
|
label: `Remove .claude/skills/${name}/`,
|
|
28519
|
-
apply: () => (0,
|
|
28214
|
+
apply: () => (0, import_node_fs54.rmSync)(dir, { recursive: true, force: true })
|
|
28520
28215
|
});
|
|
28521
28216
|
}
|
|
28522
28217
|
}
|
|
@@ -28530,24 +28225,24 @@ function registerUninstallCommand(program2) {
|
|
|
28530
28225
|
});
|
|
28531
28226
|
}
|
|
28532
28227
|
const verityDir = projectPath(VERITY_DIR);
|
|
28533
|
-
if ((0,
|
|
28228
|
+
if ((0, import_node_fs54.existsSync)(verityDir)) {
|
|
28534
28229
|
actions.push({
|
|
28535
28230
|
label: `Remove ${VERITY_DIR}/`,
|
|
28536
|
-
apply: () => (0,
|
|
28231
|
+
apply: () => (0, import_node_fs54.rmSync)(verityDir, { recursive: true, force: true })
|
|
28537
28232
|
});
|
|
28538
28233
|
}
|
|
28539
28234
|
if (!keepVerityMd) {
|
|
28540
28235
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
28541
|
-
if ((0,
|
|
28236
|
+
if ((0, import_node_fs54.existsSync)(verityMd)) {
|
|
28542
28237
|
actions.push({
|
|
28543
28238
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
28544
|
-
apply: () => (0,
|
|
28239
|
+
apply: () => (0, import_node_fs54.rmSync)(verityMd, { force: true })
|
|
28545
28240
|
});
|
|
28546
28241
|
}
|
|
28547
28242
|
}
|
|
28548
28243
|
const cleanupEmptyDir = (path) => {
|
|
28549
|
-
if ((0,
|
|
28550
|
-
(0,
|
|
28244
|
+
if ((0, import_node_fs54.existsSync)(path) && (0, import_node_fs54.statSync)(path).isDirectory() && (0, import_node_fs54.readdirSync)(path).length === 0) {
|
|
28245
|
+
(0, import_node_fs54.rmdirSync)(path);
|
|
28551
28246
|
}
|
|
28552
28247
|
};
|
|
28553
28248
|
actions.push({
|
|
@@ -28558,11 +28253,11 @@ function registerUninstallCommand(program2) {
|
|
|
28558
28253
|
}
|
|
28559
28254
|
});
|
|
28560
28255
|
const home = process.env.HOME ?? "";
|
|
28561
|
-
const globalVerityDir = (0,
|
|
28562
|
-
if (purgeGlobal && (0,
|
|
28256
|
+
const globalVerityDir = (0, import_node_path38.join)(home, ".verity");
|
|
28257
|
+
if (purgeGlobal && (0, import_node_fs54.existsSync)(globalVerityDir)) {
|
|
28563
28258
|
actions.push({
|
|
28564
28259
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
28565
|
-
apply: () => (0,
|
|
28260
|
+
apply: () => (0, import_node_fs54.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
28566
28261
|
});
|
|
28567
28262
|
}
|
|
28568
28263
|
if (actions.length === 0) {
|
|
@@ -28756,8 +28451,8 @@ function registerTaskCommands(program2) {
|
|
|
28756
28451
|
}
|
|
28757
28452
|
|
|
28758
28453
|
// src/commands/reset.ts
|
|
28759
|
-
var
|
|
28760
|
-
var
|
|
28454
|
+
var import_node_fs55 = require("node:fs");
|
|
28455
|
+
var import_node_path39 = require("node:path");
|
|
28761
28456
|
function registerResetCommand(program2) {
|
|
28762
28457
|
program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
|
|
28763
28458
|
const globals = program2.opts();
|
|
@@ -28794,11 +28489,11 @@ function registerResetCommand(program2) {
|
|
|
28794
28489
|
}
|
|
28795
28490
|
const cacheDir = projectPath(CACHE_DIR);
|
|
28796
28491
|
let purged = 0;
|
|
28797
|
-
if ((0,
|
|
28798
|
-
for (const entry of (0,
|
|
28492
|
+
if ((0, import_node_fs55.existsSync)(cacheDir)) {
|
|
28493
|
+
for (const entry of (0, import_node_fs55.readdirSync)(cacheDir)) {
|
|
28799
28494
|
if (entry.startsWith("pending-")) {
|
|
28800
28495
|
try {
|
|
28801
|
-
(0,
|
|
28496
|
+
(0, import_node_fs55.unlinkSync)((0, import_node_path39.join)(cacheDir, entry));
|
|
28802
28497
|
purged++;
|
|
28803
28498
|
} catch {
|
|
28804
28499
|
}
|
|
@@ -28813,19 +28508,19 @@ function registerResetCommand(program2) {
|
|
|
28813
28508
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
28814
28509
|
];
|
|
28815
28510
|
for (const file of filesToClear) {
|
|
28816
|
-
if ((0,
|
|
28511
|
+
if ((0, import_node_fs55.existsSync)(file)) {
|
|
28817
28512
|
try {
|
|
28818
|
-
(0,
|
|
28513
|
+
(0, import_node_fs55.writeFileSync)(file, "");
|
|
28819
28514
|
} catch {
|
|
28820
28515
|
}
|
|
28821
28516
|
}
|
|
28822
28517
|
}
|
|
28823
28518
|
if (opts.all) {
|
|
28824
28519
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
28825
|
-
if ((0,
|
|
28826
|
-
for (const entry of (0,
|
|
28520
|
+
if ((0, import_node_fs55.existsSync)(logsDir)) {
|
|
28521
|
+
for (const entry of (0, import_node_fs55.readdirSync)(logsDir)) {
|
|
28827
28522
|
try {
|
|
28828
|
-
(0,
|
|
28523
|
+
(0, import_node_fs55.unlinkSync)((0, import_node_path39.join)(logsDir, entry));
|
|
28829
28524
|
} catch {
|
|
28830
28525
|
}
|
|
28831
28526
|
}
|
|
@@ -28837,7 +28532,7 @@ function registerResetCommand(program2) {
|
|
|
28837
28532
|
}
|
|
28838
28533
|
|
|
28839
28534
|
// src/commands/reflect.ts
|
|
28840
|
-
var
|
|
28535
|
+
var import_node_fs56 = require("node:fs");
|
|
28841
28536
|
|
|
28842
28537
|
// src/lib/reflection-globs.ts
|
|
28843
28538
|
var MAX_GLOBS = 6;
|
|
@@ -28875,7 +28570,7 @@ async function writeNodeToDisk(args) {
|
|
|
28875
28570
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
28876
28571
|
);
|
|
28877
28572
|
if (written === 0) return false;
|
|
28878
|
-
return (0,
|
|
28573
|
+
return (0, import_node_fs56.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
|
|
28879
28574
|
} catch {
|
|
28880
28575
|
return false;
|
|
28881
28576
|
}
|
|
@@ -29120,88 +28815,6 @@ function registerMemoryCommand(program2) {
|
|
|
29120
28815
|
if (!quiet) {
|
|
29121
28816
|
printInfo(result.status === "unchanged" ? "Knowledge graph is up to date." : result.status === "tracked" ? "Skipped: .verity/memory/ is tracked by git here, and the pull never rewrites tracked files. Run `verity memory untrack` to make the graph machine-local." : `Pulled ${result.received} node(s); ${result.written} new or updated file(s) written to .verity/memory/.`);
|
|
29122
28817
|
}
|
|
29123
|
-
let org;
|
|
29124
|
-
try {
|
|
29125
|
-
org = await pullOrgKnowledge({
|
|
29126
|
-
serviceUrl: urlResult.data,
|
|
29127
|
-
token: tokenResult.data.token,
|
|
29128
|
-
verbose: globals.verbose,
|
|
29129
|
-
force: !!opts.force
|
|
29130
|
-
});
|
|
29131
|
-
} catch (err) {
|
|
29132
|
-
org = { ok: false, error: err.message };
|
|
29133
|
-
}
|
|
29134
|
-
logEvent("memory_org_pull", org.ok ? { status: org.status, received: org.received } : { status: "failed", category: org.category ?? null });
|
|
29135
|
-
if (!quiet) {
|
|
29136
|
-
if (!org.ok) printWarn(`Could not refresh the org knowledge mirror: ${org.error}`);
|
|
29137
|
-
else if (org.status === "pulled") printInfo(`Org knowledge: ${org.received} claim(s) mirrored at ${org.dir}.`);
|
|
29138
|
-
else if (org.status === "unchanged") printInfo("Org knowledge mirror is up to date.");
|
|
29139
|
-
}
|
|
29140
|
-
process.exit(0);
|
|
29141
|
-
});
|
|
29142
|
-
memory.command("org").description("List the org knowledge mirrored for this repository's organization").action(async () => {
|
|
29143
|
-
try {
|
|
29144
|
-
process.chdir(repoRoot());
|
|
29145
|
-
} catch {
|
|
29146
|
-
}
|
|
29147
|
-
const dir = orgMirrorDir();
|
|
29148
|
-
if (!dir) {
|
|
29149
|
-
printError("Not a repository with an origin remote, so there is no organization to list.");
|
|
29150
|
-
process.exit(1);
|
|
29151
|
-
}
|
|
29152
|
-
const claims = await readOrgMirror();
|
|
29153
|
-
if (claims.length === 0) {
|
|
29154
|
-
printInfo(`No org knowledge mirrored yet (${dir}). Run \`verity memory pull\`.`);
|
|
29155
|
-
process.exit(0);
|
|
29156
|
-
}
|
|
29157
|
-
for (const c of claims) console.log(`${c.tag_id} ${c.kind.padEnd(11)} ${c.title} \xB7 ${c.origin}`);
|
|
29158
|
-
printInfo(`${claims.length} claim(s) at ${dir}. Demote one with \`verity memory demote <id> --reason "\u2026"\`.`);
|
|
29159
|
-
process.exit(0);
|
|
29160
|
-
});
|
|
29161
|
-
memory.command("demote <claim-id>").description("Demote an org knowledge claim for the whole organization, with a reason").requiredOption("--reason <text>", "Why this claim should no longer be shared (1\u2013500 characters)").action(async (claimId, opts) => {
|
|
29162
|
-
const globals = program2.opts();
|
|
29163
|
-
try {
|
|
29164
|
-
process.chdir(repoRoot());
|
|
29165
|
-
} catch {
|
|
29166
|
-
}
|
|
29167
|
-
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(claimId)) {
|
|
29168
|
-
printError("The claim id is the `id` in the mirrored file, a uuid. `verity memory org` lists them.");
|
|
29169
|
-
process.exit(1);
|
|
29170
|
-
}
|
|
29171
|
-
const reason = opts.reason.trim();
|
|
29172
|
-
if (reason.length === 0 || reason.length > 500) {
|
|
29173
|
-
printError("--reason is 1 to 500 characters.");
|
|
29174
|
-
process.exit(1);
|
|
29175
|
-
}
|
|
29176
|
-
const tokenResult = await resolveToken(globals.token);
|
|
29177
|
-
if (!tokenResult.ok) {
|
|
29178
|
-
printError(tokenResult.error);
|
|
29179
|
-
process.exit(1);
|
|
29180
|
-
}
|
|
29181
|
-
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
29182
|
-
if (!urlResult.ok) {
|
|
29183
|
-
printError(urlResult.error);
|
|
29184
|
-
process.exit(1);
|
|
29185
|
-
}
|
|
29186
|
-
const res = await apiRequest({
|
|
29187
|
-
method: "POST",
|
|
29188
|
-
path: `/memory/org/claims/${claimId}/demote`,
|
|
29189
|
-
serviceUrl: urlResult.data,
|
|
29190
|
-
token: tokenResult.data.token,
|
|
29191
|
-
body: { reason },
|
|
29192
|
-
verbose: globals.verbose,
|
|
29193
|
-
cmd: "memory-demote",
|
|
29194
|
-
extraHeaders: { "X-Verity-Via": "cli" }
|
|
29195
|
-
});
|
|
29196
|
-
if (!res.ok) {
|
|
29197
|
-
printError(`Could not demote the claim: ${res.error}`);
|
|
29198
|
-
process.exit(1);
|
|
29199
|
-
}
|
|
29200
|
-
printInfo(`Demoted ${claimId} for the whole organization. Restore it from the dashboard if that was wrong.`);
|
|
29201
|
-
try {
|
|
29202
|
-
await pullOrgKnowledge({ serviceUrl: urlResult.data, token: tokenResult.data.token, verbose: globals.verbose, force: true });
|
|
29203
|
-
} catch {
|
|
29204
|
-
}
|
|
29205
28818
|
process.exit(0);
|
|
29206
28819
|
});
|
|
29207
28820
|
memory.command("untrack").description("Stop committing .verity/memory/ \u2014 the graph stays on disk and leaves your diffs").action(() => {
|
|
@@ -29367,8 +28980,8 @@ function registerTelemetryCommands(program2) {
|
|
|
29367
28980
|
}
|
|
29368
28981
|
|
|
29369
28982
|
// src/cli.ts
|
|
29370
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.32.6-experimental.
|
|
29371
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.6-experimental.
|
|
28983
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.32.6-experimental.8f2b5f7").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
|
|
28984
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.6-experimental.8f2b5f7");
|
|
29372
28985
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
29373
28986
|
try {
|
|
29374
28987
|
await foldLegacyLocalCredential();
|