@codacy/verity-cli 0.32.0-experimental.68ae2ee → 0.32.0-experimental.f0746f7
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/CHANGELOG.md +2 -57
- package/bin/verity.js +822 -1088
- package/data/skills/verity-analyze/SKILL.md +0 -7
- package/data/skills/verity-feedback/SKILL.md +0 -6
- package/data/skills/verity-insights/SKILL.md +0 -7
- package/data/skills/verity-learn/SKILL.md +0 -6
- package/data/skills/verity-memory/SKILL.md +0 -7
- package/data/skills/verity-reflect/SKILL.md +0 -6
- package/data/skills/verity-setup/SKILL.md +5 -12
- package/data/skills/verity-status/SKILL.md +0 -6
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10405,8 +10405,6 @@ var MAX_INTENT_CHARS = 2e3;
|
|
|
10405
10405
|
var SNAPSHOT_DIR = `${VERITY_DIR}/.snapshot`;
|
|
10406
10406
|
var BASELINE_DIR = `${VERITY_DIR}/.baseline`;
|
|
10407
10407
|
var CONVERSATION_BUFFER_FILE = `${VERITY_DIR}/.conversation-buffer`;
|
|
10408
|
-
var PLUGIN_MARKER_FILE = `${VERITY_DIR}/.plugin-active`;
|
|
10409
|
-
var PROJECT_CONFIG_FILE = `${VERITY_DIR}/config.json`;
|
|
10410
10408
|
var CONVERSATION_MAX_ENTRIES = 10;
|
|
10411
10409
|
var CONVERSATION_WINDOW_MINUTES = 15;
|
|
10412
10410
|
var MAX_FINDINGS = 25;
|
|
@@ -10833,18 +10831,6 @@ function splitLines(s) {
|
|
|
10833
10831
|
}
|
|
10834
10832
|
var SHA_RE = /^[0-9a-f]{40}$/;
|
|
10835
10833
|
function readBaselineSha() {
|
|
10836
|
-
const sha = readRawBaselineSha();
|
|
10837
|
-
if (sha === null) return null;
|
|
10838
|
-
if (!commitResolves(sha)) {
|
|
10839
|
-
try {
|
|
10840
|
-
(0, import_node_fs3.unlinkSync)(BASELINE_SHA_FILE);
|
|
10841
|
-
} catch {
|
|
10842
|
-
}
|
|
10843
|
-
return null;
|
|
10844
|
-
}
|
|
10845
|
-
return sha;
|
|
10846
|
-
}
|
|
10847
|
-
function readRawBaselineSha() {
|
|
10848
10834
|
if (!(0, import_node_fs3.existsSync)(BASELINE_SHA_FILE)) return null;
|
|
10849
10835
|
let sha;
|
|
10850
10836
|
try {
|
|
@@ -10852,7 +10838,16 @@ function readRawBaselineSha() {
|
|
|
10852
10838
|
} catch {
|
|
10853
10839
|
return null;
|
|
10854
10840
|
}
|
|
10855
|
-
|
|
10841
|
+
if (!SHA_RE.test(sha)) return null;
|
|
10842
|
+
const reachable = execGit(`git cat-file -e ${sha}^{commit} 2>/dev/null && echo ok`) === "ok";
|
|
10843
|
+
if (!reachable) {
|
|
10844
|
+
try {
|
|
10845
|
+
(0, import_node_fs3.unlinkSync)(BASELINE_SHA_FILE);
|
|
10846
|
+
} catch {
|
|
10847
|
+
}
|
|
10848
|
+
return null;
|
|
10849
|
+
}
|
|
10850
|
+
return sha;
|
|
10856
10851
|
}
|
|
10857
10852
|
function writeBaselineSha(sha) {
|
|
10858
10853
|
if (!SHA_RE.test(sha)) return;
|
|
@@ -10862,25 +10857,6 @@ function writeBaselineSha(sha) {
|
|
|
10862
10857
|
} catch {
|
|
10863
10858
|
}
|
|
10864
10859
|
}
|
|
10865
|
-
function commitObjectExists(sha) {
|
|
10866
|
-
if (!SHA_RE.test(sha)) return false;
|
|
10867
|
-
return execGit(`git cat-file -e ${sha}^{commit} 2>/dev/null && echo ok`) === "ok";
|
|
10868
|
-
}
|
|
10869
|
-
function committedSinceRewrite(oldSha) {
|
|
10870
|
-
if (!SHA_RE.test(oldSha)) return [];
|
|
10871
|
-
const newLocal = new Set(splitLines(execGit(`git rev-list HEAD --not ${oldSha} --remotes`)));
|
|
10872
|
-
if (newLocal.size === 0) return [];
|
|
10873
|
-
const files = /* @__PURE__ */ new Set();
|
|
10874
|
-
for (const line of splitLines(execGit(`git cherry ${oldSha} HEAD`))) {
|
|
10875
|
-
const sp = line.indexOf(" ");
|
|
10876
|
-
if (sp < 0) continue;
|
|
10877
|
-
const mark = line.slice(0, sp);
|
|
10878
|
-
const sha = line.slice(sp + 1).trim();
|
|
10879
|
-
if (mark !== "+" || !newLocal.has(sha)) continue;
|
|
10880
|
-
for (const f of splitLines(execGit(`git diff-tree --no-commit-id --name-only -r ${sha}`))) files.add(f);
|
|
10881
|
-
}
|
|
10882
|
-
return [...files].filter((f) => !isVerityOwnedPath(f));
|
|
10883
|
-
}
|
|
10884
10860
|
var VERITY_OWNED_PREFIXES = [".verity/", ".gate/", ".codacy/"];
|
|
10885
10861
|
var VERITY_OWNED_FILES = ["VERITY.md"];
|
|
10886
10862
|
function isVerityOwnedPath(file) {
|
|
@@ -10893,7 +10869,6 @@ function getChangedFiles() {
|
|
|
10893
10869
|
for (const f of splitLines(execGit("git diff --name-only HEAD"))) sets.add(f);
|
|
10894
10870
|
for (const f of splitLines(execGit("git diff --name-only --cached"))) sets.add(f);
|
|
10895
10871
|
for (const f of splitLines(execGit("git ls-files --others --exclude-standard"))) sets.add(f);
|
|
10896
|
-
const rawBaseline = readRawBaselineSha();
|
|
10897
10872
|
const baseline = readBaselineSha();
|
|
10898
10873
|
if (baseline) {
|
|
10899
10874
|
const committed = splitLines(execGit(`git diff --name-only ${baseline}..HEAD`));
|
|
@@ -10901,13 +10876,6 @@ function getChangedFiles() {
|
|
|
10901
10876
|
hasRecentCommitFiles = true;
|
|
10902
10877
|
for (const f of committed) sets.add(f);
|
|
10903
10878
|
}
|
|
10904
|
-
} else if (rawBaseline && commitObjectExists(rawBaseline)) {
|
|
10905
|
-
const committed = committedSinceRewrite(rawBaseline);
|
|
10906
|
-
logEvent("baseline_rewritten", { recovered: committed.length });
|
|
10907
|
-
if (committed.length > 0) {
|
|
10908
|
-
hasRecentCommitFiles = true;
|
|
10909
|
-
for (const f of committed) sets.add(f);
|
|
10910
|
-
}
|
|
10911
10879
|
} else {
|
|
10912
10880
|
const headTimestamp = parseInt(execGit("git log -1 --format=%ct HEAD"), 10) || 0;
|
|
10913
10881
|
const commitAge = Math.floor(Date.now() / 1e3) - headTimestamp;
|
|
@@ -12733,155 +12701,9 @@ async function applyMomentSelection(moments) {
|
|
|
12733
12701
|
return settings;
|
|
12734
12702
|
}
|
|
12735
12703
|
|
|
12736
|
-
// src/lib/project-config.ts
|
|
12737
|
-
var import_node_fs4 = require("node:fs");
|
|
12738
|
-
var DEFAULTS = { git_moments: [] };
|
|
12739
|
-
function isMoment(value) {
|
|
12740
|
-
return value === "commit" || value === "push";
|
|
12741
|
-
}
|
|
12742
|
-
function parseMoments(raw) {
|
|
12743
|
-
return [...new Set(raw.split(",").map((s) => s.trim()).filter(isMoment))];
|
|
12744
|
-
}
|
|
12745
|
-
function readProjectConfig() {
|
|
12746
|
-
try {
|
|
12747
|
-
if (!(0, import_node_fs4.existsSync)(PROJECT_CONFIG_FILE)) return DEFAULTS;
|
|
12748
|
-
const raw = JSON.parse((0, import_node_fs4.readFileSync)(PROJECT_CONFIG_FILE, "utf-8"));
|
|
12749
|
-
const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
|
|
12750
|
-
return { git_moments: [...new Set(moments)] };
|
|
12751
|
-
} catch {
|
|
12752
|
-
return DEFAULTS;
|
|
12753
|
-
}
|
|
12754
|
-
}
|
|
12755
|
-
function writeProjectConfig(patch) {
|
|
12756
|
-
const next = { ...readProjectConfig(), ...patch };
|
|
12757
|
-
(0, import_node_fs4.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
12758
|
-
(0, import_node_fs4.writeFileSync)(PROJECT_CONFIG_FILE, JSON.stringify(next, null, 2) + "\n");
|
|
12759
|
-
return next;
|
|
12760
|
-
}
|
|
12761
|
-
function resolveGuardMoments(explicit) {
|
|
12762
|
-
if (explicit !== void 0) return parseMoments(explicit);
|
|
12763
|
-
return readProjectConfig().git_moments;
|
|
12764
|
-
}
|
|
12765
|
-
|
|
12766
|
-
// src/lib/plugin-ownership.ts
|
|
12767
|
-
var import_node_fs6 = require("node:fs");
|
|
12768
|
-
|
|
12769
|
-
// src/lib/stderr-log.ts
|
|
12770
|
-
var import_node_fs5 = require("node:fs");
|
|
12771
|
-
var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
|
|
12772
|
-
var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
12773
|
-
function scrub(s) {
|
|
12774
|
-
return s.replace(TOKEN_RE2, "verity_***REDACTED***").replace(ANSI_RE, "");
|
|
12775
|
-
}
|
|
12776
|
-
var installed = false;
|
|
12777
|
-
var wroteBanner = false;
|
|
12778
|
-
var banner = "";
|
|
12779
|
-
function append(text) {
|
|
12780
|
-
try {
|
|
12781
|
-
const dir = projectPath(DEBUG_LOG_DIR);
|
|
12782
|
-
const file = projectPath(STDERR_LOG_FILE);
|
|
12783
|
-
(0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
12784
|
-
rotateIfNeeded(file);
|
|
12785
|
-
(0, import_node_fs5.appendFileSync)(file, text);
|
|
12786
|
-
} catch {
|
|
12787
|
-
}
|
|
12788
|
-
}
|
|
12789
|
-
function ensureBanner() {
|
|
12790
|
-
if (wroteBanner) return;
|
|
12791
|
-
wroteBanner = true;
|
|
12792
|
-
append(banner);
|
|
12793
|
-
}
|
|
12794
|
-
function installStderrLog(cmd, argv, version) {
|
|
12795
|
-
if (installed || !isDebugEnabled()) return;
|
|
12796
|
-
installed = true;
|
|
12797
|
-
banner = `
|
|
12798
|
-
\u2501\u2501 verity ${cmd} \xB7 ${(/* @__PURE__ */ new Date()).toISOString()} \xB7 pid ${process.pid}
|
|
12799
|
-
v${version} \xB7 ${process.cwd()}
|
|
12800
|
-
argv: ${scrub(argv.join(" "))}
|
|
12801
|
-
`;
|
|
12802
|
-
const original = process.stderr.write.bind(process.stderr);
|
|
12803
|
-
const tee = (...args) => {
|
|
12804
|
-
const result = original(...args);
|
|
12805
|
-
try {
|
|
12806
|
-
const chunk = args[0];
|
|
12807
|
-
const text = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
|
|
12808
|
-
ensureBanner();
|
|
12809
|
-
append(scrub(text));
|
|
12810
|
-
} catch {
|
|
12811
|
-
}
|
|
12812
|
-
return result;
|
|
12813
|
-
};
|
|
12814
|
-
process.stderr.write = tee;
|
|
12815
|
-
}
|
|
12816
|
-
function logToFileOnly(text) {
|
|
12817
|
-
if (!installed) return;
|
|
12818
|
-
ensureBanner();
|
|
12819
|
-
append(text.endsWith("\n") ? text : `${text}
|
|
12820
|
-
`);
|
|
12821
|
-
}
|
|
12822
|
-
|
|
12823
|
-
// src/lib/plugin-ownership.ts
|
|
12824
|
-
var MARKER_TTL_SECONDS = 24 * 60 * 60;
|
|
12825
|
-
function isPluginInvocation() {
|
|
12826
|
-
return !!process.env.VERITY_PLUGIN_ROOT;
|
|
12827
|
-
}
|
|
12828
|
-
function readMarker() {
|
|
12829
|
-
try {
|
|
12830
|
-
if (!(0, import_node_fs6.existsSync)(PLUGIN_MARKER_FILE)) return null;
|
|
12831
|
-
const raw = JSON.parse((0, import_node_fs6.readFileSync)(PLUGIN_MARKER_FILE, "utf-8"));
|
|
12832
|
-
const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
|
|
12833
|
-
if (!pluginRoot) return null;
|
|
12834
|
-
return {
|
|
12835
|
-
session_id: typeof raw.session_id === "string" ? raw.session_id : null,
|
|
12836
|
-
plugin_root: pluginRoot,
|
|
12837
|
-
version: typeof raw.version === "string" ? raw.version : null,
|
|
12838
|
-
ts: typeof raw.ts === "number" ? raw.ts : 0
|
|
12839
|
-
};
|
|
12840
|
-
} catch {
|
|
12841
|
-
return null;
|
|
12842
|
-
}
|
|
12843
|
-
}
|
|
12844
|
-
function recordPluginOwnership(sessionId) {
|
|
12845
|
-
const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
12846
|
-
if (!pluginRoot) return;
|
|
12847
|
-
try {
|
|
12848
|
-
(0, import_node_fs6.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
12849
|
-
const marker = {
|
|
12850
|
-
session_id: sessionId,
|
|
12851
|
-
plugin_root: pluginRoot,
|
|
12852
|
-
version: process.env.VERITY_PLUGIN_VERSION || null,
|
|
12853
|
-
ts: Math.floor(Date.now() / 1e3)
|
|
12854
|
-
};
|
|
12855
|
-
(0, import_node_fs6.writeFileSync)(PLUGIN_MARKER_FILE, JSON.stringify(marker));
|
|
12856
|
-
} catch {
|
|
12857
|
-
}
|
|
12858
|
-
}
|
|
12859
|
-
function shouldDeferToPlugin(sessionId) {
|
|
12860
|
-
if (isPluginInvocation()) {
|
|
12861
|
-
recordPluginOwnership(sessionId);
|
|
12862
|
-
return false;
|
|
12863
|
-
}
|
|
12864
|
-
const marker = readMarker();
|
|
12865
|
-
if (!marker) return false;
|
|
12866
|
-
if (!(0, import_node_fs6.existsSync)(marker.plugin_root)) return false;
|
|
12867
|
-
if (sessionId && marker.session_id) return sessionId === marker.session_id;
|
|
12868
|
-
return Math.floor(Date.now() / 1e3) - marker.ts < MARKER_TTL_SECONDS;
|
|
12869
|
-
}
|
|
12870
|
-
function pluginActiveHere() {
|
|
12871
|
-
const marker = readMarker();
|
|
12872
|
-
return !!marker && (0, import_node_fs6.existsSync)(marker.plugin_root);
|
|
12873
|
-
}
|
|
12874
|
-
function deferredToPlugin(command, sessionId) {
|
|
12875
|
-
if (!shouldDeferToPlugin(sessionId)) return false;
|
|
12876
|
-
logToFileOnly(
|
|
12877
|
-
`${command}: the Verity Claude Code plugin owns this session's hooks \u2014 standing down so the turn is not gated twice. Remove the duplicate settings.json hooks with \`verity init --plugin-mode\`.`
|
|
12878
|
-
);
|
|
12879
|
-
return true;
|
|
12880
|
-
}
|
|
12881
|
-
|
|
12882
12704
|
// src/commands/hooks.ts
|
|
12883
12705
|
var ALL_MOMENTS = ["stop", "pre-commit", "pre-push"];
|
|
12884
|
-
function
|
|
12706
|
+
function parseMoments(raw) {
|
|
12885
12707
|
const seen = /* @__PURE__ */ new Set();
|
|
12886
12708
|
for (const part of raw.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
12887
12709
|
if (ALL_MOMENTS.includes(part)) seen.add(part);
|
|
@@ -12893,22 +12715,7 @@ function registerHooksCommands(program2) {
|
|
|
12893
12715
|
hooks.command("install").description("Install Verity hooks into Claude Code settings").option("--force", "Overwrite existing Verity hooks").option("--moments <list>", "Reconcile to exactly these moments: stop,pre-commit,pre-push").action(async (opts) => {
|
|
12894
12716
|
const force = opts.force ?? false;
|
|
12895
12717
|
if (opts.moments != null) {
|
|
12896
|
-
const moments =
|
|
12897
|
-
const gitMoments = [
|
|
12898
|
-
...moments.includes("pre-commit") ? ["commit"] : [],
|
|
12899
|
-
...moments.includes("pre-push") ? ["push"] : []
|
|
12900
|
-
];
|
|
12901
|
-
writeProjectConfig({ git_moments: gitMoments });
|
|
12902
|
-
if (pluginActiveHere()) {
|
|
12903
|
-
printInfo("The Verity plugin wires the hooks; recorded your selection in .verity/config.json:");
|
|
12904
|
-
printInfo(` Stop (analysis on every turn): ${moments.includes("stop") ? "on" : "off \u2014 the plugin still wires it; see below"}`);
|
|
12905
|
-
printInfo(` Pre-commit gate: ${gitMoments.includes("commit") ? "on" : "off"}`);
|
|
12906
|
-
printInfo(` Pre-push/PR gate: ${gitMoments.includes("push") ? "on" : "off"}`);
|
|
12907
|
-
if (!moments.includes("stop")) {
|
|
12908
|
-
printWarn(" Turning the Stop review off is not yet supported under the plugin \u2014 it stays on.");
|
|
12909
|
-
}
|
|
12910
|
-
return;
|
|
12911
|
-
}
|
|
12718
|
+
const moments = parseMoments(opts.moments);
|
|
12912
12719
|
await applyMomentSelection(moments);
|
|
12913
12720
|
const status = await checkAllVerityHooks();
|
|
12914
12721
|
printInfo("Verity hooks reconciled in .claude/settings.json:");
|
|
@@ -12955,24 +12762,6 @@ function registerHooksCommands(program2) {
|
|
|
12955
12762
|
});
|
|
12956
12763
|
hooks.command("check").description("Check if Verity hooks are installed").action(async () => {
|
|
12957
12764
|
const status = await checkAllVerityHooks();
|
|
12958
|
-
if (pluginActiveHere()) {
|
|
12959
|
-
const moments = readProjectConfig().git_moments;
|
|
12960
|
-
printInfo("Wired by the Verity Claude Code plugin (not .claude/settings.json):");
|
|
12961
|
-
printInfo(" Stop hook (verity analyze): installed");
|
|
12962
|
-
printInfo(" Intent hook (verity intent capture): installed");
|
|
12963
|
-
printInfo(" Baseline hook (verity baseline capture): installed");
|
|
12964
|
-
printInfo(
|
|
12965
|
-
` Git-moment gate (verity guard): ${moments.length ? `installed [${moments.join(", ")}]` : "wired but gating nothing"}`
|
|
12966
|
-
);
|
|
12967
|
-
if (!moments.length) {
|
|
12968
|
-
printInfo(' Enable it with "verity config git-moments commit,push".');
|
|
12969
|
-
}
|
|
12970
|
-
if (status.stop || status.intent || status.baseline || status.guard) {
|
|
12971
|
-
printWarn(" Duplicate hooks also exist in .claude/settings.json. They stand down at run time,");
|
|
12972
|
-
printWarn(' but remove them with "verity init --plugin-mode" so the wiring says what it does.');
|
|
12973
|
-
}
|
|
12974
|
-
return;
|
|
12975
|
-
}
|
|
12976
12765
|
printInfo(`Stop hook (verity analyze): ${status.stop ? "installed" : "not installed"}`);
|
|
12977
12766
|
printInfo(`Intent hook (verity intent capture): ${status.intent ? "installed" : "not installed"}`);
|
|
12978
12767
|
printInfo(`Baseline hook (verity baseline capture): ${status.baseline ? "installed" : "not installed"}`);
|
|
@@ -12998,7 +12787,7 @@ var import_node_crypto8 = require("node:crypto");
|
|
|
12998
12787
|
|
|
12999
12788
|
// src/lib/conversation-buffer.ts
|
|
13000
12789
|
var import_promises5 = require("node:fs/promises");
|
|
13001
|
-
var
|
|
12790
|
+
var import_node_fs4 = require("node:fs");
|
|
13002
12791
|
var import_node_child_process5 = require("node:child_process");
|
|
13003
12792
|
var import_node_crypto = require("node:crypto");
|
|
13004
12793
|
function stripImageReferences(text) {
|
|
@@ -13034,7 +12823,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
13034
12823
|
}
|
|
13035
12824
|
async function readAndClearConversationBuffer(currentSessionId) {
|
|
13036
12825
|
try {
|
|
13037
|
-
if ((0,
|
|
12826
|
+
if ((0, import_node_fs4.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
13038
12827
|
const entries = await readBufferEntries();
|
|
13039
12828
|
let mine = entries;
|
|
13040
12829
|
let others = [];
|
|
@@ -13058,7 +12847,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
|
|
|
13058
12847
|
};
|
|
13059
12848
|
}
|
|
13060
12849
|
}
|
|
13061
|
-
if ((0,
|
|
12850
|
+
if ((0, import_node_fs4.existsSync)(INTENT_FILE)) {
|
|
13062
12851
|
try {
|
|
13063
12852
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
13064
12853
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -13113,301 +12902,65 @@ function getRecentCommitMessages() {
|
|
|
13113
12902
|
}
|
|
13114
12903
|
}
|
|
13115
12904
|
|
|
13116
|
-
// src/lib/
|
|
13117
|
-
var
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
"
|
|
13123
|
-
"
|
|
13124
|
-
"
|
|
13125
|
-
"
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
"
|
|
13129
|
-
"
|
|
13130
|
-
"
|
|
13131
|
-
"
|
|
13132
|
-
"
|
|
13133
|
-
"
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
].join("|"),
|
|
13146
|
-
"i"
|
|
13147
|
-
);
|
|
13148
|
-
var FALSE_POSITIVE_PATTERNS = [
|
|
13149
|
-
/\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
|
|
13150
|
-
/\berror\s+handling\b/i,
|
|
13151
|
-
/\berror\s+boundar(?:y|ies)\b/i,
|
|
13152
|
-
/\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
|
|
13153
|
-
/\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
|
|
13154
|
-
];
|
|
13155
|
-
function hasDebugIntent(prompt) {
|
|
13156
|
-
if (!DEBUG_PATTERN.test(prompt)) return false;
|
|
13157
|
-
for (const fp of FALSE_POSITIVE_PATTERNS) {
|
|
13158
|
-
if (fp.test(prompt)) return false;
|
|
12905
|
+
// src/lib/context-identity.ts
|
|
12906
|
+
var import_node_crypto2 = require("node:crypto");
|
|
12907
|
+
var import_node_fs5 = require("node:fs");
|
|
12908
|
+
var import_node_os2 = require("node:os");
|
|
12909
|
+
var import_node_path6 = require("node:path");
|
|
12910
|
+
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
12911
|
+
"",
|
|
12912
|
+
"-",
|
|
12913
|
+
"n/a",
|
|
12914
|
+
"na",
|
|
12915
|
+
"none",
|
|
12916
|
+
"null",
|
|
12917
|
+
"undefined",
|
|
12918
|
+
"unknown",
|
|
12919
|
+
"anon",
|
|
12920
|
+
"anonymous",
|
|
12921
|
+
"default",
|
|
12922
|
+
"_default"
|
|
12923
|
+
]);
|
|
12924
|
+
function isSharedSentinel(value) {
|
|
12925
|
+
if (value == null) return true;
|
|
12926
|
+
return SHARED_SENTINELS.has(value.trim().toLowerCase());
|
|
12927
|
+
}
|
|
12928
|
+
var ephemeral = /* @__PURE__ */ new Map();
|
|
12929
|
+
function ephemeralId(slot, width) {
|
|
12930
|
+
let id = ephemeral.get(slot);
|
|
12931
|
+
if (!id) {
|
|
12932
|
+
id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
|
|
12933
|
+
ephemeral.set(slot, id);
|
|
13159
12934
|
}
|
|
13160
|
-
return
|
|
12935
|
+
return id;
|
|
13161
12936
|
}
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
12937
|
+
function contextIdentity(input) {
|
|
12938
|
+
const tokenUsable = !isSharedSentinel(input.token ?? null);
|
|
12939
|
+
const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
|
|
12940
|
+
const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
|
|
12941
|
+
const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
|
|
12942
|
+
let treeKey = "no-tree";
|
|
12943
|
+
const rawTree = input.treeRoot;
|
|
12944
|
+
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
12945
|
+
let resolved = rawTree;
|
|
12946
|
+
try {
|
|
12947
|
+
resolved = import_node_fs5.realpathSync.native(rawTree);
|
|
12948
|
+
} catch {
|
|
12949
|
+
}
|
|
12950
|
+
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
12951
|
+
}
|
|
12952
|
+
return {
|
|
12953
|
+
userKey,
|
|
12954
|
+
treeKey,
|
|
12955
|
+
sessionKey: sessionKey2,
|
|
12956
|
+
userKeySource: tokenUsable ? "token" : "ephemeral",
|
|
12957
|
+
sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
|
|
12958
|
+
ephemeral: !tokenUsable || !sessionUsable
|
|
12959
|
+
};
|
|
13168
12960
|
}
|
|
13169
|
-
function
|
|
13170
|
-
const
|
|
13171
|
-
|
|
13172
|
-
const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
|
|
13173
|
-
if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
|
|
13174
|
-
return mode2;
|
|
13175
|
-
}
|
|
13176
|
-
function resolveAnalysisMode(predictedMode, signals) {
|
|
13177
|
-
if (!predictedMode || !isValidMode(predictedMode)) {
|
|
13178
|
-
return detectAnalysisMode(
|
|
13179
|
-
signals.noFilesChanged,
|
|
13180
|
-
signals.assistantResponse,
|
|
13181
|
-
signals.conversationPrompts,
|
|
13182
|
-
signals.actionSummary,
|
|
13183
|
-
signals.sessionAuthoredCode
|
|
13184
|
-
);
|
|
13185
|
-
}
|
|
13186
|
-
const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
|
|
13187
|
-
const agentInvestigated = didAgentInvestigate(signals.actionSummary);
|
|
13188
|
-
switch (predictedMode) {
|
|
13189
|
-
case "skip":
|
|
13190
|
-
if (agentAuthoredCode) return "standard";
|
|
13191
|
-
return "skip";
|
|
13192
|
-
case "plan":
|
|
13193
|
-
if (agentAuthoredCode) return "standard";
|
|
13194
|
-
return "plan";
|
|
13195
|
-
case "debug":
|
|
13196
|
-
return "debug";
|
|
13197
|
-
case "standard":
|
|
13198
|
-
if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
|
|
13199
|
-
return agentInvestigated ? "plan" : "skip";
|
|
13200
|
-
}
|
|
13201
|
-
return "standard";
|
|
13202
|
-
}
|
|
13203
|
-
}
|
|
13204
|
-
function didAgentInvestigate(summary) {
|
|
13205
|
-
if (!summary) return false;
|
|
13206
|
-
return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
|
|
13207
|
-
}
|
|
13208
|
-
function isValidMode(mode2) {
|
|
13209
|
-
return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
|
|
13210
|
-
}
|
|
13211
|
-
function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
|
|
13212
|
-
const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
|
|
13213
|
-
if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
|
|
13214
|
-
if (!agentAuthoredCode) return "skip";
|
|
13215
|
-
}
|
|
13216
|
-
if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
|
|
13217
|
-
return "plan";
|
|
13218
|
-
}
|
|
13219
|
-
if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
|
|
13220
|
-
return didAgentInvestigate(actionSummary) ? "plan" : "skip";
|
|
13221
|
-
}
|
|
13222
|
-
for (const prompt of conversationPrompts) {
|
|
13223
|
-
if (hasDebugIntent(prompt)) {
|
|
13224
|
-
return "debug";
|
|
13225
|
-
}
|
|
13226
|
-
}
|
|
13227
|
-
return "standard";
|
|
13228
|
-
}
|
|
13229
|
-
var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
|
|
13230
|
-
var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
|
|
13231
|
-
var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
|
|
13232
|
-
var CHAIN_RE = /&&|\||;|\$\(|\x60/;
|
|
13233
|
-
function isNonAuthoringCommand(cmd) {
|
|
13234
|
-
if (typeof cmd !== "string" || cmd.trim().length === 0) return false;
|
|
13235
|
-
if (FILE_MUTATE_RE.test(cmd)) return false;
|
|
13236
|
-
if (CHAIN_RE.test(cmd)) return false;
|
|
13237
|
-
return GIT_PLUMBING_RE.test(cmd) || READ_ONLY_RE.test(cmd);
|
|
13238
|
-
}
|
|
13239
|
-
function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
|
|
13240
|
-
if (!actionSummary) return sessionAuthoredCode;
|
|
13241
|
-
if ((actionSummary.subagents ?? 0) > 0) return true;
|
|
13242
|
-
if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
|
|
13243
|
-
const commands = actionSummary.commands ?? [];
|
|
13244
|
-
if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
|
|
13245
|
-
if (sessionAuthoredCode) {
|
|
13246
|
-
const allSafe = commands.length > 0 && commands.every(isNonAuthoringCommand);
|
|
13247
|
-
if (!allSafe) return true;
|
|
13248
|
-
}
|
|
13249
|
-
return false;
|
|
13250
|
-
}
|
|
13251
|
-
function scopeToAuthored(files, actionSummary) {
|
|
13252
|
-
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
13253
|
-
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
13254
|
-
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
13255
|
-
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
13256
|
-
}
|
|
13257
|
-
function chooseReviewScope(input) {
|
|
13258
|
-
if (input.narrowingIsTrustworthy) return input.scopedFiles;
|
|
13259
|
-
if (input.recoveredScope.length > 0) return input.recoveredScope;
|
|
13260
|
-
return input.authorshipWasObservable ? [] : input.allForReview;
|
|
13261
|
-
}
|
|
13262
|
-
function narrowToAgentAuthored(files, actionSummary) {
|
|
13263
|
-
if (!actionSummary) return files;
|
|
13264
|
-
const touched = [
|
|
13265
|
-
...actionSummary.files_edited,
|
|
13266
|
-
...actionSummary.files_created
|
|
13267
|
-
];
|
|
13268
|
-
if (touched.length === 0) return files;
|
|
13269
|
-
return files.filter((f) => {
|
|
13270
|
-
const suffix = "/" + f;
|
|
13271
|
-
return touched.some((t) => t === f || t.endsWith(suffix));
|
|
13272
|
-
});
|
|
13273
|
-
}
|
|
13274
|
-
|
|
13275
|
-
// src/lib/skip-detection.ts
|
|
13276
|
-
function isBareAckPrompt(prompt) {
|
|
13277
|
-
if (typeof prompt !== "string") return false;
|
|
13278
|
-
const trimmed = prompt.trim();
|
|
13279
|
-
if (trimmed.length === 0) return false;
|
|
13280
|
-
if (trimmed.length > 20) return false;
|
|
13281
|
-
const bareAckPattern = /^(\d{1,2}|y|n|yes|no|yep|nope|ok(ay)?|sure|skip|cancel|stop|done|noted|got\s+it|sounds\s+good|thanks|thank\s+you|thx)[.!?]*$/i;
|
|
13282
|
-
return bareAckPattern.test(trimmed);
|
|
13283
|
-
}
|
|
13284
|
-
function isContinuationPrompt(prompt) {
|
|
13285
|
-
if (typeof prompt !== "string") return false;
|
|
13286
|
-
const trimmed = prompt.trim();
|
|
13287
|
-
if (trimmed.length === 0) return false;
|
|
13288
|
-
if (trimmed.length > 24) return false;
|
|
13289
|
-
const continuation = /^(let['’]?s\s+(go|do\s+it|start|continue)|go|go\s+ahead|go\s+on|proceed|continue|carry\s+on|keep\s+going|do\s+it|make\s+it\s+so|next|start|begin|ship\s+it|yes\s+please|please\s+continue|perfect|great|nice|excellent|agreed)[.!]*$/i;
|
|
13290
|
-
return continuation.test(trimmed) || isBareAckPrompt(trimmed);
|
|
13291
|
-
}
|
|
13292
|
-
function isSlashCommand(prompt) {
|
|
13293
|
-
if (typeof prompt !== "string") return false;
|
|
13294
|
-
return /^\s*\/[A-Za-z][\w-]*(\s|$)/.test(prompt);
|
|
13295
|
-
}
|
|
13296
|
-
function resolveGoalPrompt(prompts) {
|
|
13297
|
-
if (prompts.length === 0) return null;
|
|
13298
|
-
const latest = prompts[prompts.length - 1];
|
|
13299
|
-
if (!isContinuationPrompt(latest.prompt)) return { entry: latest, turnsBack: 0 };
|
|
13300
|
-
for (let i = prompts.length - 2; i >= 0; i--) {
|
|
13301
|
-
if (!isContinuationPrompt(prompts[i].prompt)) {
|
|
13302
|
-
return { entry: prompts[i], turnsBack: prompts.length - 1 - i };
|
|
13303
|
-
}
|
|
13304
|
-
}
|
|
13305
|
-
return { entry: latest, turnsBack: 0 };
|
|
13306
|
-
}
|
|
13307
|
-
function isReflectionQuestion(response) {
|
|
13308
|
-
if (!response || typeof response !== "string") return false;
|
|
13309
|
-
const markers = [
|
|
13310
|
-
/reflection\s+for\s+future\s+agents/i,
|
|
13311
|
-
/what(?:'s|\s+is)\s+one\s+thing\s+you\s+learned/i,
|
|
13312
|
-
/say\s+['"]?skip['"]?\s+to\s+skip/i,
|
|
13313
|
-
/quick\s+reflection\s+question/i,
|
|
13314
|
-
// Post-flip (VRT-21): the agent drafts the reflection itself and, when
|
|
13315
|
-
// interactive, asks the user to confirm/correct before recording. That
|
|
13316
|
-
// turn authors no code either, so it's still a reflection turn.
|
|
13317
|
-
/reflection\s+draft/i,
|
|
13318
|
-
/confirm,?\s+correct,?\s+or\s+add/i
|
|
13319
|
-
];
|
|
13320
|
-
return markers.some((m) => m.test(response));
|
|
13321
|
-
}
|
|
13322
|
-
function isMetaTaskLabel(label2) {
|
|
13323
|
-
if (label2 === null || label2 === void 0) return false;
|
|
13324
|
-
if (typeof label2 !== "string") return false;
|
|
13325
|
-
const trimmed = label2.trim();
|
|
13326
|
-
if (trimmed.length === 0) return true;
|
|
13327
|
-
const metaPatterns = [
|
|
13328
|
-
/^verity\s+[\w-]+\s+response$/i,
|
|
13329
|
-
// "Verity reflect response"
|
|
13330
|
-
/^simple user response$/i,
|
|
13331
|
-
/^verity\s+command$/i,
|
|
13332
|
-
// "Verity command"
|
|
13333
|
-
/^user\s+(question|reply|response|ack)$/i
|
|
13334
|
-
];
|
|
13335
|
-
return metaPatterns.some((p) => p.test(trimmed));
|
|
13336
|
-
}
|
|
13337
|
-
function shouldSkipForBareAck(input) {
|
|
13338
|
-
if (!isBareAckPrompt(input.prompt)) return false;
|
|
13339
|
-
if (input.turnAuthoredCode) return false;
|
|
13340
|
-
return input.canSeeTurnAuthorship;
|
|
13341
|
-
}
|
|
13342
|
-
function isCommandOnlyTurn(input) {
|
|
13343
|
-
if (!input.authorshipIsObservable) return false;
|
|
13344
|
-
if (input.userCommandsTruncated) return false;
|
|
13345
|
-
const commands = input.userCommands ?? [];
|
|
13346
|
-
if (commands.length === 0) return false;
|
|
13347
|
-
if (input.agentAuthoredFiles > 0) return false;
|
|
13348
|
-
if (input.agentToolCalls > 0) return false;
|
|
13349
|
-
return commands.every(isNonAuthoringCommand);
|
|
13350
|
-
}
|
|
13351
|
-
|
|
13352
|
-
// src/lib/context-identity.ts
|
|
13353
|
-
var import_node_crypto2 = require("node:crypto");
|
|
13354
|
-
var import_node_fs8 = require("node:fs");
|
|
13355
|
-
var import_node_os2 = require("node:os");
|
|
13356
|
-
var import_node_path6 = require("node:path");
|
|
13357
|
-
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
13358
|
-
"",
|
|
13359
|
-
"-",
|
|
13360
|
-
"n/a",
|
|
13361
|
-
"na",
|
|
13362
|
-
"none",
|
|
13363
|
-
"null",
|
|
13364
|
-
"undefined",
|
|
13365
|
-
"unknown",
|
|
13366
|
-
"anon",
|
|
13367
|
-
"anonymous",
|
|
13368
|
-
"default",
|
|
13369
|
-
"_default"
|
|
13370
|
-
]);
|
|
13371
|
-
function isSharedSentinel(value) {
|
|
13372
|
-
if (value == null) return true;
|
|
13373
|
-
return SHARED_SENTINELS.has(value.trim().toLowerCase());
|
|
13374
|
-
}
|
|
13375
|
-
var ephemeral = /* @__PURE__ */ new Map();
|
|
13376
|
-
function ephemeralId(slot, width) {
|
|
13377
|
-
let id = ephemeral.get(slot);
|
|
13378
|
-
if (!id) {
|
|
13379
|
-
id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
|
|
13380
|
-
ephemeral.set(slot, id);
|
|
13381
|
-
}
|
|
13382
|
-
return id;
|
|
13383
|
-
}
|
|
13384
|
-
function contextIdentity(input) {
|
|
13385
|
-
const tokenUsable = !isSharedSentinel(input.token ?? null);
|
|
13386
|
-
const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
|
|
13387
|
-
const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
|
|
13388
|
-
const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
|
|
13389
|
-
let treeKey = "no-tree";
|
|
13390
|
-
const rawTree = input.treeRoot;
|
|
13391
|
-
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
13392
|
-
let resolved = rawTree;
|
|
13393
|
-
try {
|
|
13394
|
-
resolved = import_node_fs8.realpathSync.native(rawTree);
|
|
13395
|
-
} catch {
|
|
13396
|
-
}
|
|
13397
|
-
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
13398
|
-
}
|
|
13399
|
-
return {
|
|
13400
|
-
userKey,
|
|
13401
|
-
treeKey,
|
|
13402
|
-
sessionKey: sessionKey2,
|
|
13403
|
-
userKeySource: tokenUsable ? "token" : "ephemeral",
|
|
13404
|
-
sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
|
|
13405
|
-
ephemeral: !tokenUsable || !sessionUsable
|
|
13406
|
-
};
|
|
13407
|
-
}
|
|
13408
|
-
function verityHome() {
|
|
13409
|
-
const override = process.env.VERITY_HOME;
|
|
13410
|
-
return override && override.trim() ? (0, import_node_path6.resolve)(override) : (0, import_node_path6.join)((0, import_node_os2.homedir)(), ".verity");
|
|
12961
|
+
function verityHome() {
|
|
12962
|
+
const override = process.env.VERITY_HOME;
|
|
12963
|
+
return override && override.trim() ? (0, import_node_path6.resolve)(override) : (0, import_node_path6.join)((0, import_node_os2.homedir)(), ".verity");
|
|
13411
12964
|
}
|
|
13412
12965
|
function dossierDir(identity) {
|
|
13413
12966
|
return (0, import_node_path6.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
@@ -13428,7 +12981,7 @@ function sessionScopeKey(token, sessionId) {
|
|
|
13428
12981
|
|
|
13429
12982
|
// src/lib/task-context-buffer.ts
|
|
13430
12983
|
var import_promises6 = require("node:fs/promises");
|
|
13431
|
-
var
|
|
12984
|
+
var import_node_fs6 = require("node:fs");
|
|
13432
12985
|
var import_node_path7 = require("node:path");
|
|
13433
12986
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
13434
12987
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
@@ -13468,7 +13021,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
|
|
|
13468
13021
|
}
|
|
13469
13022
|
async function readTaskContextBuffer(taskId) {
|
|
13470
13023
|
const filePath = bufferPath(taskId);
|
|
13471
|
-
if (!(0,
|
|
13024
|
+
if (!(0, import_node_fs6.existsSync)(filePath)) return null;
|
|
13472
13025
|
try {
|
|
13473
13026
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
13474
13027
|
if (!content.trim()) return null;
|
|
@@ -13502,7 +13055,7 @@ async function readTaskContextBuffer(taskId) {
|
|
|
13502
13055
|
}
|
|
13503
13056
|
async function cleanupTaskContextBuffers() {
|
|
13504
13057
|
try {
|
|
13505
|
-
if (!(0,
|
|
13058
|
+
if (!(0, import_node_fs6.existsSync)(TASK_CONTEXT_DIR)) return;
|
|
13506
13059
|
const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
|
|
13507
13060
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
13508
13061
|
for (const file of files) {
|
|
@@ -13527,7 +13080,7 @@ async function appendEntry(taskId, entry) {
|
|
|
13527
13080
|
try {
|
|
13528
13081
|
await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
|
|
13529
13082
|
const filePath = bufferPath(taskId);
|
|
13530
|
-
if ((0,
|
|
13083
|
+
if ((0, import_node_fs6.existsSync)(filePath)) {
|
|
13531
13084
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
13532
13085
|
if (stats.size >= MAX_BUFFER_BYTES) {
|
|
13533
13086
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
@@ -13538,7 +13091,7 @@ async function appendEntry(taskId, entry) {
|
|
|
13538
13091
|
}
|
|
13539
13092
|
}
|
|
13540
13093
|
const line = JSON.stringify(entry) + "\n";
|
|
13541
|
-
const existing = (0,
|
|
13094
|
+
const existing = (0, import_node_fs6.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
|
|
13542
13095
|
await (0, import_promises6.writeFile)(filePath, existing + line);
|
|
13543
13096
|
} catch {
|
|
13544
13097
|
}
|
|
@@ -13546,7 +13099,7 @@ async function appendEntry(taskId, entry) {
|
|
|
13546
13099
|
|
|
13547
13100
|
// src/lib/memory-retrieval.ts
|
|
13548
13101
|
var import_promises7 = require("node:fs/promises");
|
|
13549
|
-
var
|
|
13102
|
+
var import_node_fs7 = require("node:fs");
|
|
13550
13103
|
var import_node_path8 = require("node:path");
|
|
13551
13104
|
var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
|
|
13552
13105
|
var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
|
|
@@ -13640,13 +13193,13 @@ function parseFrontmatter(content) {
|
|
|
13640
13193
|
return { fm, body: match[2].trim() };
|
|
13641
13194
|
}
|
|
13642
13195
|
async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
|
|
13643
|
-
if (!(0,
|
|
13196
|
+
if (!(0, import_node_fs7.existsSync)(memoryDir())) return null;
|
|
13644
13197
|
const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
|
|
13645
13198
|
const promptTokens = tokenize(promptText);
|
|
13646
13199
|
const nodes = [];
|
|
13647
13200
|
for (const domain of DOMAINS) {
|
|
13648
13201
|
const domainDir = (0, import_node_path8.join)(memoryDir(), domain);
|
|
13649
|
-
if (!(0,
|
|
13202
|
+
if (!(0, import_node_fs7.existsSync)(domainDir)) continue;
|
|
13650
13203
|
try {
|
|
13651
13204
|
const files = await (0, import_promises7.readdir)(domainDir);
|
|
13652
13205
|
for (const file of files) {
|
|
@@ -13711,12 +13264,12 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
13711
13264
|
|
|
13712
13265
|
// src/lib/memory-sync.ts
|
|
13713
13266
|
var import_promises8 = require("node:fs/promises");
|
|
13714
|
-
var
|
|
13267
|
+
var import_node_fs9 = require("node:fs");
|
|
13715
13268
|
var import_node_path10 = require("node:path");
|
|
13716
13269
|
var import_node_crypto3 = require("node:crypto");
|
|
13717
13270
|
|
|
13718
13271
|
// src/lib/safe-path.ts
|
|
13719
|
-
var
|
|
13272
|
+
var import_node_fs8 = require("node:fs");
|
|
13720
13273
|
var import_node_path9 = require("node:path");
|
|
13721
13274
|
function resolveInside(baseDir, candidate) {
|
|
13722
13275
|
if (typeof candidate !== "string" || candidate.length === 0) return null;
|
|
@@ -13726,16 +13279,16 @@ function resolveInside(baseDir, candidate) {
|
|
|
13726
13279
|
const baseSep = baseAbs.endsWith(import_node_path9.sep) ? baseAbs : baseAbs + import_node_path9.sep;
|
|
13727
13280
|
if (full !== baseAbs && !full.startsWith(baseSep)) return null;
|
|
13728
13281
|
try {
|
|
13729
|
-
if ((0,
|
|
13730
|
-
const realBase = (0,
|
|
13282
|
+
if ((0, import_node_fs8.existsSync)(baseAbs)) {
|
|
13283
|
+
const realBase = (0, import_node_fs8.realpathSync)(baseAbs);
|
|
13731
13284
|
const realBaseSep = realBase.endsWith(import_node_path9.sep) ? realBase : realBase + import_node_path9.sep;
|
|
13732
13285
|
let probe = full;
|
|
13733
|
-
while (!(0,
|
|
13286
|
+
while (!(0, import_node_fs8.existsSync)(probe)) {
|
|
13734
13287
|
const parent = (0, import_node_path9.dirname)(probe);
|
|
13735
13288
|
if (parent === probe) break;
|
|
13736
13289
|
probe = parent;
|
|
13737
13290
|
}
|
|
13738
|
-
const realProbe = (0,
|
|
13291
|
+
const realProbe = (0, import_node_fs8.realpathSync)(probe);
|
|
13739
13292
|
if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
|
|
13740
13293
|
}
|
|
13741
13294
|
} catch {
|
|
@@ -13814,24 +13367,24 @@ async function ensureMemoryDir() {
|
|
|
13814
13367
|
for (const domain of DOMAINS2) {
|
|
13815
13368
|
await (0, import_promises8.mkdir)((0, import_node_path10.join)(memoryDir2(), domain), { recursive: true });
|
|
13816
13369
|
}
|
|
13817
|
-
if (!(0,
|
|
13370
|
+
if (!(0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
13818
13371
|
await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
13819
13372
|
}
|
|
13820
|
-
if (!(0,
|
|
13373
|
+
if (!(0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "index.md"))) {
|
|
13821
13374
|
await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
13822
13375
|
}
|
|
13823
|
-
if (!(0,
|
|
13376
|
+
if (!(0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "log.md"))) {
|
|
13824
13377
|
await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
13825
13378
|
}
|
|
13826
13379
|
}
|
|
13827
13380
|
async function buildManifest() {
|
|
13828
|
-
if (!(0,
|
|
13381
|
+
if (!(0, import_node_fs9.existsSync)(memoryDir2())) {
|
|
13829
13382
|
return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
|
|
13830
13383
|
}
|
|
13831
13384
|
const nodes = [];
|
|
13832
13385
|
for (const domain of DOMAINS2) {
|
|
13833
13386
|
const domainDir = (0, import_node_path10.join)(memoryDir2(), domain);
|
|
13834
|
-
if (!(0,
|
|
13387
|
+
if (!(0, import_node_fs9.existsSync)(domainDir)) continue;
|
|
13835
13388
|
try {
|
|
13836
13389
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
13837
13390
|
for (const file of files) {
|
|
@@ -13867,10 +13420,10 @@ function hashContent(content) {
|
|
|
13867
13420
|
}
|
|
13868
13421
|
async function readOnDiskNodes() {
|
|
13869
13422
|
const out = /* @__PURE__ */ new Map();
|
|
13870
|
-
if (!(0,
|
|
13423
|
+
if (!(0, import_node_fs9.existsSync)(memoryDir2())) return out;
|
|
13871
13424
|
for (const domain of DOMAINS2) {
|
|
13872
13425
|
const domainDir = (0, import_node_path10.join)(memoryDir2(), domain);
|
|
13873
|
-
if (!(0,
|
|
13426
|
+
if (!(0, import_node_fs9.existsSync)(domainDir)) continue;
|
|
13874
13427
|
try {
|
|
13875
13428
|
for (const file of await (0, import_promises8.readdir)(domainDir)) {
|
|
13876
13429
|
if (!file.endsWith(".md")) continue;
|
|
@@ -13922,7 +13475,7 @@ async function computeEditedNodeUploads() {
|
|
|
13922
13475
|
for (const [path, prevHash] of prev) {
|
|
13923
13476
|
if (prevHash == null) continue;
|
|
13924
13477
|
const full = (0, import_node_path10.join)(memoryDir2(), path);
|
|
13925
|
-
if (!(0,
|
|
13478
|
+
if (!(0, import_node_fs9.existsSync)(full)) continue;
|
|
13926
13479
|
let content;
|
|
13927
13480
|
try {
|
|
13928
13481
|
content = await (0, import_promises8.readFile)(full, "utf-8");
|
|
@@ -13958,7 +13511,7 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
13958
13511
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
13959
13512
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
13960
13513
|
try {
|
|
13961
|
-
const existing = (0,
|
|
13514
|
+
const existing = (0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
13962
13515
|
await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
13963
13516
|
} catch {
|
|
13964
13517
|
}
|
|
@@ -13979,7 +13532,7 @@ async function applyOneWrite(write, treePaths) {
|
|
|
13979
13532
|
notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
|
|
13980
13533
|
}
|
|
13981
13534
|
}
|
|
13982
|
-
if ((0,
|
|
13535
|
+
if ((0, import_node_fs9.existsSync)(fullPath)) {
|
|
13983
13536
|
let existing = "";
|
|
13984
13537
|
try {
|
|
13985
13538
|
existing = await (0, import_promises8.readFile)(fullPath, "utf-8");
|
|
@@ -14033,7 +13586,7 @@ async function regenerateIndex() {
|
|
|
14033
13586
|
let totalNodes = 0;
|
|
14034
13587
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
14035
13588
|
const domainDir = (0, import_node_path10.join)(memoryDir2(), domain);
|
|
14036
|
-
if (!(0,
|
|
13589
|
+
if (!(0, import_node_fs9.existsSync)(domainDir)) continue;
|
|
14037
13590
|
try {
|
|
14038
13591
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
14039
13592
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
@@ -14303,7 +13856,7 @@ function hasLegacyMemoryBlock(text) {
|
|
|
14303
13856
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
14304
13857
|
const claudeMdPath = (0, import_node_path10.join)(cwd, "CLAUDE.md");
|
|
14305
13858
|
let existing = "";
|
|
14306
|
-
if ((0,
|
|
13859
|
+
if ((0, import_node_fs9.existsSync)(claudeMdPath)) {
|
|
14307
13860
|
existing = await (0, import_promises8.readFile)(claudeMdPath, "utf-8");
|
|
14308
13861
|
}
|
|
14309
13862
|
let startTag = CLAUDE_MD_START;
|
|
@@ -14439,10 +13992,237 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
14439
13992
|
`;
|
|
14440
13993
|
|
|
14441
13994
|
// src/lib/dossier-session.ts
|
|
14442
|
-
var
|
|
13995
|
+
var import_node_fs14 = require("node:fs");
|
|
14443
13996
|
var import_node_crypto7 = require("node:crypto");
|
|
14444
13997
|
var import_node_path13 = require("node:path");
|
|
14445
13998
|
|
|
13999
|
+
// src/lib/analysis-mode.ts
|
|
14000
|
+
var DEBUG_PHRASES = [
|
|
14001
|
+
"not working",
|
|
14002
|
+
"doesn't work",
|
|
14003
|
+
"doesn't work",
|
|
14004
|
+
"does not work",
|
|
14005
|
+
"isn't working",
|
|
14006
|
+
"is not working",
|
|
14007
|
+
"can't figure out",
|
|
14008
|
+
"stack trace"
|
|
14009
|
+
];
|
|
14010
|
+
var DEBUG_WORDS = [
|
|
14011
|
+
"fix",
|
|
14012
|
+
"bug",
|
|
14013
|
+
"broken",
|
|
14014
|
+
"crash",
|
|
14015
|
+
"crashing",
|
|
14016
|
+
"failing",
|
|
14017
|
+
"debug",
|
|
14018
|
+
"debugging",
|
|
14019
|
+
"investigate",
|
|
14020
|
+
"troubleshoot",
|
|
14021
|
+
"regression",
|
|
14022
|
+
"wrong"
|
|
14023
|
+
];
|
|
14024
|
+
var DEBUG_PATTERN = new RegExp(
|
|
14025
|
+
[
|
|
14026
|
+
...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
|
|
14027
|
+
...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
|
|
14028
|
+
].join("|"),
|
|
14029
|
+
"i"
|
|
14030
|
+
);
|
|
14031
|
+
var FALSE_POSITIVE_PATTERNS = [
|
|
14032
|
+
/\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
|
|
14033
|
+
/\berror\s+handling\b/i,
|
|
14034
|
+
/\berror\s+boundar(?:y|ies)\b/i,
|
|
14035
|
+
/\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
|
|
14036
|
+
/\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
|
|
14037
|
+
];
|
|
14038
|
+
function hasDebugIntent(prompt) {
|
|
14039
|
+
if (!DEBUG_PATTERN.test(prompt)) return false;
|
|
14040
|
+
for (const fp of FALSE_POSITIVE_PATTERNS) {
|
|
14041
|
+
if (fp.test(prompt)) return false;
|
|
14042
|
+
}
|
|
14043
|
+
return true;
|
|
14044
|
+
}
|
|
14045
|
+
var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
|
|
14046
|
+
var CODE_AUTHORING_PATTERN = /\b(add|create|implement|build|write|fix|update|change|refactor|modify|remove|delete|move|rename)\b.*\b(function|component|feature|endpoint|test|file|module|class|type|interface|hook|page|route|style|migration|code|bug|error|issue)\b/i;
|
|
14047
|
+
function isGitOnlyPrompt(prompt) {
|
|
14048
|
+
if (!GIT_ONLY_PATTERN.test(prompt)) return false;
|
|
14049
|
+
if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
|
|
14050
|
+
return true;
|
|
14051
|
+
}
|
|
14052
|
+
function reconcileAnalysisMode(predictedMode, signals) {
|
|
14053
|
+
const mode2 = resolveAnalysisMode(predictedMode, signals);
|
|
14054
|
+
if (mode2 !== "skip") return mode2;
|
|
14055
|
+
const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
|
|
14056
|
+
if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
|
|
14057
|
+
return mode2;
|
|
14058
|
+
}
|
|
14059
|
+
function resolveAnalysisMode(predictedMode, signals) {
|
|
14060
|
+
if (!predictedMode || !isValidMode(predictedMode)) {
|
|
14061
|
+
return detectAnalysisMode(
|
|
14062
|
+
signals.noFilesChanged,
|
|
14063
|
+
signals.assistantResponse,
|
|
14064
|
+
signals.conversationPrompts,
|
|
14065
|
+
signals.actionSummary,
|
|
14066
|
+
signals.sessionAuthoredCode
|
|
14067
|
+
);
|
|
14068
|
+
}
|
|
14069
|
+
const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
|
|
14070
|
+
const agentInvestigated = didAgentInvestigate(signals.actionSummary);
|
|
14071
|
+
switch (predictedMode) {
|
|
14072
|
+
case "skip":
|
|
14073
|
+
if (agentAuthoredCode) return "standard";
|
|
14074
|
+
return "skip";
|
|
14075
|
+
case "plan":
|
|
14076
|
+
if (agentAuthoredCode) return "standard";
|
|
14077
|
+
return "plan";
|
|
14078
|
+
case "debug":
|
|
14079
|
+
return "debug";
|
|
14080
|
+
case "standard":
|
|
14081
|
+
if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
|
|
14082
|
+
return agentInvestigated ? "plan" : "skip";
|
|
14083
|
+
}
|
|
14084
|
+
return "standard";
|
|
14085
|
+
}
|
|
14086
|
+
}
|
|
14087
|
+
function didAgentInvestigate(summary) {
|
|
14088
|
+
if (!summary) return false;
|
|
14089
|
+
return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
|
|
14090
|
+
}
|
|
14091
|
+
function isValidMode(mode2) {
|
|
14092
|
+
return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
|
|
14093
|
+
}
|
|
14094
|
+
function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
|
|
14095
|
+
const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
|
|
14096
|
+
if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
|
|
14097
|
+
if (!agentAuthoredCode) return "skip";
|
|
14098
|
+
}
|
|
14099
|
+
if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
|
|
14100
|
+
return "plan";
|
|
14101
|
+
}
|
|
14102
|
+
if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
|
|
14103
|
+
return didAgentInvestigate(actionSummary) ? "plan" : "skip";
|
|
14104
|
+
}
|
|
14105
|
+
for (const prompt of conversationPrompts) {
|
|
14106
|
+
if (hasDebugIntent(prompt)) {
|
|
14107
|
+
return "debug";
|
|
14108
|
+
}
|
|
14109
|
+
}
|
|
14110
|
+
return "standard";
|
|
14111
|
+
}
|
|
14112
|
+
var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
|
|
14113
|
+
var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
|
|
14114
|
+
var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
|
|
14115
|
+
var CHAIN_RE = /&&|\||;|\$\(|\x60/;
|
|
14116
|
+
function isNonAuthoringCommand(cmd) {
|
|
14117
|
+
if (typeof cmd !== "string" || cmd.trim().length === 0) return false;
|
|
14118
|
+
if (FILE_MUTATE_RE.test(cmd)) return false;
|
|
14119
|
+
if (CHAIN_RE.test(cmd)) return false;
|
|
14120
|
+
return GIT_PLUMBING_RE.test(cmd) || READ_ONLY_RE.test(cmd);
|
|
14121
|
+
}
|
|
14122
|
+
function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
|
|
14123
|
+
if (!actionSummary) return sessionAuthoredCode;
|
|
14124
|
+
if ((actionSummary.subagents ?? 0) > 0) return true;
|
|
14125
|
+
if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
|
|
14126
|
+
const commands = actionSummary.commands ?? [];
|
|
14127
|
+
if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
|
|
14128
|
+
if (sessionAuthoredCode) {
|
|
14129
|
+
const allSafe = commands.length > 0 && commands.every(isNonAuthoringCommand);
|
|
14130
|
+
if (!allSafe) return true;
|
|
14131
|
+
}
|
|
14132
|
+
return false;
|
|
14133
|
+
}
|
|
14134
|
+
function scopeToAuthored(files, actionSummary) {
|
|
14135
|
+
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
14136
|
+
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
14137
|
+
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
14138
|
+
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
14139
|
+
}
|
|
14140
|
+
function narrowToAgentAuthored(files, actionSummary) {
|
|
14141
|
+
if (!actionSummary) return files;
|
|
14142
|
+
const touched = [
|
|
14143
|
+
...actionSummary.files_edited,
|
|
14144
|
+
...actionSummary.files_created
|
|
14145
|
+
];
|
|
14146
|
+
if (touched.length === 0) return files;
|
|
14147
|
+
return files.filter((f) => {
|
|
14148
|
+
const suffix = "/" + f;
|
|
14149
|
+
return touched.some((t) => t === f || t.endsWith(suffix));
|
|
14150
|
+
});
|
|
14151
|
+
}
|
|
14152
|
+
|
|
14153
|
+
// src/lib/skip-detection.ts
|
|
14154
|
+
function isBareAckPrompt(prompt) {
|
|
14155
|
+
if (typeof prompt !== "string") return false;
|
|
14156
|
+
const trimmed = prompt.trim();
|
|
14157
|
+
if (trimmed.length === 0) return false;
|
|
14158
|
+
if (trimmed.length > 20) return false;
|
|
14159
|
+
const bareAckPattern = /^(\d{1,2}|y|n|yes|no|yep|nope|ok(ay)?|sure|skip|cancel|stop|done|noted|got\s+it|sounds\s+good|thanks|thank\s+you|thx)[.!?]*$/i;
|
|
14160
|
+
return bareAckPattern.test(trimmed);
|
|
14161
|
+
}
|
|
14162
|
+
function isContinuationPrompt(prompt) {
|
|
14163
|
+
if (typeof prompt !== "string") return false;
|
|
14164
|
+
const trimmed = prompt.trim();
|
|
14165
|
+
if (trimmed.length === 0) return false;
|
|
14166
|
+
if (trimmed.length > 24) return false;
|
|
14167
|
+
const continuation = /^(let['’]?s\s+(go|do\s+it|start|continue)|go|go\s+ahead|go\s+on|proceed|continue|carry\s+on|keep\s+going|do\s+it|make\s+it\s+so|next|start|begin|ship\s+it|yes\s+please|please\s+continue|perfect|great|nice|excellent|agreed)[.!]*$/i;
|
|
14168
|
+
return continuation.test(trimmed) || isBareAckPrompt(trimmed);
|
|
14169
|
+
}
|
|
14170
|
+
function resolveGoalPrompt(prompts) {
|
|
14171
|
+
if (prompts.length === 0) return null;
|
|
14172
|
+
const latest = prompts[prompts.length - 1];
|
|
14173
|
+
if (!isContinuationPrompt(latest.prompt)) return { entry: latest, turnsBack: 0 };
|
|
14174
|
+
for (let i = prompts.length - 2; i >= 0; i--) {
|
|
14175
|
+
if (!isContinuationPrompt(prompts[i].prompt)) {
|
|
14176
|
+
return { entry: prompts[i], turnsBack: prompts.length - 1 - i };
|
|
14177
|
+
}
|
|
14178
|
+
}
|
|
14179
|
+
return { entry: latest, turnsBack: 0 };
|
|
14180
|
+
}
|
|
14181
|
+
function isReflectionQuestion(response) {
|
|
14182
|
+
if (!response || typeof response !== "string") return false;
|
|
14183
|
+
const markers = [
|
|
14184
|
+
/reflection\s+for\s+future\s+agents/i,
|
|
14185
|
+
/what(?:'s|\s+is)\s+one\s+thing\s+you\s+learned/i,
|
|
14186
|
+
/say\s+['"]?skip['"]?\s+to\s+skip/i,
|
|
14187
|
+
/quick\s+reflection\s+question/i,
|
|
14188
|
+
// Post-flip (VRT-21): the agent drafts the reflection itself and, when
|
|
14189
|
+
// interactive, asks the user to confirm/correct before recording. That
|
|
14190
|
+
// turn authors no code either, so it's still a reflection turn.
|
|
14191
|
+
/reflection\s+draft/i,
|
|
14192
|
+
/confirm,?\s+correct,?\s+or\s+add/i
|
|
14193
|
+
];
|
|
14194
|
+
return markers.some((m) => m.test(response));
|
|
14195
|
+
}
|
|
14196
|
+
function isMetaTaskLabel(label2) {
|
|
14197
|
+
if (label2 === null || label2 === void 0) return false;
|
|
14198
|
+
if (typeof label2 !== "string") return false;
|
|
14199
|
+
const trimmed = label2.trim();
|
|
14200
|
+
if (trimmed.length === 0) return true;
|
|
14201
|
+
const metaPatterns = [
|
|
14202
|
+
/^verity\s+[\w-]+\s+response$/i,
|
|
14203
|
+
// "Verity reflect response"
|
|
14204
|
+
/^simple user response$/i,
|
|
14205
|
+
/^verity\s+command$/i,
|
|
14206
|
+
// "Verity command"
|
|
14207
|
+
/^user\s+(question|reply|response|ack)$/i
|
|
14208
|
+
];
|
|
14209
|
+
return metaPatterns.some((p) => p.test(trimmed));
|
|
14210
|
+
}
|
|
14211
|
+
function shouldSkipForBareAck(input) {
|
|
14212
|
+
if (!isBareAckPrompt(input.prompt)) return false;
|
|
14213
|
+
if (input.turnAuthoredCode) return false;
|
|
14214
|
+
return input.canSeeTurnAuthorship;
|
|
14215
|
+
}
|
|
14216
|
+
function isCommandOnlyTurn(input) {
|
|
14217
|
+
if (!input.authorshipIsObservable) return false;
|
|
14218
|
+
if (input.userCommandsTruncated) return false;
|
|
14219
|
+
const commands = input.userCommands ?? [];
|
|
14220
|
+
if (commands.length === 0) return false;
|
|
14221
|
+
if (input.agentAuthoredFiles > 0) return false;
|
|
14222
|
+
if (input.agentToolCalls > 0) return false;
|
|
14223
|
+
return commands.every(isNonAuthoringCommand);
|
|
14224
|
+
}
|
|
14225
|
+
|
|
14446
14226
|
// src/lib/pending-repeat.ts
|
|
14447
14227
|
var STOP = /* @__PURE__ */ new Set([
|
|
14448
14228
|
"the",
|
|
@@ -14546,7 +14326,7 @@ function statementAnchorKey(file, patternId) {
|
|
|
14546
14326
|
|
|
14547
14327
|
// src/lib/dossier/log.ts
|
|
14548
14328
|
var import_node_crypto4 = require("node:crypto");
|
|
14549
|
-
var
|
|
14329
|
+
var import_node_fs10 = require("node:fs");
|
|
14550
14330
|
var import_node_path11 = require("node:path");
|
|
14551
14331
|
var CRC_TABLE = (() => {
|
|
14552
14332
|
const t = new Int32Array(256);
|
|
@@ -14566,7 +14346,7 @@ function crc32(s) {
|
|
|
14566
14346
|
function openDossier(identity) {
|
|
14567
14347
|
try {
|
|
14568
14348
|
const dir = dossierDir(identity);
|
|
14569
|
-
(0,
|
|
14349
|
+
(0, import_node_fs10.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
14570
14350
|
return {
|
|
14571
14351
|
dir,
|
|
14572
14352
|
identity,
|
|
@@ -14634,7 +14414,7 @@ function appendEvent(d, ev) {
|
|
|
14634
14414
|
at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
14635
14415
|
...ev
|
|
14636
14416
|
});
|
|
14637
|
-
(0,
|
|
14417
|
+
(0, import_node_fs10.appendFileSync)(d.eventsPath, line, { mode: 384 });
|
|
14638
14418
|
return true;
|
|
14639
14419
|
} catch {
|
|
14640
14420
|
return false;
|
|
@@ -14642,14 +14422,14 @@ function appendEvent(d, ev) {
|
|
|
14642
14422
|
}
|
|
14643
14423
|
function rotateIfNeeded2(d) {
|
|
14644
14424
|
try {
|
|
14645
|
-
if (!(0,
|
|
14646
|
-
if ((0,
|
|
14647
|
-
(0,
|
|
14648
|
-
(0,
|
|
14649
|
-
const kept = (0,
|
|
14425
|
+
if (!(0, import_node_fs10.existsSync)(d.eventsPath)) return;
|
|
14426
|
+
if ((0, import_node_fs10.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
|
|
14427
|
+
(0, import_node_fs10.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
|
|
14428
|
+
(0, import_node_fs10.renameSync)(d.eventsPath, (0, import_node_path11.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
|
|
14429
|
+
const kept = (0, import_node_fs10.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
14650
14430
|
for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
|
|
14651
14431
|
try {
|
|
14652
|
-
(0,
|
|
14432
|
+
(0, import_node_fs10.renameSync)((0, import_node_path11.join)(d.rotatedDir, stale), (0, import_node_path11.join)(d.rotatedDir, `${stale}.pruned`));
|
|
14653
14433
|
} catch {
|
|
14654
14434
|
}
|
|
14655
14435
|
}
|
|
@@ -14659,7 +14439,7 @@ function rotateIfNeeded2(d) {
|
|
|
14659
14439
|
|
|
14660
14440
|
// src/lib/dossier/fold-dossier.ts
|
|
14661
14441
|
var import_node_crypto5 = require("node:crypto");
|
|
14662
|
-
var
|
|
14442
|
+
var import_node_fs11 = require("node:fs");
|
|
14663
14443
|
var import_node_path12 = require("node:path");
|
|
14664
14444
|
var EMPTY_CAPABILITIES = () => ({
|
|
14665
14445
|
human_reachable: { value: "unknown", tier: "unknown" },
|
|
@@ -14711,12 +14491,12 @@ function foldDossier(d, opts = {}) {
|
|
|
14711
14491
|
}
|
|
14712
14492
|
};
|
|
14713
14493
|
try {
|
|
14714
|
-
if ((0,
|
|
14715
|
-
const files = (0,
|
|
14494
|
+
if ((0, import_node_fs11.existsSync)(d.rotatedDir)) {
|
|
14495
|
+
const files = (0, import_node_fs11.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
14716
14496
|
state.meta.rotations = files.length;
|
|
14717
14497
|
for (const f of files) {
|
|
14718
14498
|
try {
|
|
14719
|
-
ingest((0,
|
|
14499
|
+
ingest((0, import_node_fs11.readFileSync)((0, import_node_path12.join)(d.rotatedDir, f), "utf8"));
|
|
14720
14500
|
} catch {
|
|
14721
14501
|
state.meta.dropped_lines++;
|
|
14722
14502
|
}
|
|
@@ -14725,9 +14505,9 @@ function foldDossier(d, opts = {}) {
|
|
|
14725
14505
|
} catch {
|
|
14726
14506
|
}
|
|
14727
14507
|
try {
|
|
14728
|
-
if ((0,
|
|
14729
|
-
state.meta.upto_offset = (0,
|
|
14730
|
-
ingest((0,
|
|
14508
|
+
if ((0, import_node_fs11.existsSync)(d.eventsPath)) {
|
|
14509
|
+
state.meta.upto_offset = (0, import_node_fs11.statSync)(d.eventsPath).size;
|
|
14510
|
+
ingest((0, import_node_fs11.readFileSync)(d.eventsPath, "utf8"));
|
|
14731
14511
|
}
|
|
14732
14512
|
} catch {
|
|
14733
14513
|
}
|
|
@@ -14998,7 +14778,7 @@ function applyBounds(state, input) {
|
|
|
14998
14778
|
}
|
|
14999
14779
|
|
|
15000
14780
|
// src/lib/dossier/cache.ts
|
|
15001
|
-
var
|
|
14781
|
+
var import_node_fs12 = require("node:fs");
|
|
15002
14782
|
function compactState(s) {
|
|
15003
14783
|
const ms = (iso) => Date.parse(iso) || 0;
|
|
15004
14784
|
return {
|
|
@@ -15127,20 +14907,20 @@ function encodeState(s) {
|
|
|
15127
14907
|
function writeFoldCache(d, state) {
|
|
15128
14908
|
try {
|
|
15129
14909
|
const tmp = `${d.foldPath}.${process.pid}.tmp`;
|
|
15130
|
-
(0,
|
|
15131
|
-
(0,
|
|
14910
|
+
(0, import_node_fs12.writeFileSync)(tmp, encodeState(state), { mode: 384 });
|
|
14911
|
+
(0, import_node_fs12.renameSync)(tmp, d.foldPath);
|
|
15132
14912
|
} catch {
|
|
15133
14913
|
}
|
|
15134
14914
|
}
|
|
15135
14915
|
function readFoldCache(d) {
|
|
15136
14916
|
try {
|
|
15137
|
-
if (!(0,
|
|
15138
|
-
const raw = JSON.parse((0,
|
|
14917
|
+
if (!(0, import_node_fs12.existsSync)(d.foldPath)) return null;
|
|
14918
|
+
const raw = JSON.parse((0, import_node_fs12.readFileSync)(d.foldPath, "utf8"));
|
|
15139
14919
|
if (raw?.v !== 1) return null;
|
|
15140
14920
|
const cached2 = expandState(raw);
|
|
15141
14921
|
if (!cached2?.meta) return null;
|
|
15142
|
-
const size = (0,
|
|
15143
|
-
const rotations = (0,
|
|
14922
|
+
const size = (0, import_node_fs12.existsSync)(d.eventsPath) ? (0, import_node_fs12.statSync)(d.eventsPath).size : 0;
|
|
14923
|
+
const rotations = (0, import_node_fs12.existsSync)(d.rotatedDir) ? (0, import_node_fs12.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
|
|
15144
14924
|
if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
|
|
15145
14925
|
return cached2;
|
|
15146
14926
|
} catch {
|
|
@@ -15191,13 +14971,13 @@ function assessContinuity(i) {
|
|
|
15191
14971
|
|
|
15192
14972
|
// src/lib/dossier/reanchor.ts
|
|
15193
14973
|
var import_node_crypto6 = require("node:crypto");
|
|
15194
|
-
var
|
|
14974
|
+
var import_node_fs13 = require("node:fs");
|
|
15195
14975
|
function lineSha(text) {
|
|
15196
14976
|
return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
15197
14977
|
}
|
|
15198
14978
|
function fileHash(path) {
|
|
15199
14979
|
try {
|
|
15200
|
-
return (0, import_node_crypto6.createHash)("sha256").update((0,
|
|
14980
|
+
return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs13.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
15201
14981
|
} catch {
|
|
15202
14982
|
return null;
|
|
15203
14983
|
}
|
|
@@ -15569,14 +15349,14 @@ function foreignAuthoredPaths(identity, opts = {}) {
|
|
|
15569
15349
|
let sessions = 0;
|
|
15570
15350
|
try {
|
|
15571
15351
|
const dir = treeDir(identity);
|
|
15572
|
-
if (!(0,
|
|
15573
|
-
for (const entry of (0,
|
|
15352
|
+
if (!(0, import_node_fs14.existsSync)(dir)) return { paths: [], sessions: 0 };
|
|
15353
|
+
for (const entry of (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true })) {
|
|
15574
15354
|
if (!entry.isDirectory()) continue;
|
|
15575
15355
|
if (entry.name === identity.sessionKey) continue;
|
|
15576
15356
|
const log = (0, import_node_path13.join)(dir, entry.name, "events.jsonl");
|
|
15577
15357
|
try {
|
|
15578
|
-
if (!(0,
|
|
15579
|
-
if (now - (0,
|
|
15358
|
+
if (!(0, import_node_fs14.existsSync)(log)) continue;
|
|
15359
|
+
if (now - (0, import_node_fs14.statSync)(log).mtimeMs > windowMs) continue;
|
|
15580
15360
|
const sib = {
|
|
15581
15361
|
dir: (0, import_node_path13.join)(dir, entry.name),
|
|
15582
15362
|
identity,
|
|
@@ -15611,13 +15391,13 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
15611
15391
|
try {
|
|
15612
15392
|
const mine = dossierDir(identity);
|
|
15613
15393
|
const userDir = (0, import_node_path13.dirname)((0, import_node_path13.dirname)(mine));
|
|
15614
|
-
if (!(0,
|
|
15394
|
+
if (!(0, import_node_fs14.existsSync)(userDir)) return 0;
|
|
15615
15395
|
const cutoff = Date.now() - maxAgeMs;
|
|
15616
|
-
for (const tree of (0,
|
|
15396
|
+
for (const tree of (0, import_node_fs14.readdirSync)(userDir, { withFileTypes: true })) {
|
|
15617
15397
|
if (!tree.isDirectory()) continue;
|
|
15618
15398
|
const treePath = (0, import_node_path13.join)(userDir, tree.name);
|
|
15619
15399
|
let live = 0;
|
|
15620
|
-
for (const entry of (0,
|
|
15400
|
+
for (const entry of (0, import_node_fs14.readdirSync)(treePath, { withFileTypes: true })) {
|
|
15621
15401
|
if (!entry.isDirectory()) continue;
|
|
15622
15402
|
const dir = (0, import_node_path13.join)(treePath, entry.name);
|
|
15623
15403
|
if (dir === mine) {
|
|
@@ -15626,9 +15406,9 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
15626
15406
|
}
|
|
15627
15407
|
try {
|
|
15628
15408
|
const log = (0, import_node_path13.join)(dir, "events.jsonl");
|
|
15629
|
-
const at = (0,
|
|
15409
|
+
const at = (0, import_node_fs14.existsSync)(log) ? (0, import_node_fs14.statSync)(log).mtimeMs : (0, import_node_fs14.statSync)(dir).mtimeMs;
|
|
15630
15410
|
if (at < cutoff) {
|
|
15631
|
-
(0,
|
|
15411
|
+
(0, import_node_fs14.rmSync)(dir, { recursive: true, force: true });
|
|
15632
15412
|
removed++;
|
|
15633
15413
|
} else {
|
|
15634
15414
|
live++;
|
|
@@ -15638,7 +15418,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
15638
15418
|
}
|
|
15639
15419
|
if (live === 0) {
|
|
15640
15420
|
try {
|
|
15641
|
-
(0,
|
|
15421
|
+
(0, import_node_fs14.rmSync)(treePath, { recursive: false, force: false });
|
|
15642
15422
|
} catch {
|
|
15643
15423
|
}
|
|
15644
15424
|
}
|
|
@@ -15655,8 +15435,8 @@ function sessionDossier(token, sessionId) {
|
|
|
15655
15435
|
}
|
|
15656
15436
|
function hasActiveGoal(d) {
|
|
15657
15437
|
try {
|
|
15658
|
-
if (!(0,
|
|
15659
|
-
return (0,
|
|
15438
|
+
if (!(0, import_node_fs14.existsSync)(d.eventsPath)) return false;
|
|
15439
|
+
return (0, import_node_fs14.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
|
|
15660
15440
|
} catch {
|
|
15661
15441
|
return false;
|
|
15662
15442
|
}
|
|
@@ -15749,7 +15529,7 @@ function recordVerdict(d, v) {
|
|
|
15749
15529
|
if (!lines.has(f.file)) {
|
|
15750
15530
|
try {
|
|
15751
15531
|
const abs = (0, import_node_path13.join)(root, f.file);
|
|
15752
|
-
lines.set(f.file, (0,
|
|
15532
|
+
lines.set(f.file, (0, import_node_fs14.existsSync)(abs) ? (0, import_node_fs14.readFileSync)(abs, "utf8").split("\n") : null);
|
|
15753
15533
|
} catch {
|
|
15754
15534
|
lines.set(f.file, null);
|
|
15755
15535
|
}
|
|
@@ -15850,7 +15630,7 @@ function recallMemory(d, identity, opts) {
|
|
|
15850
15630
|
readFileLines: (file) => {
|
|
15851
15631
|
try {
|
|
15852
15632
|
const abs = (0, import_node_path13.join)(root, file);
|
|
15853
|
-
return (0,
|
|
15633
|
+
return (0, import_node_fs14.existsSync)(abs) ? (0, import_node_fs14.readFileSync)(abs, "utf8").split("\n") : null;
|
|
15854
15634
|
} catch {
|
|
15855
15635
|
return null;
|
|
15856
15636
|
}
|
|
@@ -15899,21 +15679,15 @@ function registerIntentCommands(program2) {
|
|
|
15899
15679
|
if (!prompt) {
|
|
15900
15680
|
process.exit(0);
|
|
15901
15681
|
}
|
|
15902
|
-
if (deferredToPlugin("intent capture", event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null)) {
|
|
15903
|
-
process.exit(0);
|
|
15904
|
-
}
|
|
15905
|
-
const isPrimitive = isSlashCommand(prompt);
|
|
15906
15682
|
const authForScope = await resolveToken(program2.opts().token);
|
|
15907
15683
|
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
15908
15684
|
const scopeSession = event.session_id || process.env.CLAUDE_SESSION_ID || "";
|
|
15909
|
-
|
|
15910
|
-
|
|
15911
|
-
|
|
15912
|
-
|
|
15913
|
-
|
|
15914
|
-
|
|
15915
|
-
} catch {
|
|
15916
|
-
}
|
|
15685
|
+
await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
|
|
15686
|
+
try {
|
|
15687
|
+
const tok = await resolveToken(globals.token);
|
|
15688
|
+
const session = sessionDossier(tok.ok ? tok.data.token : null, event.session_id ?? null);
|
|
15689
|
+
if (session) recordGoal(session.d, prompt);
|
|
15690
|
+
} catch {
|
|
15917
15691
|
}
|
|
15918
15692
|
try {
|
|
15919
15693
|
await ensureMemoryDir();
|
|
@@ -15994,21 +15768,21 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
15994
15768
|
}
|
|
15995
15769
|
|
|
15996
15770
|
// src/commands/lifecycle.ts
|
|
15997
|
-
var
|
|
15771
|
+
var import_node_fs18 = require("node:fs");
|
|
15998
15772
|
var import_node_path17 = require("node:path");
|
|
15999
15773
|
|
|
16000
15774
|
// src/lib/baseline.ts
|
|
16001
|
-
var
|
|
15775
|
+
var import_node_fs17 = require("node:fs");
|
|
16002
15776
|
var import_node_path16 = require("node:path");
|
|
16003
15777
|
var import_node_crypto9 = require("node:crypto");
|
|
16004
15778
|
|
|
16005
15779
|
// src/lib/snapshot.ts
|
|
16006
|
-
var
|
|
15780
|
+
var import_node_fs16 = require("node:fs");
|
|
16007
15781
|
var import_node_path15 = require("node:path");
|
|
16008
15782
|
var import_node_child_process6 = require("node:child_process");
|
|
16009
15783
|
|
|
16010
15784
|
// src/lib/files.ts
|
|
16011
|
-
var
|
|
15785
|
+
var import_node_fs15 = require("node:fs");
|
|
16012
15786
|
var import_node_path14 = require("node:path");
|
|
16013
15787
|
var LANG_MAP = {
|
|
16014
15788
|
// Analyzable (static analysis + Gemini)
|
|
@@ -16085,7 +15859,7 @@ function sortByMtime(files) {
|
|
|
16085
15859
|
const resolved = resolveFile(f);
|
|
16086
15860
|
if (!resolved) return null;
|
|
16087
15861
|
try {
|
|
16088
|
-
const stat3 = (0,
|
|
15862
|
+
const stat3 = (0, import_node_fs15.statSync)(resolved);
|
|
16089
15863
|
return { path: f, resolved, mtime: stat3.mtimeMs };
|
|
16090
15864
|
} catch {
|
|
16091
15865
|
return null;
|
|
@@ -16118,7 +15892,7 @@ function collectCodeDelta(files, opts) {
|
|
|
16118
15892
|
}
|
|
16119
15893
|
let size;
|
|
16120
15894
|
try {
|
|
16121
|
-
size = (0,
|
|
15895
|
+
size = (0, import_node_fs15.statSync)(resolved).size;
|
|
16122
15896
|
} catch {
|
|
16123
15897
|
exclude(filepath, "not-stattable");
|
|
16124
15898
|
continue;
|
|
@@ -16135,7 +15909,7 @@ function collectCodeDelta(files, opts) {
|
|
|
16135
15909
|
}
|
|
16136
15910
|
let content;
|
|
16137
15911
|
try {
|
|
16138
|
-
content = (0,
|
|
15912
|
+
content = (0, import_node_fs15.readFileSync)(resolved, "utf-8");
|
|
16139
15913
|
} catch {
|
|
16140
15914
|
exclude(filepath, "not-readable");
|
|
16141
15915
|
continue;
|
|
@@ -16174,7 +15948,7 @@ function collectCodeDelta(files, opts) {
|
|
|
16174
15948
|
|
|
16175
15949
|
// src/lib/snapshot.ts
|
|
16176
15950
|
function generateSnapshotDiffs(files) {
|
|
16177
|
-
if (!(0,
|
|
15951
|
+
if (!(0, import_node_fs16.existsSync)(SNAPSHOT_DIR)) {
|
|
16178
15952
|
return { diffs: [], has_snapshots: false };
|
|
16179
15953
|
}
|
|
16180
15954
|
const diffs = [];
|
|
@@ -16182,8 +15956,8 @@ function generateSnapshotDiffs(files) {
|
|
|
16182
15956
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
16183
15957
|
const snapshotPath = (0, import_node_path15.join)(SNAPSHOT_DIR, file.path);
|
|
16184
15958
|
const language = file.language ?? detectLanguage(file.path);
|
|
16185
|
-
if ((0,
|
|
16186
|
-
const oldContent = (0,
|
|
15959
|
+
if ((0, import_node_fs16.existsSync)(snapshotPath)) {
|
|
15960
|
+
const oldContent = (0, import_node_fs16.readFileSync)(snapshotPath, "utf-8");
|
|
16187
15961
|
if (oldContent === file.content) continue;
|
|
16188
15962
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
16189
15963
|
if (diff) {
|
|
@@ -16210,8 +15984,8 @@ function saveSnapshots(files) {
|
|
|
16210
15984
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
16211
15985
|
const snapshotPath = (0, import_node_path15.join)(SNAPSHOT_DIR, file.path);
|
|
16212
15986
|
snapshotPaths.add(snapshotPath);
|
|
16213
|
-
(0,
|
|
16214
|
-
(0,
|
|
15987
|
+
(0, import_node_fs16.mkdirSync)((0, import_node_path15.dirname)(snapshotPath), { recursive: true });
|
|
15988
|
+
(0, import_node_fs16.writeFileSync)(snapshotPath, file.content);
|
|
16215
15989
|
}
|
|
16216
15990
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
16217
15991
|
}
|
|
@@ -16219,9 +15993,9 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
16219
15993
|
const tmpOld = (0, import_node_path15.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
16220
15994
|
const tmpNew = (0, import_node_path15.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
16221
15995
|
try {
|
|
16222
|
-
(0,
|
|
16223
|
-
(0,
|
|
16224
|
-
(0,
|
|
15996
|
+
(0, import_node_fs16.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
15997
|
+
(0, import_node_fs16.writeFileSync)(tmpOld, oldContent);
|
|
15998
|
+
(0, import_node_fs16.writeFileSync)(tmpNew, newContent);
|
|
16225
15999
|
const result = (0, import_node_child_process6.execSync)(
|
|
16226
16000
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
16227
16001
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -16235,32 +16009,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
16235
16009
|
return null;
|
|
16236
16010
|
} finally {
|
|
16237
16011
|
try {
|
|
16238
|
-
(0,
|
|
16012
|
+
(0, import_node_fs16.unlinkSync)(tmpOld);
|
|
16239
16013
|
} catch {
|
|
16240
16014
|
}
|
|
16241
16015
|
try {
|
|
16242
|
-
(0,
|
|
16016
|
+
(0, import_node_fs16.unlinkSync)(tmpNew);
|
|
16243
16017
|
} catch {
|
|
16244
16018
|
}
|
|
16245
16019
|
}
|
|
16246
16020
|
}
|
|
16247
16021
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
16248
|
-
if (!(0,
|
|
16022
|
+
if (!(0, import_node_fs16.existsSync)(dir)) return;
|
|
16249
16023
|
try {
|
|
16250
|
-
const entries = (0,
|
|
16024
|
+
const entries = (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true });
|
|
16251
16025
|
for (const entry of entries) {
|
|
16252
16026
|
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
16253
16027
|
const fullPath = (0, import_node_path15.join)(dir, entry.name);
|
|
16254
16028
|
if (entry.isDirectory()) {
|
|
16255
16029
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
16256
16030
|
try {
|
|
16257
|
-
const remaining = (0,
|
|
16258
|
-
if (remaining.length === 0) (0,
|
|
16031
|
+
const remaining = (0, import_node_fs16.readdirSync)(fullPath);
|
|
16032
|
+
if (remaining.length === 0) (0, import_node_fs16.rmdirSync)(fullPath);
|
|
16259
16033
|
} catch {
|
|
16260
16034
|
}
|
|
16261
16035
|
} else if (!keepSet.has(fullPath)) {
|
|
16262
16036
|
try {
|
|
16263
|
-
(0,
|
|
16037
|
+
(0, import_node_fs16.unlinkSync)(fullPath);
|
|
16264
16038
|
} catch {
|
|
16265
16039
|
}
|
|
16266
16040
|
}
|
|
@@ -16291,8 +16065,8 @@ var CARRY_FILE = `${BASELINE_DIR}/.carry`;
|
|
|
16291
16065
|
var CARRY_WINDOW_MS = 12e4;
|
|
16292
16066
|
function writeCarry(sessionId, headSha) {
|
|
16293
16067
|
try {
|
|
16294
|
-
(0,
|
|
16295
|
-
(0,
|
|
16068
|
+
(0, import_node_fs17.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
|
|
16069
|
+
(0, import_node_fs17.writeFileSync)(
|
|
16296
16070
|
projectPath(CARRY_FILE),
|
|
16297
16071
|
JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
|
|
16298
16072
|
);
|
|
@@ -16302,10 +16076,10 @@ function writeCarry(sessionId, headSha) {
|
|
|
16302
16076
|
function claimCarry(newKey) {
|
|
16303
16077
|
const carryPath = projectPath(CARRY_FILE);
|
|
16304
16078
|
try {
|
|
16305
|
-
if (!(0,
|
|
16306
|
-
const carry = JSON.parse((0,
|
|
16079
|
+
if (!(0, import_node_fs17.existsSync)(carryPath)) return null;
|
|
16080
|
+
const carry = JSON.parse((0, import_node_fs17.readFileSync)(carryPath, "utf-8"));
|
|
16307
16081
|
try {
|
|
16308
|
-
(0,
|
|
16082
|
+
(0, import_node_fs17.rmSync)(carryPath, { force: true });
|
|
16309
16083
|
} catch {
|
|
16310
16084
|
}
|
|
16311
16085
|
if (!carry?.from_key || typeof carry.ts !== "number") return null;
|
|
@@ -16316,11 +16090,11 @@ function claimCarry(newKey) {
|
|
|
16316
16090
|
if (!prior) return null;
|
|
16317
16091
|
const toDir = sessionDir(newKey);
|
|
16318
16092
|
try {
|
|
16319
|
-
(0,
|
|
16093
|
+
(0, import_node_fs17.rmSync)(toDir, { recursive: true, force: true });
|
|
16320
16094
|
} catch {
|
|
16321
16095
|
}
|
|
16322
|
-
(0,
|
|
16323
|
-
(0,
|
|
16096
|
+
(0, import_node_fs17.renameSync)(fromDir, toDir);
|
|
16097
|
+
(0, import_node_fs17.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
|
|
16324
16098
|
return readManifest(toDir);
|
|
16325
16099
|
} catch {
|
|
16326
16100
|
return null;
|
|
@@ -16344,21 +16118,21 @@ function captureBaseline(opts = {}) {
|
|
|
16344
16118
|
const head_sha = getCurrentCommit();
|
|
16345
16119
|
const dirty = getDirtyFiles();
|
|
16346
16120
|
try {
|
|
16347
|
-
(0,
|
|
16121
|
+
(0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
|
|
16348
16122
|
} catch {
|
|
16349
16123
|
}
|
|
16350
16124
|
const filesDir = (0, import_node_path16.join)(dir, "files");
|
|
16351
16125
|
const mirrored = [];
|
|
16352
16126
|
try {
|
|
16353
|
-
(0,
|
|
16127
|
+
(0, import_node_fs17.mkdirSync)(filesDir, { recursive: true });
|
|
16354
16128
|
for (const p of dirty) {
|
|
16355
16129
|
if (p.includes("..")) continue;
|
|
16356
16130
|
const content = safeReadForMirror(projectPath(p));
|
|
16357
16131
|
if (content === null) continue;
|
|
16358
16132
|
const dest = mirrorPath(dir, p);
|
|
16359
16133
|
try {
|
|
16360
|
-
(0,
|
|
16361
|
-
(0,
|
|
16134
|
+
(0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(dest), { recursive: true });
|
|
16135
|
+
(0, import_node_fs17.writeFileSync)(dest, content);
|
|
16362
16136
|
mirrored.push(p);
|
|
16363
16137
|
} catch {
|
|
16364
16138
|
}
|
|
@@ -16373,8 +16147,8 @@ function captureBaseline(opts = {}) {
|
|
|
16373
16147
|
version: BASELINE_VERSION
|
|
16374
16148
|
};
|
|
16375
16149
|
try {
|
|
16376
|
-
(0,
|
|
16377
|
-
(0,
|
|
16150
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
16151
|
+
(0, import_node_fs17.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
|
|
16378
16152
|
} catch {
|
|
16379
16153
|
}
|
|
16380
16154
|
pruneOldBaselines();
|
|
@@ -16385,9 +16159,9 @@ function readBaseline(sessionId) {
|
|
|
16385
16159
|
}
|
|
16386
16160
|
function readManifest(dir) {
|
|
16387
16161
|
const mp = manifestPath(dir);
|
|
16388
|
-
if (!(0,
|
|
16162
|
+
if (!(0, import_node_fs17.existsSync)(mp)) return null;
|
|
16389
16163
|
try {
|
|
16390
|
-
const parsed = JSON.parse((0,
|
|
16164
|
+
const parsed = JSON.parse((0, import_node_fs17.readFileSync)(mp, "utf-8"));
|
|
16391
16165
|
if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
|
|
16392
16166
|
return null;
|
|
16393
16167
|
}
|
|
@@ -16418,9 +16192,9 @@ function preImage(repoRelPath, baseline) {
|
|
|
16418
16192
|
function resolvePreImage(repoRelPath, baseline) {
|
|
16419
16193
|
if (baseline.dirty_paths.includes(repoRelPath)) {
|
|
16420
16194
|
const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
|
|
16421
|
-
if ((0,
|
|
16195
|
+
if ((0, import_node_fs17.existsSync)(mp)) {
|
|
16422
16196
|
try {
|
|
16423
|
-
return { content: (0,
|
|
16197
|
+
return { content: (0, import_node_fs17.readFileSync)(mp, "utf-8"), existed: true };
|
|
16424
16198
|
} catch {
|
|
16425
16199
|
}
|
|
16426
16200
|
}
|
|
@@ -16465,8 +16239,8 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
16465
16239
|
const content = safeReadForMirror(projectPath(p));
|
|
16466
16240
|
if (content === null) continue;
|
|
16467
16241
|
const dest = mirrorPath(dir, p);
|
|
16468
|
-
(0,
|
|
16469
|
-
(0,
|
|
16242
|
+
(0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(dest), { recursive: true });
|
|
16243
|
+
(0, import_node_fs17.writeFileSync)(dest, content);
|
|
16470
16244
|
dirty.add(p);
|
|
16471
16245
|
adopted++;
|
|
16472
16246
|
} catch {
|
|
@@ -16475,7 +16249,7 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
16475
16249
|
if (adopted === 0) return 0;
|
|
16476
16250
|
try {
|
|
16477
16251
|
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
16478
|
-
(0,
|
|
16252
|
+
(0, import_node_fs17.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
16479
16253
|
preImageCache.delete(baseline);
|
|
16480
16254
|
} catch {
|
|
16481
16255
|
return 0;
|
|
@@ -16486,7 +16260,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
16486
16260
|
const pre = preImage(repoRelPath, baseline);
|
|
16487
16261
|
let current;
|
|
16488
16262
|
try {
|
|
16489
|
-
current = (0,
|
|
16263
|
+
current = (0, import_node_fs17.readFileSync)(projectPath(repoRelPath), "utf-8");
|
|
16490
16264
|
} catch {
|
|
16491
16265
|
return pre.existed;
|
|
16492
16266
|
}
|
|
@@ -16495,8 +16269,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
16495
16269
|
}
|
|
16496
16270
|
function safeReadForMirror(absPath) {
|
|
16497
16271
|
try {
|
|
16498
|
-
if ((0,
|
|
16499
|
-
const buf = (0,
|
|
16272
|
+
if ((0, import_node_fs17.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
|
|
16273
|
+
const buf = (0, import_node_fs17.readFileSync)(absPath);
|
|
16500
16274
|
if (buf.includes(0)) return null;
|
|
16501
16275
|
return buf.toString("utf-8");
|
|
16502
16276
|
} catch {
|
|
@@ -16507,7 +16281,7 @@ function pruneOldBaselines() {
|
|
|
16507
16281
|
const root = projectPath(BASELINE_DIR);
|
|
16508
16282
|
let entries;
|
|
16509
16283
|
try {
|
|
16510
|
-
entries = (0,
|
|
16284
|
+
entries = (0, import_node_fs17.readdirSync)(root);
|
|
16511
16285
|
} catch {
|
|
16512
16286
|
return;
|
|
16513
16287
|
}
|
|
@@ -16517,8 +16291,8 @@ function pruneOldBaselines() {
|
|
|
16517
16291
|
const manifest = readManifest(dir);
|
|
16518
16292
|
if (!manifest) {
|
|
16519
16293
|
try {
|
|
16520
|
-
if (now - (0,
|
|
16521
|
-
(0,
|
|
16294
|
+
if (now - (0, import_node_fs17.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
|
|
16295
|
+
(0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
|
|
16522
16296
|
}
|
|
16523
16297
|
} catch {
|
|
16524
16298
|
}
|
|
@@ -16526,7 +16300,7 @@ function pruneOldBaselines() {
|
|
|
16526
16300
|
}
|
|
16527
16301
|
if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
|
|
16528
16302
|
try {
|
|
16529
|
-
(0,
|
|
16303
|
+
(0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
|
|
16530
16304
|
} catch {
|
|
16531
16305
|
}
|
|
16532
16306
|
}
|
|
@@ -16620,7 +16394,6 @@ function registerLifecycleCommands(program2) {
|
|
|
16620
16394
|
if (!verityConfigured()) process.exit(0);
|
|
16621
16395
|
const event = await readHookStdin();
|
|
16622
16396
|
const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
|
|
16623
|
-
if (deferredToPlugin("compact", sessionId)) process.exit(0);
|
|
16624
16397
|
const globals = program2.opts();
|
|
16625
16398
|
const tok = await resolveToken(globals.token);
|
|
16626
16399
|
const session2 = sessionDossier(tok.ok ? tok.data.token : null, sessionId);
|
|
@@ -16649,7 +16422,6 @@ function registerLifecycleCommands(program2) {
|
|
|
16649
16422
|
if (!verityConfigured()) process.exit(0);
|
|
16650
16423
|
const event = await readHookStdin();
|
|
16651
16424
|
const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
|
|
16652
|
-
if (deferredToPlugin("session end", sessionId)) process.exit(0);
|
|
16653
16425
|
const reason = opts.reason ?? event.session_end_reason ?? event.reason ?? "other";
|
|
16654
16426
|
if (reason === "clear") {
|
|
16655
16427
|
writeCarry(sessionId ?? void 0, getCurrentCommit());
|
|
@@ -16702,7 +16474,7 @@ function buildCompactionContext(session) {
|
|
|
16702
16474
|
readFileLines: (file) => {
|
|
16703
16475
|
try {
|
|
16704
16476
|
const abs = (0, import_node_path17.join)(root, file);
|
|
16705
|
-
return (0,
|
|
16477
|
+
return (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null;
|
|
16706
16478
|
} catch {
|
|
16707
16479
|
return null;
|
|
16708
16480
|
}
|
|
@@ -16759,18 +16531,18 @@ async function readHookStdin() {
|
|
|
16759
16531
|
|
|
16760
16532
|
// src/commands/standard.ts
|
|
16761
16533
|
var import_promises12 = require("node:fs/promises");
|
|
16762
|
-
var
|
|
16534
|
+
var import_node_fs25 = require("node:fs");
|
|
16763
16535
|
var import_yaml3 = __toESM(require_dist());
|
|
16764
16536
|
|
|
16765
16537
|
// src/lib/synthesize.ts
|
|
16766
16538
|
var import_node_child_process8 = require("node:child_process");
|
|
16767
|
-
var
|
|
16539
|
+
var import_node_fs21 = require("node:fs");
|
|
16768
16540
|
var import_promises9 = require("node:fs/promises");
|
|
16769
16541
|
var import_node_path20 = require("node:path");
|
|
16770
16542
|
var import_yaml = __toESM(require_dist());
|
|
16771
16543
|
|
|
16772
16544
|
// src/lib/data-dir.ts
|
|
16773
|
-
var
|
|
16545
|
+
var import_node_fs19 = require("node:fs");
|
|
16774
16546
|
var import_node_path18 = require("node:path");
|
|
16775
16547
|
function resolveDataDir() {
|
|
16776
16548
|
const candidates = [
|
|
@@ -16778,21 +16550,10 @@ function resolveDataDir() {
|
|
|
16778
16550
|
// installed: node_modules/@codacy/verity-cli/data
|
|
16779
16551
|
(0, import_node_path18.join)(__dirname, "..", "..", "data"),
|
|
16780
16552
|
// edge case: nested resolution
|
|
16781
|
-
// THE COMMITTED SOURCE, for a source checkout that has not been built.
|
|
16782
|
-
// cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
|
|
16783
|
-
// into it) and is gitignored, because skills have one committed source — so
|
|
16784
|
-
// in a fresh clone the packaged candidates above do not exist at all, and
|
|
16785
|
-
// without this the synthesizer throws "Could not find Verity skill data"
|
|
16786
|
-
// for every test and every `verity` run from source. Resolved from this
|
|
16787
|
-
// module's own location, never the cwd: see the warning below.
|
|
16788
|
-
(0, import_node_path18.join)(__dirname, "..", "..", "client"),
|
|
16789
|
-
// bundled: cli/bin/ → ../../client
|
|
16790
|
-
(0, import_node_path18.join)(__dirname, "..", "..", "..", "client"),
|
|
16791
|
-
// tsx: cli/src/lib/ → ../../../client
|
|
16792
16553
|
...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
|
|
16793
16554
|
];
|
|
16794
16555
|
for (const candidate of candidates) {
|
|
16795
|
-
if ((0,
|
|
16556
|
+
if ((0, import_node_fs19.existsSync)((0, import_node_path18.join)(candidate, "skills"))) {
|
|
16796
16557
|
return candidate;
|
|
16797
16558
|
}
|
|
16798
16559
|
}
|
|
@@ -16806,7 +16567,7 @@ function setupDataPath(file) {
|
|
|
16806
16567
|
|
|
16807
16568
|
// src/lib/detect.ts
|
|
16808
16569
|
var import_node_child_process7 = require("node:child_process");
|
|
16809
|
-
var
|
|
16570
|
+
var import_node_fs20 = require("node:fs");
|
|
16810
16571
|
var import_node_path19 = require("node:path");
|
|
16811
16572
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
16812
16573
|
"typescript",
|
|
@@ -16863,7 +16624,7 @@ function walk(root) {
|
|
|
16863
16624
|
if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
|
|
16864
16625
|
let entries;
|
|
16865
16626
|
try {
|
|
16866
|
-
entries = (0,
|
|
16627
|
+
entries = (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true });
|
|
16867
16628
|
} catch {
|
|
16868
16629
|
return;
|
|
16869
16630
|
}
|
|
@@ -16938,7 +16699,7 @@ var TOOL_CONFIG_MARKERS = [
|
|
|
16938
16699
|
];
|
|
16939
16700
|
function readJson(path) {
|
|
16940
16701
|
try {
|
|
16941
|
-
return JSON.parse((0,
|
|
16702
|
+
return JSON.parse((0, import_node_fs20.readFileSync)(path, "utf-8"));
|
|
16942
16703
|
} catch {
|
|
16943
16704
|
return null;
|
|
16944
16705
|
}
|
|
@@ -16971,9 +16732,9 @@ function declaredDependencies(root, files) {
|
|
|
16971
16732
|
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path19.join)(root, f))
|
|
16972
16733
|
];
|
|
16973
16734
|
for (const path of pythonManifests) {
|
|
16974
|
-
if (!(0,
|
|
16735
|
+
if (!(0, import_node_fs20.existsSync)(path)) continue;
|
|
16975
16736
|
try {
|
|
16976
|
-
const text = (0,
|
|
16737
|
+
const text = (0, import_node_fs20.readFileSync)(path, "utf-8");
|
|
16977
16738
|
for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
16978
16739
|
for (const line of text.split("\n")) {
|
|
16979
16740
|
if (!/dependencies\s*=/.test(line)) continue;
|
|
@@ -16987,9 +16748,9 @@ function declaredDependencies(root, files) {
|
|
|
16987
16748
|
...files.filter((f) => f.includes("/") && (0, import_node_path19.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path19.join)(root, f))
|
|
16988
16749
|
];
|
|
16989
16750
|
for (const path of goMods) {
|
|
16990
|
-
if (!(0,
|
|
16751
|
+
if (!(0, import_node_fs20.existsSync)(path)) continue;
|
|
16991
16752
|
try {
|
|
16992
|
-
const text = (0,
|
|
16753
|
+
const text = (0, import_node_fs20.readFileSync)(path, "utf-8");
|
|
16993
16754
|
for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
16994
16755
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
16995
16756
|
}
|
|
@@ -16998,9 +16759,9 @@ function declaredDependencies(root, files) {
|
|
|
16998
16759
|
}
|
|
16999
16760
|
for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
|
|
17000
16761
|
const path = (0, import_node_path19.join)(root, file);
|
|
17001
|
-
if (!(0,
|
|
16762
|
+
if (!(0, import_node_fs20.existsSync)(path)) continue;
|
|
17002
16763
|
try {
|
|
17003
|
-
const text = (0,
|
|
16764
|
+
const text = (0, import_node_fs20.readFileSync)(path, "utf-8");
|
|
17004
16765
|
for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
17005
16766
|
} catch {
|
|
17006
16767
|
}
|
|
@@ -17008,7 +16769,7 @@ function declaredDependencies(root, files) {
|
|
|
17008
16769
|
return names2;
|
|
17009
16770
|
}
|
|
17010
16771
|
function detectBuildSystem(root, files) {
|
|
17011
|
-
const has = (f) => (0,
|
|
16772
|
+
const has = (f) => (0, import_node_fs20.existsSync)((0, import_node_path19.join)(root, f)) || files.some((p) => (0, import_node_path19.basename)(p) === f);
|
|
17012
16773
|
if (has("pnpm-lock.yaml")) return "pnpm";
|
|
17013
16774
|
if (has("yarn.lock")) return "yarn";
|
|
17014
16775
|
if (has("bun.lock") || has("bun.lockb")) return "bun";
|
|
@@ -17025,7 +16786,7 @@ function detectBuildSystem(root, files) {
|
|
|
17025
16786
|
}
|
|
17026
16787
|
function detectArchitecture(root, files) {
|
|
17027
16788
|
const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
|
|
17028
|
-
if (workspaceMarkers.some((m) => (0,
|
|
16789
|
+
if (workspaceMarkers.some((m) => (0, import_node_fs20.existsSync)((0, import_node_path19.join)(root, m)))) return "monorepo";
|
|
17029
16790
|
const pkg = readJson((0, import_node_path19.join)(root, "package.json"));
|
|
17030
16791
|
if (pkg && "workspaces" in pkg) return "monorepo";
|
|
17031
16792
|
const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
|
|
@@ -17050,8 +16811,8 @@ function measureAvgFileLength(root, files, languages) {
|
|
|
17050
16811
|
for (let i = 0; i < candidates.length; i += stride) {
|
|
17051
16812
|
const path = (0, import_node_path19.join)(root, candidates[i]);
|
|
17052
16813
|
try {
|
|
17053
|
-
if ((0,
|
|
17054
|
-
total += (0,
|
|
16814
|
+
if ((0, import_node_fs20.statSync)(path).size > 2 * 1024 * 1024) continue;
|
|
16815
|
+
total += (0, import_node_fs20.readFileSync)(path, "utf-8").split("\n").length;
|
|
17055
16816
|
counted++;
|
|
17056
16817
|
} catch {
|
|
17057
16818
|
}
|
|
@@ -17076,7 +16837,7 @@ function detectProject(root = repoRoot()) {
|
|
|
17076
16837
|
const existingToolConfigs = [];
|
|
17077
16838
|
for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
|
|
17078
16839
|
for (const marker of markers) {
|
|
17079
|
-
if ((0,
|
|
16840
|
+
if ((0, import_node_fs20.existsSync)((0, import_node_path19.join)(root, marker))) {
|
|
17080
16841
|
existingToolConfigs.push({ tool, path: `./${marker}` });
|
|
17081
16842
|
break;
|
|
17082
16843
|
}
|
|
@@ -17181,8 +16942,8 @@ ${closingNote(input.origin)}
|
|
|
17181
16942
|
|
|
17182
16943
|
// src/lib/synthesize.ts
|
|
17183
16944
|
function loadCatalog() {
|
|
17184
|
-
const catalog = (0, import_yaml.parse)((0,
|
|
17185
|
-
const template = (0, import_yaml.parse)((0,
|
|
16945
|
+
const catalog = (0, import_yaml.parse)((0, import_node_fs21.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
|
|
16946
|
+
const template = (0, import_yaml.parse)((0, import_node_fs21.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
|
|
17186
16947
|
return { catalog, template };
|
|
17187
16948
|
}
|
|
17188
16949
|
function selectTools(languages, intensity, catalog) {
|
|
@@ -17460,7 +17221,7 @@ function validatePatternIds() {
|
|
|
17460
17221
|
}
|
|
17461
17222
|
async function runSynthesis(opts) {
|
|
17462
17223
|
const standardPath = projectPath(STANDARD_FILE);
|
|
17463
|
-
if ((0,
|
|
17224
|
+
if ((0, import_node_fs21.existsSync)(standardPath) && !opts.force) {
|
|
17464
17225
|
return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
|
|
17465
17226
|
}
|
|
17466
17227
|
const detected = opts.detected ?? detectProject();
|
|
@@ -17588,11 +17349,11 @@ ${validation.detail}`);
|
|
|
17588
17349
|
|
|
17589
17350
|
// src/lib/setup-state.ts
|
|
17590
17351
|
var import_promises10 = require("node:fs/promises");
|
|
17591
|
-
var
|
|
17352
|
+
var import_node_fs22 = require("node:fs");
|
|
17592
17353
|
var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
|
|
17593
17354
|
async function readSetupState() {
|
|
17594
17355
|
const path = projectPath(SETUP_STATE_FILE);
|
|
17595
|
-
if (!(0,
|
|
17356
|
+
if (!(0, import_node_fs22.existsSync)(path)) return null;
|
|
17596
17357
|
try {
|
|
17597
17358
|
const parsed = JSON.parse(await (0, import_promises10.readFile)(path, "utf-8"));
|
|
17598
17359
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
@@ -17608,12 +17369,12 @@ async function writeSetupState(patch) {
|
|
|
17608
17369
|
}
|
|
17609
17370
|
|
|
17610
17371
|
// src/lib/push-setup.ts
|
|
17611
|
-
var
|
|
17372
|
+
var import_node_fs24 = require("node:fs");
|
|
17612
17373
|
var import_promises11 = require("node:fs/promises");
|
|
17613
17374
|
var import_yaml2 = __toESM(require_dist());
|
|
17614
17375
|
|
|
17615
17376
|
// src/lib/verityignore.ts
|
|
17616
|
-
var
|
|
17377
|
+
var import_node_fs23 = require("node:fs");
|
|
17617
17378
|
var EMPTY = { rules: [], securityOverlap: [], problems: [] };
|
|
17618
17379
|
var SECURITY_PROBES = [
|
|
17619
17380
|
".env",
|
|
@@ -17706,9 +17467,9 @@ function isIgnored2(ig, path) {
|
|
|
17706
17467
|
}
|
|
17707
17468
|
function loadVerityIgnore() {
|
|
17708
17469
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
17709
|
-
if (!(0,
|
|
17470
|
+
if (!(0, import_node_fs23.existsSync)(file)) return EMPTY;
|
|
17710
17471
|
try {
|
|
17711
|
-
return parseVerityIgnore((0,
|
|
17472
|
+
return parseVerityIgnore((0, import_node_fs23.readFileSync)(file, "utf-8"));
|
|
17712
17473
|
} catch {
|
|
17713
17474
|
return EMPTY;
|
|
17714
17475
|
}
|
|
@@ -17746,9 +17507,9 @@ function buildStandardUpload(standard, ignoreRaw) {
|
|
|
17746
17507
|
}
|
|
17747
17508
|
function readVerityIgnoreRaw() {
|
|
17748
17509
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
17749
|
-
if (!(0,
|
|
17510
|
+
if (!(0, import_node_fs23.existsSync)(file)) return null;
|
|
17750
17511
|
try {
|
|
17751
|
-
return (0,
|
|
17512
|
+
return (0, import_node_fs23.readFileSync)(file, "utf-8");
|
|
17752
17513
|
} catch {
|
|
17753
17514
|
return null;
|
|
17754
17515
|
}
|
|
@@ -17776,7 +17537,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
17776
17537
|
}
|
|
17777
17538
|
let standardVersion = null;
|
|
17778
17539
|
const standardPath = projectPath(STANDARD_FILE);
|
|
17779
|
-
if (pushStandard && (0,
|
|
17540
|
+
if (pushStandard && (0, import_node_fs24.existsSync)(standardPath)) {
|
|
17780
17541
|
try {
|
|
17781
17542
|
const content = (0, import_yaml2.parse)(await (0, import_promises11.readFile)(standardPath, "utf-8"));
|
|
17782
17543
|
const upload = buildStandardUpload(content, readVerityIgnoreRaw());
|
|
@@ -17801,7 +17562,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
17801
17562
|
}
|
|
17802
17563
|
let configPushed = false;
|
|
17803
17564
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
17804
|
-
if (pushConfig && (0,
|
|
17565
|
+
if (pushConfig && (0, import_node_fs24.existsSync)(configPath)) {
|
|
17805
17566
|
try {
|
|
17806
17567
|
const content = JSON.parse(await (0, import_promises11.readFile)(configPath, "utf-8"));
|
|
17807
17568
|
const result = await apiRequest({
|
|
@@ -17833,7 +17594,7 @@ function registerStandardCommands(program2) {
|
|
|
17833
17594
|
const state = await readSetupState();
|
|
17834
17595
|
if (opts.configOnly) {
|
|
17835
17596
|
const standardPath = projectPath(STANDARD_FILE);
|
|
17836
|
-
if (!(0,
|
|
17597
|
+
if (!(0, import_node_fs25.existsSync)(standardPath)) {
|
|
17837
17598
|
printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
|
|
17838
17599
|
process.exit(1);
|
|
17839
17600
|
}
|
|
@@ -18002,22 +17763,6 @@ function registerConfigCommands(program2) {
|
|
|
18002
17763
|
}
|
|
18003
17764
|
process.stdout.write(urlResult.data + "\n");
|
|
18004
17765
|
});
|
|
18005
|
-
config.command("git-moments [moments]").description('Get or set the git moments the guard reviews: commit,push \u2014 or "none"').action((moments) => {
|
|
18006
|
-
if (moments === void 0) {
|
|
18007
|
-
const current = readProjectConfig().git_moments;
|
|
18008
|
-
process.stdout.write((current.length ? current.join(",") : "none") + "\n");
|
|
18009
|
-
return;
|
|
18010
|
-
}
|
|
18011
|
-
const next = moments === "none" ? [] : parseMoments(moments);
|
|
18012
|
-
if (moments !== "none" && next.length === 0) {
|
|
18013
|
-
printError(`Unrecognised moments: ${moments}. Use "commit", "push", "commit,push", or "none".`);
|
|
18014
|
-
process.exit(1);
|
|
18015
|
-
}
|
|
18016
|
-
writeProjectConfig({ git_moments: next });
|
|
18017
|
-
printInfo(
|
|
18018
|
-
next.length ? `Git-moment review enabled for: ${next.join(", ")}` : "Git-moment review disabled \u2014 commits and pushes are no longer gated."
|
|
18019
|
-
);
|
|
18020
|
-
});
|
|
18021
17766
|
config.command("push").description("Upload the analysis config to the service").option("--file <path>", "Path to config file", CODACY_CONFIG_FILE).action(async (opts) => {
|
|
18022
17767
|
const globals = program2.opts();
|
|
18023
17768
|
const tokenResult = await resolveToken(globals.token);
|
|
@@ -18160,10 +17905,10 @@ function formatRunDetail(run2) {
|
|
|
18160
17905
|
}
|
|
18161
17906
|
|
|
18162
17907
|
// src/lib/ignore-declaration.ts
|
|
18163
|
-
var
|
|
17908
|
+
var import_node_fs27 = require("node:fs");
|
|
18164
17909
|
|
|
18165
17910
|
// src/lib/debounce.ts
|
|
18166
|
-
var
|
|
17911
|
+
var import_node_fs26 = require("node:fs");
|
|
18167
17912
|
var import_node_crypto10 = require("node:crypto");
|
|
18168
17913
|
function scopedFile(base, sessionId) {
|
|
18169
17914
|
if (!sessionId) return base;
|
|
@@ -18171,9 +17916,9 @@ function scopedFile(base, sessionId) {
|
|
|
18171
17916
|
}
|
|
18172
17917
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
18173
17918
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
18174
|
-
if (!(0,
|
|
17919
|
+
if (!(0, import_node_fs26.existsSync)(file)) return null;
|
|
18175
17920
|
try {
|
|
18176
|
-
const lastTs = parseInt((0,
|
|
17921
|
+
const lastTs = parseInt((0, import_node_fs26.readFileSync)(file, "utf-8").trim(), 10);
|
|
18177
17922
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
18178
17923
|
const elapsed = nowTs - lastTs;
|
|
18179
17924
|
if (elapsed < debounceSeconds) {
|
|
@@ -18186,10 +17931,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
|
18186
17931
|
function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
18187
17932
|
if (bypassForRecentCommits) return null;
|
|
18188
17933
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
18189
|
-
if (!(0,
|
|
17934
|
+
if (!(0, import_node_fs26.existsSync)(file)) return null;
|
|
18190
17935
|
let debounceTime;
|
|
18191
17936
|
try {
|
|
18192
|
-
debounceTime = (0,
|
|
17937
|
+
debounceTime = (0, import_node_fs26.statSync)(file).mtimeMs;
|
|
18193
17938
|
} catch {
|
|
18194
17939
|
return null;
|
|
18195
17940
|
}
|
|
@@ -18197,7 +17942,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
18197
17942
|
const resolved = resolveFile(f);
|
|
18198
17943
|
if (!resolved) continue;
|
|
18199
17944
|
try {
|
|
18200
|
-
const stat3 = (0,
|
|
17945
|
+
const stat3 = (0, import_node_fs26.statSync)(resolved);
|
|
18201
17946
|
if (stat3.mtimeMs > debounceTime) {
|
|
18202
17947
|
return null;
|
|
18203
17948
|
}
|
|
@@ -18213,8 +17958,8 @@ function computeContentHash(files) {
|
|
|
18213
17958
|
for (const f of sorted) {
|
|
18214
17959
|
const resolved = resolveFile(f) ?? f;
|
|
18215
17960
|
try {
|
|
18216
|
-
if ((0,
|
|
18217
|
-
hash.update((0,
|
|
17961
|
+
if ((0, import_node_fs26.existsSync)(resolved)) {
|
|
17962
|
+
hash.update((0, import_node_fs26.readFileSync)(resolved));
|
|
18218
17963
|
}
|
|
18219
17964
|
} catch {
|
|
18220
17965
|
}
|
|
@@ -18224,9 +17969,9 @@ function computeContentHash(files) {
|
|
|
18224
17969
|
function checkContentHash(files, sessionId) {
|
|
18225
17970
|
const hash = computeContentHash(files);
|
|
18226
17971
|
const file = scopedFile(HASH_FILE, sessionId);
|
|
18227
|
-
if ((0,
|
|
17972
|
+
if ((0, import_node_fs26.existsSync)(file)) {
|
|
18228
17973
|
try {
|
|
18229
|
-
const storedHash = (0,
|
|
17974
|
+
const storedHash = (0, import_node_fs26.readFileSync)(file, "utf-8").trim();
|
|
18230
17975
|
if (hash === storedHash) {
|
|
18231
17976
|
return { skip: "No source changes since last analysis", hash };
|
|
18232
17977
|
}
|
|
@@ -18236,24 +17981,24 @@ function checkContentHash(files, sessionId) {
|
|
|
18236
17981
|
return { skip: null, hash };
|
|
18237
17982
|
}
|
|
18238
17983
|
function recordAnalysisStart(sessionId) {
|
|
18239
|
-
(0,
|
|
18240
|
-
(0,
|
|
17984
|
+
(0, import_node_fs26.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
17985
|
+
(0, import_node_fs26.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
|
|
18241
17986
|
}
|
|
18242
17987
|
function recordPassHash(hash, sessionId) {
|
|
18243
|
-
(0,
|
|
17988
|
+
(0, import_node_fs26.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
|
|
18244
17989
|
}
|
|
18245
17990
|
function narrowToRecent(files, sessionId) {
|
|
18246
17991
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
18247
|
-
if (!(0,
|
|
17992
|
+
if (!(0, import_node_fs26.existsSync)(file)) return files;
|
|
18248
17993
|
let debounceTime;
|
|
18249
17994
|
try {
|
|
18250
|
-
debounceTime = (0,
|
|
17995
|
+
debounceTime = (0, import_node_fs26.statSync)(file).mtimeMs;
|
|
18251
17996
|
} catch {
|
|
18252
17997
|
return files;
|
|
18253
17998
|
}
|
|
18254
17999
|
const recent = files.filter((f) => {
|
|
18255
18000
|
try {
|
|
18256
|
-
return (0,
|
|
18001
|
+
return (0, import_node_fs26.existsSync)(f) && (0, import_node_fs26.statSync)(f).mtimeMs > debounceTime;
|
|
18257
18002
|
} catch {
|
|
18258
18003
|
return false;
|
|
18259
18004
|
}
|
|
@@ -18266,9 +18011,9 @@ function readIteration(currentCommit, _contentHash) {
|
|
|
18266
18011
|
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
18267
18012
|
function readBlockState(currentCommit, opts) {
|
|
18268
18013
|
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
18269
|
-
if (!(0,
|
|
18014
|
+
if (!(0, import_node_fs26.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
18270
18015
|
try {
|
|
18271
|
-
const stored = (0,
|
|
18016
|
+
const stored = (0, import_node_fs26.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
18272
18017
|
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
18273
18018
|
if (!parsed) return NO_BLOCKS;
|
|
18274
18019
|
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
@@ -18314,8 +18059,8 @@ function isSameProblem(previous, current) {
|
|
|
18314
18059
|
return current.split(",").some((k) => prev.has(k));
|
|
18315
18060
|
}
|
|
18316
18061
|
function writeBlockState(commit, state) {
|
|
18317
|
-
(0,
|
|
18318
|
-
(0,
|
|
18062
|
+
(0, import_node_fs26.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
18063
|
+
(0, import_node_fs26.writeFileSync)(
|
|
18319
18064
|
ITERATION_FILE,
|
|
18320
18065
|
JSON.stringify({
|
|
18321
18066
|
v: 2,
|
|
@@ -18420,9 +18165,9 @@ function resolveIgnoreState(keys) {
|
|
|
18420
18165
|
}
|
|
18421
18166
|
function readIgnoreState(sessionId) {
|
|
18422
18167
|
const file = stateFile(sessionId);
|
|
18423
|
-
if (!(0,
|
|
18168
|
+
if (!(0, import_node_fs27.existsSync)(file)) return null;
|
|
18424
18169
|
try {
|
|
18425
|
-
const o = JSON.parse((0,
|
|
18170
|
+
const o = JSON.parse((0, import_node_fs27.readFileSync)(file, "utf-8")) ?? {};
|
|
18426
18171
|
const spent = typeof o.spent === "number" ? o.spent : 0;
|
|
18427
18172
|
const raw = o.active;
|
|
18428
18173
|
let active = null;
|
|
@@ -18446,8 +18191,8 @@ function readIgnoreState(sessionId) {
|
|
|
18446
18191
|
}
|
|
18447
18192
|
function writeIgnoreState(state, sessionId) {
|
|
18448
18193
|
try {
|
|
18449
|
-
(0,
|
|
18450
|
-
(0,
|
|
18194
|
+
(0, import_node_fs27.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
18195
|
+
(0, import_node_fs27.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
|
|
18451
18196
|
} catch {
|
|
18452
18197
|
}
|
|
18453
18198
|
}
|
|
@@ -18821,8 +18566,59 @@ function createRun(opts, globals) {
|
|
|
18821
18566
|
};
|
|
18822
18567
|
}
|
|
18823
18568
|
|
|
18824
|
-
// src/
|
|
18825
|
-
var
|
|
18569
|
+
// src/lib/stderr-log.ts
|
|
18570
|
+
var import_node_fs28 = require("node:fs");
|
|
18571
|
+
var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
|
|
18572
|
+
var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
18573
|
+
function scrub(s) {
|
|
18574
|
+
return s.replace(TOKEN_RE2, "verity_***REDACTED***").replace(ANSI_RE, "");
|
|
18575
|
+
}
|
|
18576
|
+
var installed = false;
|
|
18577
|
+
var wroteBanner = false;
|
|
18578
|
+
var banner = "";
|
|
18579
|
+
function append(text) {
|
|
18580
|
+
try {
|
|
18581
|
+
const dir = projectPath(DEBUG_LOG_DIR);
|
|
18582
|
+
const file = projectPath(STDERR_LOG_FILE);
|
|
18583
|
+
(0, import_node_fs28.mkdirSync)(dir, { recursive: true });
|
|
18584
|
+
rotateIfNeeded(file);
|
|
18585
|
+
(0, import_node_fs28.appendFileSync)(file, text);
|
|
18586
|
+
} catch {
|
|
18587
|
+
}
|
|
18588
|
+
}
|
|
18589
|
+
function ensureBanner() {
|
|
18590
|
+
if (wroteBanner) return;
|
|
18591
|
+
wroteBanner = true;
|
|
18592
|
+
append(banner);
|
|
18593
|
+
}
|
|
18594
|
+
function installStderrLog(cmd, argv, version) {
|
|
18595
|
+
if (installed || !isDebugEnabled()) return;
|
|
18596
|
+
installed = true;
|
|
18597
|
+
banner = `
|
|
18598
|
+
\u2501\u2501 verity ${cmd} \xB7 ${(/* @__PURE__ */ new Date()).toISOString()} \xB7 pid ${process.pid}
|
|
18599
|
+
v${version} \xB7 ${process.cwd()}
|
|
18600
|
+
argv: ${scrub(argv.join(" "))}
|
|
18601
|
+
`;
|
|
18602
|
+
const original = process.stderr.write.bind(process.stderr);
|
|
18603
|
+
const tee = (...args) => {
|
|
18604
|
+
const result = original(...args);
|
|
18605
|
+
try {
|
|
18606
|
+
const chunk = args[0];
|
|
18607
|
+
const text = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
|
|
18608
|
+
ensureBanner();
|
|
18609
|
+
append(scrub(text));
|
|
18610
|
+
} catch {
|
|
18611
|
+
}
|
|
18612
|
+
return result;
|
|
18613
|
+
};
|
|
18614
|
+
process.stderr.write = tee;
|
|
18615
|
+
}
|
|
18616
|
+
function logToFileOnly(text) {
|
|
18617
|
+
if (!installed) return;
|
|
18618
|
+
ensureBanner();
|
|
18619
|
+
append(text.endsWith("\n") ? text : `${text}
|
|
18620
|
+
`);
|
|
18621
|
+
}
|
|
18826
18622
|
|
|
18827
18623
|
// src/lib/repo-context.ts
|
|
18828
18624
|
var import_node_child_process9 = require("node:child_process");
|
|
@@ -19643,7 +19439,7 @@ function installRunEvidence(run2) {
|
|
|
19643
19439
|
|
|
19644
19440
|
// src/lib/git-frame.ts
|
|
19645
19441
|
var import_node_child_process10 = require("node:child_process");
|
|
19646
|
-
var
|
|
19442
|
+
var import_node_fs29 = require("node:fs");
|
|
19647
19443
|
var import_node_os4 = require("node:os");
|
|
19648
19444
|
var import_node_path21 = require("node:path");
|
|
19649
19445
|
var import_node_path22 = require("node:path");
|
|
@@ -19782,14 +19578,14 @@ function gitAt(dir, args) {
|
|
|
19782
19578
|
}
|
|
19783
19579
|
function realpathOr(p) {
|
|
19784
19580
|
try {
|
|
19785
|
-
return
|
|
19581
|
+
return import_node_fs29.realpathSync.native(p);
|
|
19786
19582
|
} catch {
|
|
19787
19583
|
return (0, import_node_path21.resolve)(p);
|
|
19788
19584
|
}
|
|
19789
19585
|
}
|
|
19790
19586
|
function resolveFrame(input) {
|
|
19791
19587
|
const found = findMomentSegment(input.command, input.on);
|
|
19792
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
19588
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs29.existsSync)(input.hookCwd);
|
|
19793
19589
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
19794
19590
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
19795
19591
|
const refuse = (refusal) => ({
|
|
@@ -19812,7 +19608,7 @@ function resolveFrame(input) {
|
|
|
19812
19608
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
19813
19609
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
19814
19610
|
if (targetDir !== baseDir) {
|
|
19815
|
-
if (!(0,
|
|
19611
|
+
if (!(0, import_node_fs29.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
19816
19612
|
dir = targetDir;
|
|
19817
19613
|
}
|
|
19818
19614
|
}
|
|
@@ -19848,19 +19644,21 @@ function refResolves(frame, ref) {
|
|
|
19848
19644
|
return frameGit(frame, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]) !== "";
|
|
19849
19645
|
}
|
|
19850
19646
|
var SHA_RE2 = /^[0-9a-f]{40}$/;
|
|
19851
|
-
function
|
|
19852
|
-
if (!frame.worktreeRoot) return
|
|
19853
|
-
|
|
19854
|
-
|
|
19855
|
-
|
|
19856
|
-
|
|
19857
|
-
|
|
19858
|
-
return
|
|
19647
|
+
function baselineShaAt(frame) {
|
|
19648
|
+
if (!frame.worktreeRoot) return null;
|
|
19649
|
+
try {
|
|
19650
|
+
const sha = (0, import_node_fs29.readFileSync)((0, import_node_path22.join)(frame.worktreeRoot, BASELINE_SHA_FILE), "utf-8").trim();
|
|
19651
|
+
if (!SHA_RE2.test(sha)) return null;
|
|
19652
|
+
return refResolves(frame, sha) ? sha : null;
|
|
19653
|
+
} catch {
|
|
19654
|
+
return null;
|
|
19859
19655
|
}
|
|
19656
|
+
}
|
|
19657
|
+
function stagedRange() {
|
|
19860
19658
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "index" };
|
|
19861
19659
|
}
|
|
19862
19660
|
function resolvePushRange(frame, command, on) {
|
|
19863
|
-
const nothing = (
|
|
19661
|
+
const nothing = (via) => ({ kind: "nothing", base: null, head: "HEAD", via });
|
|
19864
19662
|
if (!frame.worktreeRoot) return nothing("refused");
|
|
19865
19663
|
const found = findMomentSegment(command, on);
|
|
19866
19664
|
const segment = found ? splitSegments(command)[found.segmentIndex] : "";
|
|
@@ -19868,32 +19666,54 @@ function resolvePushRange(frame, command, on) {
|
|
|
19868
19666
|
if (target.isDelete) return nothing("deletion");
|
|
19869
19667
|
const head = target.srcRef ?? "HEAD";
|
|
19870
19668
|
if (!refResolves(frame, head)) return nothing(`src-unresolvable:${head}`);
|
|
19871
|
-
const
|
|
19872
|
-
const
|
|
19873
|
-
const
|
|
19874
|
-
if (
|
|
19875
|
-
|
|
19876
|
-
|
|
19877
|
-
|
|
19878
|
-
|
|
19879
|
-
|
|
19880
|
-
|
|
19881
|
-
|
|
19669
|
+
const srcName = target.srcRef;
|
|
19670
|
+
const branchForRemote = srcName ?? frame.branch;
|
|
19671
|
+
const candidates = [];
|
|
19672
|
+
if (target.remote && (target.dstRef ?? srcName)) {
|
|
19673
|
+
const dstName = (target.dstRef ?? srcName).replace(/^refs\/heads\//, "");
|
|
19674
|
+
candidates.push({ ref: `refs/remotes/${target.remote}/${dstName}`, via: `refspec:${target.remote}/${dstName}` });
|
|
19675
|
+
}
|
|
19676
|
+
if (target.remote && !srcName && !target.dstRef && frame.branch) {
|
|
19677
|
+
candidates.push({ ref: `refs/remotes/${target.remote}/${frame.branch}`, via: `remote:${target.remote}/${frame.branch}` });
|
|
19678
|
+
}
|
|
19679
|
+
candidates.push({ ref: srcName ? `${srcName}@{push}` : "@{push}", via: "@{push}" });
|
|
19680
|
+
candidates.push({ ref: srcName ? `${srcName}@{upstream}` : "@{upstream}", via: "@{upstream}" });
|
|
19681
|
+
if (branchForRemote) {
|
|
19682
|
+
candidates.push({
|
|
19683
|
+
ref: `refs/remotes/origin/${branchForRemote.replace(/^refs\/heads\//, "")}`,
|
|
19684
|
+
via: `origin/${branchForRemote.replace(/^refs\/heads\//, "")}`
|
|
19685
|
+
});
|
|
19686
|
+
}
|
|
19687
|
+
for (const c of candidates) {
|
|
19688
|
+
if (!refResolves(frame, c.ref)) continue;
|
|
19689
|
+
const mergeBase = frameGit(frame, ["merge-base", c.ref, head]);
|
|
19690
|
+
if (SHA_RE2.test(mergeBase)) return { kind: "push", base: mergeBase, head, via: c.via };
|
|
19882
19691
|
}
|
|
19883
|
-
|
|
19692
|
+
const baseline = baselineShaAt(frame);
|
|
19693
|
+
if (baseline) return { kind: "baseline", base: baseline, head, via: "review-baseline" };
|
|
19694
|
+
if (refResolves(frame, `${head}~1`)) return { kind: "last-commit", base: `${head}~1`, head, via: `${head}~1` };
|
|
19695
|
+
return nothing("no-parent");
|
|
19884
19696
|
}
|
|
19885
19697
|
function rangeFiles(frame, range) {
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19698
|
+
let out;
|
|
19699
|
+
switch (range.kind) {
|
|
19700
|
+
case "staged":
|
|
19701
|
+
out = frameGit(frame, ["diff", "--cached", "--name-only"]);
|
|
19702
|
+
break;
|
|
19703
|
+
case "push":
|
|
19704
|
+
case "baseline":
|
|
19705
|
+
case "last-commit":
|
|
19706
|
+
out = frameGit(frame, ["diff", "--name-only", range.base, range.head === "INDEX" ? "HEAD" : range.head]);
|
|
19707
|
+
break;
|
|
19708
|
+
case "nothing":
|
|
19709
|
+
return [];
|
|
19889
19710
|
}
|
|
19890
|
-
return
|
|
19711
|
+
return out.split("\n").filter((l) => l.length > 0).filter((f) => !isVerityOwnedPath(f));
|
|
19891
19712
|
}
|
|
19892
19713
|
function rangeChangeSignals(frame, range, paths) {
|
|
19893
19714
|
const out = /* @__PURE__ */ new Map();
|
|
19894
19715
|
if (range.kind === "nothing" || paths.length === 0) return out;
|
|
19895
|
-
|
|
19896
|
-
const args = range.kind === "staged" || range.kind === "merge" ? ["diff", "--cached", "--unified=0"] : ["diff", "--unified=0", range.base, range.head === "INDEX" ? "HEAD" : range.head];
|
|
19716
|
+
const args = range.kind === "staged" ? ["diff", "--cached", "--unified=0"] : ["diff", "--unified=0", range.base, range.head === "INDEX" ? "HEAD" : range.head];
|
|
19897
19717
|
const diff = frameGit(frame, [...args, "--", ...paths]);
|
|
19898
19718
|
let current = null;
|
|
19899
19719
|
let oldSide = null;
|
|
@@ -19925,9 +19745,8 @@ function rangeChangeSignals(frame, range, paths) {
|
|
|
19925
19745
|
return out;
|
|
19926
19746
|
}
|
|
19927
19747
|
function rangeMessages(frame, range) {
|
|
19928
|
-
if (range.kind
|
|
19929
|
-
|
|
19930
|
-
return frameGit(frame, ["show", "-s", "--format=%B%x00", ...commits]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
|
|
19748
|
+
if (range.kind === "staged" || range.kind === "nothing" || !range.base) return "";
|
|
19749
|
+
return frameGit(frame, ["log", `${range.base}..${range.head === "INDEX" ? "HEAD" : range.head}`, "--format=%B%x00"]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
|
|
19931
19750
|
}
|
|
19932
19751
|
function frameTelemetry(frame, range, divergence) {
|
|
19933
19752
|
const t = {
|
|
@@ -19975,7 +19794,7 @@ function truthy(v) {
|
|
|
19975
19794
|
}
|
|
19976
19795
|
|
|
19977
19796
|
// src/lib/transcript.ts
|
|
19978
|
-
var
|
|
19797
|
+
var import_node_fs30 = require("node:fs");
|
|
19979
19798
|
var MAX_READ_BYTES = 256 * 1024;
|
|
19980
19799
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
19981
19800
|
var MAX_FILES_LIST = 20;
|
|
@@ -20002,7 +19821,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
20002
19821
|
function readTurnLines(transcriptPath) {
|
|
20003
19822
|
let size;
|
|
20004
19823
|
try {
|
|
20005
|
-
size = (0,
|
|
19824
|
+
size = (0, import_node_fs30.statSync)(transcriptPath).size;
|
|
20006
19825
|
} catch {
|
|
20007
19826
|
return null;
|
|
20008
19827
|
}
|
|
@@ -20010,7 +19829,7 @@ function readTurnLines(transcriptPath) {
|
|
|
20010
19829
|
let raw;
|
|
20011
19830
|
let windowed = false;
|
|
20012
19831
|
if (size <= SMALL_FILE_BYTES) {
|
|
20013
|
-
raw = (0,
|
|
19832
|
+
raw = (0, import_node_fs30.readFileSync)(transcriptPath, "utf-8");
|
|
20014
19833
|
} else {
|
|
20015
19834
|
windowed = true;
|
|
20016
19835
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -20327,9 +20146,6 @@ async function bootstrap(run2) {
|
|
|
20327
20146
|
isTTY: process.stdout.isTTY === true
|
|
20328
20147
|
});
|
|
20329
20148
|
const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
|
|
20330
|
-
if (deferredToPlugin("analyze", sessionId ?? process.env.CLAUDE_SESSION_ID ?? null)) {
|
|
20331
|
-
process.exit(0);
|
|
20332
|
-
}
|
|
20333
20149
|
const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
|
|
20334
20150
|
const tokenResult = await resolveToken(globals.token);
|
|
20335
20151
|
const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
@@ -20509,7 +20325,7 @@ function channelSilence(input) {
|
|
|
20509
20325
|
// src/lib/cli-version.ts
|
|
20510
20326
|
function cliVersion() {
|
|
20511
20327
|
try {
|
|
20512
|
-
return true ? "0.32.0-experimental.
|
|
20328
|
+
return true ? "0.32.0-experimental.f0746f7" : "dev";
|
|
20513
20329
|
} catch {
|
|
20514
20330
|
return "dev";
|
|
20515
20331
|
}
|
|
@@ -20550,7 +20366,7 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
20550
20366
|
|
|
20551
20367
|
// src/lib/static-analysis.ts
|
|
20552
20368
|
var import_node_child_process11 = require("node:child_process");
|
|
20553
|
-
var
|
|
20369
|
+
var import_node_fs31 = require("node:fs");
|
|
20554
20370
|
var SEVERITY_ORDER = {
|
|
20555
20371
|
Error: 0,
|
|
20556
20372
|
Critical: 0,
|
|
@@ -20598,7 +20414,7 @@ function runCodacyAnalysis(files) {
|
|
|
20598
20414
|
if (files.length === 0) return empty;
|
|
20599
20415
|
const existingFiles = files.filter((f) => {
|
|
20600
20416
|
try {
|
|
20601
|
-
return (0,
|
|
20417
|
+
return (0, import_node_fs31.existsSync)(f);
|
|
20602
20418
|
} catch {
|
|
20603
20419
|
return false;
|
|
20604
20420
|
}
|
|
@@ -20867,7 +20683,7 @@ async function scope(run2) {
|
|
|
20867
20683
|
}
|
|
20868
20684
|
|
|
20869
20685
|
// src/lib/specs.ts
|
|
20870
|
-
var
|
|
20686
|
+
var import_node_fs32 = require("node:fs");
|
|
20871
20687
|
var import_node_path23 = require("node:path");
|
|
20872
20688
|
var SPEC_CANDIDATES = [
|
|
20873
20689
|
"CLAUDE.md",
|
|
@@ -20899,16 +20715,16 @@ function discoverSpecs(consulted = []) {
|
|
|
20899
20715
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
20900
20716
|
if (totalBytes >= totalCap) return false;
|
|
20901
20717
|
if (seen.has(specPath)) return true;
|
|
20902
|
-
if (!(0,
|
|
20718
|
+
if (!(0, import_node_fs32.existsSync)(specPath)) return true;
|
|
20903
20719
|
seen.add(specPath);
|
|
20904
20720
|
const remaining = totalCap - totalBytes;
|
|
20905
20721
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
20906
20722
|
const readBytes = Math.min(fileCap, remaining);
|
|
20907
20723
|
try {
|
|
20908
20724
|
const buf = Buffer.alloc(readBytes);
|
|
20909
|
-
const fd = (0,
|
|
20910
|
-
const bytesRead = (0,
|
|
20911
|
-
(0,
|
|
20725
|
+
const fd = (0, import_node_fs32.openSync)(specPath, "r");
|
|
20726
|
+
const bytesRead = (0, import_node_fs32.readSync)(fd, buf, 0, readBytes, 0);
|
|
20727
|
+
(0, import_node_fs32.closeSync)(fd);
|
|
20912
20728
|
const content = buf.slice(0, bytesRead).toString("utf-8");
|
|
20913
20729
|
if (!content) return true;
|
|
20914
20730
|
result.push({ path: specPath, content });
|
|
@@ -20924,7 +20740,7 @@ function discoverSpecs(consulted = []) {
|
|
|
20924
20740
|
if (!addSpec(candidate)) break;
|
|
20925
20741
|
}
|
|
20926
20742
|
for (const dir of ["spec", "docs"]) {
|
|
20927
|
-
if (!(0,
|
|
20743
|
+
if (!(0, import_node_fs32.existsSync)(dir)) continue;
|
|
20928
20744
|
try {
|
|
20929
20745
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
20930
20746
|
for (const mdFile of mdFiles) {
|
|
@@ -20939,7 +20755,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
20939
20755
|
if (depth >= maxDepth) return [];
|
|
20940
20756
|
const result = [];
|
|
20941
20757
|
try {
|
|
20942
|
-
const entries = (0,
|
|
20758
|
+
const entries = (0, import_node_fs32.readdirSync)(dir, { withFileTypes: true });
|
|
20943
20759
|
for (const entry of entries) {
|
|
20944
20760
|
const fullPath = (0, import_node_path23.join)(dir, entry.name);
|
|
20945
20761
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -20958,14 +20774,14 @@ function discoverPlans() {
|
|
|
20958
20774
|
const candidates = [];
|
|
20959
20775
|
const seen = /* @__PURE__ */ new Set();
|
|
20960
20776
|
for (const plansDir of [localPlansDir, homePlansDir]) {
|
|
20961
|
-
if (!(0,
|
|
20777
|
+
if (!(0, import_node_fs32.existsSync)(plansDir)) continue;
|
|
20962
20778
|
try {
|
|
20963
|
-
for (const f of (0,
|
|
20779
|
+
for (const f of (0, import_node_fs32.readdirSync)(plansDir)) {
|
|
20964
20780
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
20965
20781
|
seen.add(f);
|
|
20966
20782
|
const fullPath = (0, import_node_path23.join)(plansDir, f);
|
|
20967
20783
|
try {
|
|
20968
|
-
const stat3 = (0,
|
|
20784
|
+
const stat3 = (0, import_node_fs32.statSync)(fullPath);
|
|
20969
20785
|
candidates.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
20970
20786
|
} catch {
|
|
20971
20787
|
}
|
|
@@ -20978,7 +20794,7 @@ function discoverPlans() {
|
|
|
20978
20794
|
for (const entry of candidates.slice(0, MAX_PLAN_FILES)) {
|
|
20979
20795
|
if (entry.size > MAX_PLAN_FILE_BYTES) continue;
|
|
20980
20796
|
try {
|
|
20981
|
-
const content = (0,
|
|
20797
|
+
const content = (0, import_node_fs32.readFileSync)(entry.path, "utf-8");
|
|
20982
20798
|
result.push({ name: entry.name, content });
|
|
20983
20799
|
} catch {
|
|
20984
20800
|
}
|
|
@@ -20993,12 +20809,12 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
20993
20809
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
20994
20810
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
20995
20811
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
20996
|
-
if (!(0,
|
|
20812
|
+
if (!(0, import_node_fs32.existsSync)(path)) continue;
|
|
20997
20813
|
try {
|
|
20998
|
-
const stat3 = (0,
|
|
20814
|
+
const stat3 = (0, import_node_fs32.statSync)(path);
|
|
20999
20815
|
if (stat3.size > MAX_PLAN_FILE_BYTES) continue;
|
|
21000
20816
|
if (totalBytes + stat3.size > MAX_TOTAL_SPEC_BYTES) continue;
|
|
21001
|
-
const content = (0,
|
|
20817
|
+
const content = (0, import_node_fs32.readFileSync)(path, "utf-8");
|
|
21002
20818
|
if (!content) continue;
|
|
21003
20819
|
result.push({ name: path, content });
|
|
21004
20820
|
totalBytes += content.length;
|
|
@@ -21174,7 +20990,7 @@ async function mode(run2) {
|
|
|
21174
20990
|
}
|
|
21175
20991
|
|
|
21176
20992
|
// src/lib/fold.ts
|
|
21177
|
-
var
|
|
20993
|
+
var import_node_fs33 = require("node:fs");
|
|
21178
20994
|
var import_node_path24 = require("node:path");
|
|
21179
20995
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
21180
20996
|
"user",
|
|
@@ -21312,7 +21128,7 @@ function candidateRoots(repoRoot2) {
|
|
|
21312
21128
|
const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
21313
21129
|
const out = [norm];
|
|
21314
21130
|
try {
|
|
21315
|
-
const real =
|
|
21131
|
+
const real = import_node_fs33.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
21316
21132
|
if (real !== norm) out.push(real);
|
|
21317
21133
|
} catch {
|
|
21318
21134
|
}
|
|
@@ -21400,8 +21216,8 @@ function fold(transcriptPath, opts = {}) {
|
|
|
21400
21216
|
}
|
|
21401
21217
|
};
|
|
21402
21218
|
try {
|
|
21403
|
-
if (!(0,
|
|
21404
|
-
ingest((0,
|
|
21219
|
+
if (!(0, import_node_fs33.existsSync)(transcriptPath)) return result;
|
|
21220
|
+
ingest((0, import_node_fs33.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
21405
21221
|
result.coverage.complete = true;
|
|
21406
21222
|
} catch {
|
|
21407
21223
|
return result;
|
|
@@ -21412,19 +21228,19 @@ function fold(transcriptPath, opts = {}) {
|
|
|
21412
21228
|
(0, import_node_path24.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
21413
21229
|
"subagents"
|
|
21414
21230
|
);
|
|
21415
|
-
if ((0,
|
|
21231
|
+
if ((0, import_node_fs33.existsSync)(sidecarDir)) {
|
|
21416
21232
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
21417
21233
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
21418
21234
|
const found = [];
|
|
21419
21235
|
const walk2 = (d, depth) => {
|
|
21420
21236
|
if (depth > 4) return;
|
|
21421
|
-
for (const e of (0,
|
|
21237
|
+
for (const e of (0, import_node_fs33.readdirSync)(d, { withFileTypes: true })) {
|
|
21422
21238
|
const p = (0, import_node_path24.join)(d, e.name);
|
|
21423
21239
|
if (e.isDirectory()) {
|
|
21424
21240
|
walk2(p, depth + 1);
|
|
21425
21241
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
21426
21242
|
try {
|
|
21427
|
-
const st = (0,
|
|
21243
|
+
const st = (0, import_node_fs33.statSync)(p);
|
|
21428
21244
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
21429
21245
|
} catch {
|
|
21430
21246
|
result.coverage.malformed++;
|
|
@@ -21441,7 +21257,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
21441
21257
|
continue;
|
|
21442
21258
|
}
|
|
21443
21259
|
try {
|
|
21444
|
-
ingest((0,
|
|
21260
|
+
ingest((0, import_node_fs33.readFileSync)(f.path, "utf8"), "subagent");
|
|
21445
21261
|
bytes += f.size;
|
|
21446
21262
|
result.coverage.subagentFiles++;
|
|
21447
21263
|
} catch {
|
|
@@ -21476,7 +21292,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
21476
21292
|
}
|
|
21477
21293
|
function classifyUnobserved(path) {
|
|
21478
21294
|
try {
|
|
21479
|
-
const st = (0,
|
|
21295
|
+
const st = (0, import_node_fs33.statSync)(path);
|
|
21480
21296
|
if (!st.isFile()) return "unreadable";
|
|
21481
21297
|
} catch {
|
|
21482
21298
|
return "unreadable";
|
|
@@ -21728,20 +21544,7 @@ async function evidence(run2) {
|
|
|
21728
21544
|
widened_to: allForReview.length
|
|
21729
21545
|
});
|
|
21730
21546
|
}
|
|
21731
|
-
const
|
|
21732
|
-
if (!narrowingIsTrustworthy && recoveredScope.length === 0 && authorshipWasObservable) {
|
|
21733
|
-
logEvent("authored_nothing_reviewable", {
|
|
21734
|
-
touched: (actionSummary?.files_edited?.length ?? 0) + (actionSummary?.files_created?.length ?? 0),
|
|
21735
|
-
candidates: allForReview.length
|
|
21736
|
-
});
|
|
21737
|
-
}
|
|
21738
|
-
const baseForReview = chooseReviewScope({
|
|
21739
|
-
narrowingIsTrustworthy,
|
|
21740
|
-
scopedFiles: scoped.files,
|
|
21741
|
-
recoveredScope,
|
|
21742
|
-
allForReview,
|
|
21743
|
-
authorshipWasObservable
|
|
21744
|
-
});
|
|
21547
|
+
const baseForReview = narrowingIsTrustworthy ? scoped.files : recoveredScope.length > 0 ? recoveredScope : allForReview;
|
|
21745
21548
|
const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
|
|
21746
21549
|
if (!opts.skipStatic && isCodacyAvailable()) {
|
|
21747
21550
|
let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
@@ -21793,20 +21596,20 @@ async function evidence(run2) {
|
|
|
21793
21596
|
}
|
|
21794
21597
|
|
|
21795
21598
|
// src/lib/cache-cleanup.ts
|
|
21796
|
-
var
|
|
21599
|
+
var import_node_fs34 = require("node:fs");
|
|
21797
21600
|
var import_node_path25 = require("node:path");
|
|
21798
21601
|
var CACHE_TTL_DAYS = 7;
|
|
21799
21602
|
function pruneStaleCache() {
|
|
21800
21603
|
try {
|
|
21801
21604
|
const dir = projectPath(CACHE_DIR);
|
|
21802
21605
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
21803
|
-
for (const entry of (0,
|
|
21606
|
+
for (const entry of (0, import_node_fs34.readdirSync)(dir)) {
|
|
21804
21607
|
if (!entry.startsWith("pending-")) continue;
|
|
21805
21608
|
const path = (0, import_node_path25.join)(dir, entry);
|
|
21806
21609
|
try {
|
|
21807
|
-
const stat3 = (0,
|
|
21610
|
+
const stat3 = (0, import_node_fs34.statSync)(path);
|
|
21808
21611
|
if (stat3.mtimeMs < cutoff) {
|
|
21809
|
-
(0,
|
|
21612
|
+
(0, import_node_fs34.unlinkSync)(path);
|
|
21810
21613
|
logEvent("cache_entry_pruned", {
|
|
21811
21614
|
path: entry,
|
|
21812
21615
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -21820,7 +21623,7 @@ function pruneStaleCache() {
|
|
|
21820
21623
|
}
|
|
21821
21624
|
|
|
21822
21625
|
// src/lib/context-files.ts
|
|
21823
|
-
var
|
|
21626
|
+
var import_node_fs35 = require("node:fs");
|
|
21824
21627
|
var import_node_os5 = require("node:os");
|
|
21825
21628
|
var MAX_CONTEXT_FILES = 10;
|
|
21826
21629
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
@@ -21878,7 +21681,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
21878
21681
|
continue;
|
|
21879
21682
|
}
|
|
21880
21683
|
try {
|
|
21881
|
-
const content = (0,
|
|
21684
|
+
const content = (0, import_node_fs35.readFileSync)(safePath, "utf8");
|
|
21882
21685
|
const bytes = Buffer.byteLength(content);
|
|
21883
21686
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
21884
21687
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -21969,7 +21772,7 @@ async function repoContext(run2) {
|
|
|
21969
21772
|
|
|
21970
21773
|
// src/lib/seed-runner.ts
|
|
21971
21774
|
var import_promises14 = require("node:fs/promises");
|
|
21972
|
-
var
|
|
21775
|
+
var import_node_fs36 = require("node:fs");
|
|
21973
21776
|
var import_node_path26 = require("node:path");
|
|
21974
21777
|
var import_yaml4 = __toESM(require_dist());
|
|
21975
21778
|
|
|
@@ -22209,7 +22012,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
22209
22012
|
return fm;
|
|
22210
22013
|
}
|
|
22211
22014
|
async function runSeed(opts) {
|
|
22212
|
-
if (!(0,
|
|
22015
|
+
if (!(0, import_node_fs36.existsSync)(STANDARD_FILE)) {
|
|
22213
22016
|
return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
22214
22017
|
}
|
|
22215
22018
|
let standardDoc;
|
|
@@ -22221,7 +22024,7 @@ async function runSeed(opts) {
|
|
|
22221
22024
|
}
|
|
22222
22025
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
22223
22026
|
let readmeContent;
|
|
22224
|
-
if ((0,
|
|
22027
|
+
if ((0, import_node_fs36.existsSync)("README.md")) {
|
|
22225
22028
|
try {
|
|
22226
22029
|
readmeContent = await (0, import_promises14.readFile)("README.md", "utf-8");
|
|
22227
22030
|
} catch {
|
|
@@ -22229,7 +22032,7 @@ async function runSeed(opts) {
|
|
|
22229
22032
|
}
|
|
22230
22033
|
let claudeMdContent;
|
|
22231
22034
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
22232
|
-
if ((0,
|
|
22035
|
+
if ((0, import_node_fs36.existsSync)(p)) {
|
|
22233
22036
|
try {
|
|
22234
22037
|
claudeMdContent = await (0, import_promises14.readFile)(p, "utf-8");
|
|
22235
22038
|
break;
|
|
@@ -22253,7 +22056,7 @@ async function runSeed(opts) {
|
|
|
22253
22056
|
return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
|
|
22254
22057
|
}
|
|
22255
22058
|
const overviewPath = (0, import_node_path26.join)(MEMORY_DIR, "domain", "project-overview.md");
|
|
22256
|
-
if ((0,
|
|
22059
|
+
if ((0, import_node_fs36.existsSync)(overviewPath) && !opts.force) {
|
|
22257
22060
|
return { created: 0, failed: 0, skipped: "already_seeded", candidates };
|
|
22258
22061
|
}
|
|
22259
22062
|
if (opts.dryRun) {
|
|
@@ -22308,7 +22111,7 @@ async function runSeed(opts) {
|
|
|
22308
22111
|
}
|
|
22309
22112
|
|
|
22310
22113
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
22311
|
-
var
|
|
22114
|
+
var import_node_fs37 = require("node:fs");
|
|
22312
22115
|
var import_node_path27 = require("node:path");
|
|
22313
22116
|
async function memoryManifest(run2) {
|
|
22314
22117
|
const { globals } = run2;
|
|
@@ -22320,8 +22123,8 @@ async function memoryManifest(run2) {
|
|
|
22320
22123
|
try {
|
|
22321
22124
|
await ensureMemoryDir();
|
|
22322
22125
|
const seedMarker = (0, import_node_path27.join)(VERITY_DIR, ".seeded");
|
|
22323
|
-
const hasStandard = (0,
|
|
22324
|
-
const alreadyTried = (0,
|
|
22126
|
+
const hasStandard = (0, import_node_fs37.existsSync)(STANDARD_FILE);
|
|
22127
|
+
const alreadyTried = (0, import_node_fs37.existsSync)(seedMarker);
|
|
22325
22128
|
if (hasStandard && !alreadyTried) {
|
|
22326
22129
|
const preManifest = await buildManifest();
|
|
22327
22130
|
if (preManifest.nodes.length === 0) {
|
|
@@ -22334,7 +22137,7 @@ async function memoryManifest(run2) {
|
|
|
22334
22137
|
dryRun: false
|
|
22335
22138
|
});
|
|
22336
22139
|
if (seedResult.created > 0) {
|
|
22337
|
-
(0,
|
|
22140
|
+
(0, import_node_fs37.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
|
|
22338
22141
|
`);
|
|
22339
22142
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
22340
22143
|
logEvent("auto_seed_ran", {
|
|
@@ -22342,7 +22145,7 @@ async function memoryManifest(run2) {
|
|
|
22342
22145
|
failed: seedResult.failed
|
|
22343
22146
|
});
|
|
22344
22147
|
} else if (seedResult.skipped === "already_seeded") {
|
|
22345
|
-
(0,
|
|
22148
|
+
(0, import_node_fs37.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
22346
22149
|
`);
|
|
22347
22150
|
} else {
|
|
22348
22151
|
logEvent("auto_seed_noop", {
|
|
@@ -22531,7 +22334,7 @@ async function workingMemory(run2) {
|
|
|
22531
22334
|
}
|
|
22532
22335
|
|
|
22533
22336
|
// src/lib/note-budget.ts
|
|
22534
|
-
var
|
|
22337
|
+
var import_node_fs38 = require("node:fs");
|
|
22535
22338
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
22536
22339
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
22537
22340
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -22553,9 +22356,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
22553
22356
|
}
|
|
22554
22357
|
function readAdvisoryEpisode(sessionId) {
|
|
22555
22358
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
22556
|
-
if (!(0,
|
|
22359
|
+
if (!(0, import_node_fs38.existsSync)(file)) return null;
|
|
22557
22360
|
try {
|
|
22558
|
-
const o = JSON.parse((0,
|
|
22361
|
+
const o = JSON.parse((0, import_node_fs38.readFileSync)(file, "utf-8")) ?? {};
|
|
22559
22362
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
22560
22363
|
if (isNaN(delivered)) return null;
|
|
22561
22364
|
return {
|
|
@@ -22569,8 +22372,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
22569
22372
|
}
|
|
22570
22373
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
22571
22374
|
try {
|
|
22572
|
-
(0,
|
|
22573
|
-
(0,
|
|
22375
|
+
(0, import_node_fs38.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
22376
|
+
(0, import_node_fs38.writeFileSync)(
|
|
22574
22377
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
22575
22378
|
JSON.stringify({ v: 1, ...episode })
|
|
22576
22379
|
);
|
|
@@ -22887,14 +22690,14 @@ async function buildRequest(run2) {
|
|
|
22887
22690
|
}
|
|
22888
22691
|
|
|
22889
22692
|
// src/lib/offline.ts
|
|
22890
|
-
var
|
|
22693
|
+
var import_node_fs39 = require("node:fs");
|
|
22891
22694
|
var import_node_crypto11 = require("node:crypto");
|
|
22892
22695
|
function cacheRequest(body) {
|
|
22893
22696
|
try {
|
|
22894
|
-
(0,
|
|
22697
|
+
(0, import_node_fs39.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
22895
22698
|
const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
|
|
22896
22699
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
22897
|
-
(0,
|
|
22700
|
+
(0, import_node_fs39.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
|
|
22898
22701
|
} catch {
|
|
22899
22702
|
}
|
|
22900
22703
|
}
|
|
@@ -23013,7 +22816,7 @@ async function transmit(run2) {
|
|
|
23013
22816
|
}
|
|
23014
22817
|
|
|
23015
22818
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
23016
|
-
var
|
|
22819
|
+
var import_node_fs40 = require("node:fs");
|
|
23017
22820
|
var import_node_path29 = require("node:path");
|
|
23018
22821
|
async function reconcile(run2) {
|
|
23019
22822
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
|
|
@@ -23043,7 +22846,7 @@ async function reconcile(run2) {
|
|
|
23043
22846
|
const st = foldDossier(memorySession.d);
|
|
23044
22847
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
|
|
23045
22848
|
try {
|
|
23046
|
-
const src = (0,
|
|
22849
|
+
const src = (0, import_node_fs40.readFileSync)((0, import_node_path29.join)(repoRoot(), file), "utf8").split("\n");
|
|
23047
22850
|
const at = src[line - 1];
|
|
23048
22851
|
return at === void 0 ? null : lineSha(at);
|
|
23049
22852
|
} catch {
|
|
@@ -23707,10 +23510,6 @@ function registerAnalyzeCommand(program2) {
|
|
|
23707
23510
|
}
|
|
23708
23511
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
23709
23512
|
async function runAnalyze(opts, globals) {
|
|
23710
|
-
if (!verityConfigured()) {
|
|
23711
|
-
(0, import_node_fs43.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
23712
|
-
process.exit(0);
|
|
23713
|
-
}
|
|
23714
23513
|
const run2 = createRun(opts, globals);
|
|
23715
23514
|
installRunEvidence(run2);
|
|
23716
23515
|
for (const [name, phase] of PIPELINE) {
|
|
@@ -23729,6 +23528,7 @@ async function runAnalyze(opts, globals) {
|
|
|
23729
23528
|
}
|
|
23730
23529
|
|
|
23731
23530
|
// src/commands/baseline.ts
|
|
23531
|
+
var import_node_fs41 = require("node:fs");
|
|
23732
23532
|
function registerBaselineCommands(program2) {
|
|
23733
23533
|
const baseline = program2.command("baseline").description("Manage the task-start working-tree baseline");
|
|
23734
23534
|
baseline.command("capture").description("Snapshot the working tree at task start (used by SessionStart hook)").option("--session-id <id>", "Session id (overrides any value from stdin)").option("--source <source>", "Lifecycle hint: startup|resume|clear|compact").action(async (opts) => {
|
|
@@ -23737,16 +23537,7 @@ function registerBaselineCommands(program2) {
|
|
|
23737
23537
|
process.chdir(repoRoot());
|
|
23738
23538
|
} catch {
|
|
23739
23539
|
}
|
|
23740
|
-
if (!
|
|
23741
|
-
const how = isPluginInvocation() ? "Offer to run /verity:setup for the user." : "Offer to run `verity init` (or /verity-setup) for the user.";
|
|
23742
|
-
process.stdout.write(
|
|
23743
|
-
JSON.stringify({
|
|
23744
|
-
hookSpecificOutput: {
|
|
23745
|
-
hookEventName: "SessionStart",
|
|
23746
|
-
additionalContext: `Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
|
|
23747
|
-
}
|
|
23748
|
-
}) + "\n"
|
|
23749
|
-
);
|
|
23540
|
+
if (!(0, import_node_fs41.existsSync)(VERITY_DIR)) {
|
|
23750
23541
|
process.exit(0);
|
|
23751
23542
|
}
|
|
23752
23543
|
let sessionId = opts.sessionId;
|
|
@@ -23762,9 +23553,6 @@ function registerBaselineCommands(program2) {
|
|
|
23762
23553
|
}
|
|
23763
23554
|
}
|
|
23764
23555
|
}
|
|
23765
|
-
if (deferredToPlugin("baseline capture", sessionId ?? process.env.CLAUDE_SESSION_ID ?? null)) {
|
|
23766
|
-
process.exit(0);
|
|
23767
|
-
}
|
|
23768
23556
|
const authForScope = await resolveToken(program2.opts().token);
|
|
23769
23557
|
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
23770
23558
|
const scopeSession = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
|
|
@@ -23789,7 +23577,7 @@ async function readStdin() {
|
|
|
23789
23577
|
}
|
|
23790
23578
|
|
|
23791
23579
|
// src/commands/review.ts
|
|
23792
|
-
var
|
|
23580
|
+
var import_node_fs42 = require("node:fs");
|
|
23793
23581
|
function registerReviewCommand(program2) {
|
|
23794
23582
|
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) => {
|
|
23795
23583
|
const globals = program2.opts();
|
|
@@ -23808,7 +23596,7 @@ async function runReview(opts, globals) {
|
|
|
23808
23596
|
const securityFiles = filterSecurity(allFiles);
|
|
23809
23597
|
let staticResults;
|
|
23810
23598
|
if (isCodacyAvailable()) {
|
|
23811
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
23599
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs42.existsSync)(f) || resolveFile(f) !== null);
|
|
23812
23600
|
staticResults = runCodacyAnalysis(scannable);
|
|
23813
23601
|
} else {
|
|
23814
23602
|
staticResults = {
|
|
@@ -23834,10 +23622,10 @@ async function runReview(opts, globals) {
|
|
|
23834
23622
|
const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
|
|
23835
23623
|
specs = [];
|
|
23836
23624
|
for (const p of specPaths) {
|
|
23837
|
-
if (!(0,
|
|
23625
|
+
if (!(0, import_node_fs42.existsSync)(p)) continue;
|
|
23838
23626
|
try {
|
|
23839
|
-
const { readFileSync:
|
|
23840
|
-
const content =
|
|
23627
|
+
const { readFileSync: readFileSync26 } = await import("node:fs");
|
|
23628
|
+
const content = readFileSync26(p, "utf-8");
|
|
23841
23629
|
specs.push({ path: p, content: content.slice(0, 10240) });
|
|
23842
23630
|
} catch {
|
|
23843
23631
|
}
|
|
@@ -23894,7 +23682,7 @@ async function runReview(opts, globals) {
|
|
|
23894
23682
|
}
|
|
23895
23683
|
|
|
23896
23684
|
// src/commands/guard.ts
|
|
23897
|
-
var
|
|
23685
|
+
var import_node_fs43 = require("node:fs");
|
|
23898
23686
|
var import_node_path30 = require("node:path");
|
|
23899
23687
|
var GUARD_BLOCK_CAP = 2;
|
|
23900
23688
|
var GUARD_ITER_FILE = (0, import_node_path30.join)(VERITY_DIR, ".guard-iteration");
|
|
@@ -23942,7 +23730,7 @@ function readPreToolUseStdin() {
|
|
|
23942
23730
|
}
|
|
23943
23731
|
function readIterMap() {
|
|
23944
23732
|
try {
|
|
23945
|
-
const raw = JSON.parse((0,
|
|
23733
|
+
const raw = JSON.parse((0, import_node_fs43.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
23946
23734
|
if (raw && typeof raw === "object") {
|
|
23947
23735
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
23948
23736
|
return { [raw.moment]: raw.count };
|
|
@@ -23962,10 +23750,10 @@ function readIter(moment) {
|
|
|
23962
23750
|
}
|
|
23963
23751
|
function writeIter(moment, count) {
|
|
23964
23752
|
try {
|
|
23965
|
-
(0,
|
|
23753
|
+
(0, import_node_fs43.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
23966
23754
|
const map = readIterMap();
|
|
23967
23755
|
map[moment] = count;
|
|
23968
|
-
(0,
|
|
23756
|
+
(0, import_node_fs43.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
23969
23757
|
} catch {
|
|
23970
23758
|
}
|
|
23971
23759
|
}
|
|
@@ -23975,16 +23763,16 @@ function resetIter(moment) {
|
|
|
23975
23763
|
if (!(moment in map)) return;
|
|
23976
23764
|
delete map[moment];
|
|
23977
23765
|
if (Object.keys(map).length === 0) {
|
|
23978
|
-
if ((0,
|
|
23766
|
+
if ((0, import_node_fs43.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs43.unlinkSync)(GUARD_ITER_FILE);
|
|
23979
23767
|
} else {
|
|
23980
|
-
(0,
|
|
23981
|
-
(0,
|
|
23768
|
+
(0, import_node_fs43.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
23769
|
+
(0, import_node_fs43.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
23982
23770
|
}
|
|
23983
23771
|
} catch {
|
|
23984
23772
|
}
|
|
23985
23773
|
}
|
|
23986
23774
|
function registerGuardCommand(program2) {
|
|
23987
|
-
program2.command("guard").description("Git-moment gate: review staged/to-push changes before a commit/push (PreToolUse hook)").option("--on <moments>", "Which git moments to gate: commit,push
|
|
23775
|
+
program2.command("guard").description("Git-moment gate: review staged/to-push changes before a commit/push (PreToolUse hook)").option("--on <moments>", "Which git moments to gate: commit,push", "commit,push").option("--json", "Output raw JSON response (debug)").action(async (opts) => {
|
|
23988
23776
|
const globals = program2.opts();
|
|
23989
23777
|
try {
|
|
23990
23778
|
await runGuard(opts, globals);
|
|
@@ -23994,14 +23782,13 @@ function registerGuardCommand(program2) {
|
|
|
23994
23782
|
});
|
|
23995
23783
|
}
|
|
23996
23784
|
function resolveMomentRange(moment, frame, command, on) {
|
|
23997
|
-
return moment === "pre-commit" ? stagedRange(
|
|
23785
|
+
return moment === "pre-commit" ? stagedRange() : resolvePushRange(frame, command, on);
|
|
23998
23786
|
}
|
|
23999
23787
|
function describeRange(range) {
|
|
24000
23788
|
if (range.kind === "staged") return "staged";
|
|
24001
|
-
if (range.kind === "
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
return base ? `${base}..${range.head} via ${range.via}` : `via ${range.via}`;
|
|
23789
|
+
if (range.kind === "nothing" || !range.base) return null;
|
|
23790
|
+
const base = /^[0-9a-f]{40}$/.test(range.base) ? range.base.slice(0, 7) : range.base;
|
|
23791
|
+
return `${base}..${range.head} via ${range.via}`;
|
|
24005
23792
|
}
|
|
24006
23793
|
function matchFlagValue(command, flags) {
|
|
24007
23794
|
const re = new RegExp(`(?<![\\w-])(?:${flags})(?:=|\\s+)('((?:[^'\\\\]|\\\\.)*)'|"((?:[^"\\\\]|\\\\.)*)"|([^\\s'"-][^\\s]*))`);
|
|
@@ -24050,7 +23837,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
|
|
|
24050
23837
|
const securityFiles = filterSecurity(files);
|
|
24051
23838
|
let staticResults;
|
|
24052
23839
|
if (isCodacyAvailable()) {
|
|
24053
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
23840
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs43.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
24054
23841
|
staticResults = runCodacyAnalysis(scannable);
|
|
24055
23842
|
} else {
|
|
24056
23843
|
staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
|
|
@@ -24123,10 +23910,8 @@ function emitAllowNotice(userMsg, agentMsg) {
|
|
|
24123
23910
|
process.exit(0);
|
|
24124
23911
|
}
|
|
24125
23912
|
async function runGuard(opts, globals) {
|
|
24126
|
-
const on =
|
|
24127
|
-
if (on.length === 0) process.exit(0);
|
|
23913
|
+
const on = opts.on.split(",").map((s) => s.trim()).filter((s) => s === "commit" || s === "push");
|
|
24128
23914
|
const { command, cwd, sessionId } = await readPreToolUseStdin();
|
|
24129
|
-
if (deferredToPlugin("guard", sessionId)) process.exit(0);
|
|
24130
23915
|
const moment = classifyCommand(command, on);
|
|
24131
23916
|
if (!moment) process.exit(0);
|
|
24132
23917
|
const verb = moment === "pre-commit" ? "commit" : "push";
|
|
@@ -24189,7 +23974,7 @@ async function runGuard(opts, globals) {
|
|
|
24189
23974
|
upgradeToExcerpts(repoContext2, {
|
|
24190
23975
|
readFile: (rel) => {
|
|
24191
23976
|
try {
|
|
24192
|
-
return (0,
|
|
23977
|
+
return (0, import_node_fs43.readFileSync)((0, import_node_path30.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
|
|
24193
23978
|
} catch {
|
|
24194
23979
|
return null;
|
|
24195
23980
|
}
|
|
@@ -24410,7 +24195,7 @@ function registerIgnoreCommand(program2) {
|
|
|
24410
24195
|
|
|
24411
24196
|
// src/commands/waive.ts
|
|
24412
24197
|
var import_node_crypto12 = require("node:crypto");
|
|
24413
|
-
var
|
|
24198
|
+
var import_node_fs44 = require("node:fs");
|
|
24414
24199
|
function registerWaiveCommand(program2) {
|
|
24415
24200
|
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) => {
|
|
24416
24201
|
const globals = program2.opts();
|
|
@@ -24439,7 +24224,7 @@ function registerWaiveCommand(program2) {
|
|
|
24439
24224
|
if (opts.file) {
|
|
24440
24225
|
body.file = opts.file;
|
|
24441
24226
|
try {
|
|
24442
|
-
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0,
|
|
24227
|
+
body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs44.readFileSync)(opts.file)).digest("hex");
|
|
24443
24228
|
} catch {
|
|
24444
24229
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
24445
24230
|
process.exit(1);
|
|
@@ -24464,7 +24249,7 @@ function registerWaiveCommand(program2) {
|
|
|
24464
24249
|
}
|
|
24465
24250
|
|
|
24466
24251
|
// src/commands/init.ts
|
|
24467
|
-
var
|
|
24252
|
+
var import_node_fs49 = require("node:fs");
|
|
24468
24253
|
var import_promises17 = require("node:fs/promises");
|
|
24469
24254
|
var import_yaml6 = __toESM(require_dist());
|
|
24470
24255
|
var import_node_path33 = require("node:path");
|
|
@@ -24546,7 +24331,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
24546
24331
|
}
|
|
24547
24332
|
|
|
24548
24333
|
// src/commands/doctor.ts
|
|
24549
|
-
var
|
|
24334
|
+
var import_node_fs46 = require("node:fs");
|
|
24550
24335
|
|
|
24551
24336
|
// src/lib/prereqs.ts
|
|
24552
24337
|
var import_node_child_process13 = require("node:child_process");
|
|
@@ -24666,7 +24451,7 @@ var import_promises15 = require("node:fs/promises");
|
|
|
24666
24451
|
|
|
24667
24452
|
// src/lib/gitignore.ts
|
|
24668
24453
|
var import_node_child_process14 = require("node:child_process");
|
|
24669
|
-
var
|
|
24454
|
+
var import_node_fs45 = require("node:fs");
|
|
24670
24455
|
var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
|
|
24671
24456
|
var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
|
|
24672
24457
|
var VERITY_GITIGNORE_BLOCK = [
|
|
@@ -24699,7 +24484,7 @@ function semanticsHold() {
|
|
|
24699
24484
|
function ensureVerityGitignore() {
|
|
24700
24485
|
let content = "";
|
|
24701
24486
|
try {
|
|
24702
|
-
content = (0,
|
|
24487
|
+
content = (0, import_node_fs45.readFileSync)(".gitignore", "utf-8");
|
|
24703
24488
|
} catch {
|
|
24704
24489
|
}
|
|
24705
24490
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -24720,7 +24505,7 @@ function ensureVerityGitignore() {
|
|
|
24720
24505
|
const sep2 = next === "" ? "" : next.endsWith("\n") ? "\n" : "\n\n";
|
|
24721
24506
|
next = next + sep2 + VERITY_GITIGNORE_BLOCK;
|
|
24722
24507
|
}
|
|
24723
|
-
(0,
|
|
24508
|
+
(0, import_node_fs45.writeFileSync)(".gitignore", next);
|
|
24724
24509
|
return verified(needsRepair ? "repaired" : "added");
|
|
24725
24510
|
} catch {
|
|
24726
24511
|
return "failed";
|
|
@@ -24847,11 +24632,11 @@ async function buildReport() {
|
|
|
24847
24632
|
const state = await readSetupState();
|
|
24848
24633
|
const hooks = await checkAllVerityHooks();
|
|
24849
24634
|
const telemetry = await checkTelemetry();
|
|
24850
|
-
const hasConfig = (0,
|
|
24635
|
+
const hasConfig = (0, import_node_fs46.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
24851
24636
|
const artifacts = {
|
|
24852
|
-
standard: (0,
|
|
24637
|
+
standard: (0, import_node_fs46.existsSync)(projectPath(STANDARD_FILE)),
|
|
24853
24638
|
analysisConfig: hasConfig,
|
|
24854
|
-
verityMd: (0,
|
|
24639
|
+
verityMd: (0, import_node_fs46.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
24855
24640
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
24856
24641
|
};
|
|
24857
24642
|
const next = [];
|
|
@@ -24945,7 +24730,7 @@ function registerDoctorCommand(program2) {
|
|
|
24945
24730
|
}
|
|
24946
24731
|
|
|
24947
24732
|
// src/commands/migrate.ts
|
|
24948
|
-
var
|
|
24733
|
+
var import_node_fs47 = require("node:fs");
|
|
24949
24734
|
var import_node_path31 = require("node:path");
|
|
24950
24735
|
var import_node_child_process15 = require("node:child_process");
|
|
24951
24736
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
@@ -24985,10 +24770,10 @@ async function runMigration(opts = {}) {
|
|
|
24985
24770
|
function migrateProjectDir(root, actions) {
|
|
24986
24771
|
const gateDir = (0, import_node_path31.join)(root, ".gate");
|
|
24987
24772
|
const verityDir = (0, import_node_path31.join)(root, ".verity");
|
|
24988
|
-
if ((0,
|
|
24773
|
+
if ((0, import_node_fs47.existsSync)(gateDir) && !(0, import_node_fs47.existsSync)(verityDir)) {
|
|
24989
24774
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
24990
24775
|
}
|
|
24991
|
-
if ((0,
|
|
24776
|
+
if ((0, import_node_fs47.existsSync)(gateDir) && (0, import_node_fs47.existsSync)(verityDir)) {
|
|
24992
24777
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
24993
24778
|
}
|
|
24994
24779
|
return false;
|
|
@@ -25009,13 +24794,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
25009
24794
|
}
|
|
25010
24795
|
}
|
|
25011
24796
|
if (moved) {
|
|
25012
|
-
if ((0,
|
|
24797
|
+
if ((0, import_node_fs47.existsSync)(gateDir)) {
|
|
25013
24798
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
25014
24799
|
if (carried > 0) {
|
|
25015
24800
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
25016
24801
|
}
|
|
25017
24802
|
try {
|
|
25018
|
-
(0,
|
|
24803
|
+
(0, import_node_fs47.rmSync)(gateDir, { recursive: true, force: true });
|
|
25019
24804
|
} catch {
|
|
25020
24805
|
}
|
|
25021
24806
|
}
|
|
@@ -25031,7 +24816,7 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
25031
24816
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
25032
24817
|
}
|
|
25033
24818
|
try {
|
|
25034
|
-
(0,
|
|
24819
|
+
(0, import_node_fs47.rmSync)(gateDir, { recursive: true, force: true });
|
|
25035
24820
|
} catch {
|
|
25036
24821
|
}
|
|
25037
24822
|
return carried > 0;
|
|
@@ -25040,9 +24825,9 @@ function migrateGlobalCredentials(home, actions) {
|
|
|
25040
24825
|
if (!home) return;
|
|
25041
24826
|
const gateCreds = (0, import_node_path31.join)(home, ".gate", "credentials");
|
|
25042
24827
|
const verityCreds = (0, import_node_path31.join)(home, ".verity", "credentials");
|
|
25043
|
-
if (!(0,
|
|
25044
|
-
if (!(0,
|
|
25045
|
-
(0,
|
|
24828
|
+
if (!(0, import_node_fs47.existsSync)(gateCreds)) return;
|
|
24829
|
+
if (!(0, import_node_fs47.existsSync)(verityCreds)) {
|
|
24830
|
+
(0, import_node_fs47.mkdirSync)((0, import_node_path31.join)(home, ".verity"), { recursive: true });
|
|
25046
24831
|
moveFile(gateCreds, verityCreds);
|
|
25047
24832
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
25048
24833
|
return;
|
|
@@ -25065,7 +24850,7 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
25065
24850
|
}
|
|
25066
24851
|
async function migrateClaudeMd(root, actions) {
|
|
25067
24852
|
const claudeMd = (0, import_node_path31.join)(root, "CLAUDE.md");
|
|
25068
|
-
const hadLegacyBlock = (0,
|
|
24853
|
+
const hadLegacyBlock = (0, import_node_fs47.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
25069
24854
|
if (!hadLegacyBlock) return;
|
|
25070
24855
|
try {
|
|
25071
24856
|
await ensureClaudeMdPointer(root);
|
|
@@ -25077,7 +24862,7 @@ async function migrateClaudeMd(root, actions) {
|
|
|
25077
24862
|
function migrateStandardFile(root, actions) {
|
|
25078
24863
|
const gateMd = (0, import_node_path31.join)(root, "GATE.md");
|
|
25079
24864
|
const verityMd = (0, import_node_path31.join)(root, "VERITY.md");
|
|
25080
|
-
if (!(0,
|
|
24865
|
+
if (!(0, import_node_fs47.existsSync)(gateMd) || (0, import_node_fs47.existsSync)(verityMd)) return;
|
|
25081
24866
|
let moved = false;
|
|
25082
24867
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
25083
24868
|
try {
|
|
@@ -25089,12 +24874,12 @@ function migrateStandardFile(root, actions) {
|
|
|
25089
24874
|
if (!moved) moveFile(gateMd, verityMd);
|
|
25090
24875
|
const content = readFileSyncSafe(verityMd);
|
|
25091
24876
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
25092
|
-
if (refreshed !== content) (0,
|
|
24877
|
+
if (refreshed !== content) (0, import_node_fs47.writeFileSync)(verityMd, refreshed);
|
|
25093
24878
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
25094
24879
|
}
|
|
25095
24880
|
async function migrateTelemetryHeaders(root, actions) {
|
|
25096
24881
|
const file = (0, import_node_path31.join)(root, ".claude", "settings.local.json");
|
|
25097
|
-
if (!(0,
|
|
24882
|
+
if (!(0, import_node_fs47.existsSync)(file)) return;
|
|
25098
24883
|
let settings;
|
|
25099
24884
|
try {
|
|
25100
24885
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -25142,14 +24927,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
25142
24927
|
}
|
|
25143
24928
|
if (toAppend.length > 0) {
|
|
25144
24929
|
const sep2 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
25145
|
-
(0,
|
|
24930
|
+
(0, import_node_fs47.writeFileSync)(verityCreds, verityContent + sep2 + toAppend.join("\n") + "\n");
|
|
25146
24931
|
}
|
|
25147
|
-
(0,
|
|
24932
|
+
(0, import_node_fs47.rmSync)(gateCreds, { force: true });
|
|
25148
24933
|
return toAppend.length;
|
|
25149
24934
|
}
|
|
25150
24935
|
function readFileSyncSafe(path) {
|
|
25151
24936
|
try {
|
|
25152
|
-
return (0,
|
|
24937
|
+
return (0, import_node_fs47.readFileSync)(path, "utf-8");
|
|
25153
24938
|
} catch {
|
|
25154
24939
|
return "";
|
|
25155
24940
|
}
|
|
@@ -25164,35 +24949,35 @@ function hasStagedChanges(root) {
|
|
|
25164
24949
|
}
|
|
25165
24950
|
function moveDir(from, to) {
|
|
25166
24951
|
try {
|
|
25167
|
-
(0,
|
|
24952
|
+
(0, import_node_fs47.renameSync)(from, to);
|
|
25168
24953
|
} catch (err) {
|
|
25169
24954
|
if (err.code !== "EXDEV") throw err;
|
|
25170
|
-
(0,
|
|
25171
|
-
(0,
|
|
24955
|
+
(0, import_node_fs47.cpSync)(from, to, { recursive: true });
|
|
24956
|
+
(0, import_node_fs47.rmSync)(from, { recursive: true, force: true });
|
|
25172
24957
|
}
|
|
25173
24958
|
}
|
|
25174
24959
|
function moveFile(from, to) {
|
|
25175
24960
|
try {
|
|
25176
|
-
(0,
|
|
24961
|
+
(0, import_node_fs47.renameSync)(from, to);
|
|
25177
24962
|
} catch (err) {
|
|
25178
24963
|
if (err.code !== "EXDEV") throw err;
|
|
25179
|
-
(0,
|
|
25180
|
-
(0,
|
|
24964
|
+
(0, import_node_fs47.cpSync)(from, to);
|
|
24965
|
+
(0, import_node_fs47.rmSync)(from, { force: true });
|
|
25181
24966
|
}
|
|
25182
24967
|
}
|
|
25183
24968
|
function carryLegacyContents(gateDir, verityDir) {
|
|
25184
24969
|
let copied = 0;
|
|
25185
24970
|
const walk2 = (relDir) => {
|
|
25186
24971
|
const srcDir = (0, import_node_path31.join)(gateDir, relDir);
|
|
25187
|
-
for (const entry of (0,
|
|
24972
|
+
for (const entry of (0, import_node_fs47.readdirSync)(srcDir)) {
|
|
25188
24973
|
const rel = relDir ? (0, import_node_path31.join)(relDir, entry) : entry;
|
|
25189
24974
|
const src = (0, import_node_path31.join)(gateDir, rel);
|
|
25190
24975
|
const dest = (0, import_node_path31.join)(verityDir, rel);
|
|
25191
|
-
if ((0,
|
|
24976
|
+
if ((0, import_node_fs47.statSync)(src).isDirectory()) {
|
|
25192
24977
|
walk2(rel);
|
|
25193
|
-
} else if (!(0,
|
|
25194
|
-
(0,
|
|
25195
|
-
(0,
|
|
24978
|
+
} else if (!(0, import_node_fs47.existsSync)(dest)) {
|
|
24979
|
+
(0, import_node_fs47.mkdirSync)((0, import_node_path31.dirname)(dest), { recursive: true });
|
|
24980
|
+
(0, import_node_fs47.cpSync)(src, dest);
|
|
25196
24981
|
copied++;
|
|
25197
24982
|
}
|
|
25198
24983
|
}
|
|
@@ -25203,20 +24988,20 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
25203
24988
|
async function needsMigration(root = repoRoot()) {
|
|
25204
24989
|
const gateDir = (0, import_node_path31.join)(root, ".gate");
|
|
25205
24990
|
const verityDir = (0, import_node_path31.join)(root, ".verity");
|
|
25206
|
-
if ((0,
|
|
25207
|
-
if ((0,
|
|
25208
|
-
if ((0,
|
|
24991
|
+
if ((0, import_node_fs47.existsSync)(gateDir) && !(0, import_node_fs47.existsSync)(verityDir)) return true;
|
|
24992
|
+
if ((0, import_node_fs47.existsSync)(gateDir) && (0, import_node_fs47.existsSync)(verityDir)) {
|
|
24993
|
+
if ((0, import_node_fs47.existsSync)((0, import_node_path31.join)(gateDir, "credentials")) && !(0, import_node_fs47.existsSync)((0, import_node_path31.join)(verityDir, "credentials"))) {
|
|
25209
24994
|
return true;
|
|
25210
24995
|
}
|
|
25211
|
-
if ((0,
|
|
24996
|
+
if ((0, import_node_fs47.existsSync)((0, import_node_path31.join)(gateDir, "memory")) && !(0, import_node_fs47.existsSync)((0, import_node_path31.join)(verityDir, "memory"))) {
|
|
25212
24997
|
return true;
|
|
25213
24998
|
}
|
|
25214
24999
|
}
|
|
25215
25000
|
const claudeMd = (0, import_node_path31.join)(root, "CLAUDE.md");
|
|
25216
|
-
if ((0,
|
|
25001
|
+
if ((0, import_node_fs47.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
25217
25002
|
return true;
|
|
25218
25003
|
}
|
|
25219
|
-
if ((0,
|
|
25004
|
+
if ((0, import_node_fs47.existsSync)((0, import_node_path31.join)(root, "GATE.md")) && !(0, import_node_fs47.existsSync)((0, import_node_path31.join)(root, "VERITY.md"))) {
|
|
25220
25005
|
return true;
|
|
25221
25006
|
}
|
|
25222
25007
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -25491,7 +25276,7 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
25491
25276
|
}
|
|
25492
25277
|
|
|
25493
25278
|
// src/lib/remote-config.ts
|
|
25494
|
-
var
|
|
25279
|
+
var import_node_fs48 = require("node:fs");
|
|
25495
25280
|
var import_promises16 = require("node:fs/promises");
|
|
25496
25281
|
var import_node_path32 = require("node:path");
|
|
25497
25282
|
var import_yaml5 = __toESM(require_dist());
|
|
@@ -25538,7 +25323,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
25538
25323
|
written.push(STANDARD_FILE);
|
|
25539
25324
|
if (rider !== null) {
|
|
25540
25325
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
25541
|
-
if (!(0,
|
|
25326
|
+
if (!(0, import_node_fs48.existsSync)(localIgnore)) {
|
|
25542
25327
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
25543
25328
|
written.push(VERITYIGNORE_FILE);
|
|
25544
25329
|
} else {
|
|
@@ -25696,7 +25481,7 @@ function resolveDataDir2() {
|
|
|
25696
25481
|
// local dev: running from repo root
|
|
25697
25482
|
];
|
|
25698
25483
|
for (const candidate of candidates) {
|
|
25699
|
-
if ((0,
|
|
25484
|
+
if ((0, import_node_fs49.existsSync)((0, import_node_path33.join)(candidate, "skills"))) {
|
|
25700
25485
|
return candidate;
|
|
25701
25486
|
}
|
|
25702
25487
|
}
|
|
@@ -25712,7 +25497,7 @@ async function skillIsCurrent(src, dest) {
|
|
|
25712
25497
|
const list2 = (dir) => {
|
|
25713
25498
|
const out = [];
|
|
25714
25499
|
const walk2 = (d, prefix) => {
|
|
25715
|
-
for (const e of (0,
|
|
25500
|
+
for (const e of (0, import_node_fs49.readdirSync)(d, { withFileTypes: true })) {
|
|
25716
25501
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
25717
25502
|
if (e.isDirectory()) walk2((0, import_node_path33.join)(d, e.name), rel);
|
|
25718
25503
|
else if (e.isFile()) out.push(rel);
|
|
@@ -25904,7 +25689,7 @@ async function synthesizeLocally(opts) {
|
|
|
25904
25689
|
async function healStaleAnalysisConfig(globals) {
|
|
25905
25690
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
25906
25691
|
const standardPath = projectPath(STANDARD_FILE);
|
|
25907
|
-
if (!(0,
|
|
25692
|
+
if (!(0, import_node_fs49.existsSync)(configPath) || !(0, import_node_fs49.existsSync)(standardPath)) return;
|
|
25908
25693
|
const validation = validatePatternIds();
|
|
25909
25694
|
if (validation.status !== "invalid") return;
|
|
25910
25695
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -25998,125 +25783,14 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
25998
25783
|
}
|
|
25999
25784
|
await reportPhaseTwo(startedAt);
|
|
26000
25785
|
}
|
|
26001
|
-
async function installSkills(force, step) {
|
|
26002
|
-
step("Installing skills");
|
|
26003
|
-
const dataDir = resolveDataDir2();
|
|
26004
|
-
const skillsSource = (0, import_node_path33.join)(dataDir, "skills");
|
|
26005
|
-
const skillsDest = ".claude/skills";
|
|
26006
|
-
let skillsInstalled = 0;
|
|
26007
|
-
for (const skill of SKILLS) {
|
|
26008
|
-
const src = (0, import_node_path33.join)(skillsSource, skill);
|
|
26009
|
-
const dest = (0, import_node_path33.join)(skillsDest, skill);
|
|
26010
|
-
if (!(0, import_node_fs51.existsSync)(src)) {
|
|
26011
|
-
printWarn(` Skill data not found: ${skill}`);
|
|
26012
|
-
continue;
|
|
26013
|
-
}
|
|
26014
|
-
if ((0, import_node_fs51.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
26015
|
-
skillsInstalled++;
|
|
26016
|
-
continue;
|
|
26017
|
-
}
|
|
26018
|
-
await copyDir(src, dest);
|
|
26019
|
-
skillsInstalled++;
|
|
26020
|
-
}
|
|
26021
|
-
printInfo(` ${skillsInstalled}/${SKILLS.length} skills installed to .claude/skills/ \u2713`);
|
|
26022
|
-
}
|
|
26023
|
-
async function adoptPluginWiring(gitMoments, moments) {
|
|
26024
|
-
const settings = await readSettings();
|
|
26025
|
-
const stripped = removeVerityHooks(settings);
|
|
26026
|
-
const hadAny = JSON.stringify(settings.hooks ?? {}) !== JSON.stringify(stripped.hooks ?? {});
|
|
26027
|
-
if (hadAny) {
|
|
26028
|
-
await writeSettings(stripped);
|
|
26029
|
-
printInfo(" Removed this project's Verity hooks from .claude/settings.json \u2713");
|
|
26030
|
-
printInfo(" The plugin wires them now, so each turn is reviewed once.");
|
|
26031
|
-
} else {
|
|
26032
|
-
printInfo(" Wired by the Verity plugin \u2014 nothing to reconcile here \u2713");
|
|
26033
|
-
}
|
|
26034
|
-
printInfo(` Pre-commit gate: ${gitMoments.includes("commit") ? "on" : "off"}`);
|
|
26035
|
-
printInfo(` Pre-push/PR gate: ${gitMoments.includes("push") ? "on" : "off"}`);
|
|
26036
|
-
printInfo(" Stop + intent + baseline + compact + session-end: always on \u2713");
|
|
26037
|
-
if (!moments.includes("stop")) {
|
|
26038
|
-
printWarn(" Turning the Stop review off is not yet supported under the plugin \u2014 it stays on.");
|
|
26039
|
-
}
|
|
26040
|
-
}
|
|
26041
|
-
async function reconcileOwnWiring(moments) {
|
|
26042
|
-
await applyMomentSelection(moments);
|
|
26043
|
-
const hookStatus = await checkAllVerityHooks();
|
|
26044
|
-
printInfo(` Stop (verity analyze): ${hookStatus.stop ? "on" : "off"}`);
|
|
26045
|
-
printInfo(` Pre-commit gate: ${hookStatus.guardOn.includes("commit") ? "on" : "off"}`);
|
|
26046
|
-
printInfo(` Pre-push/PR gate: ${hookStatus.guardOn.includes("push") ? "on" : "off"}`);
|
|
26047
|
-
printInfo(" Intent + baseline + compact + session-end: always on \u2713");
|
|
26048
|
-
if (!hookStatus.stop && hookStatus.guardOn.length === 0) {
|
|
26049
|
-
printWarn(" No analysis moment is active \u2014 code changes will NOT be reviewed.");
|
|
26050
|
-
printWarn(" Enable one: verity hooks install --moments stop");
|
|
26051
|
-
}
|
|
26052
|
-
}
|
|
26053
|
-
async function checkPrerequisites(step) {
|
|
26054
|
-
step("Checking prerequisites");
|
|
26055
|
-
const prereqs = await checkPrereqs({ install: true });
|
|
26056
|
-
for (const c of prereqs.checks) {
|
|
26057
|
-
if (c.status === "ok") {
|
|
26058
|
-
if (c.justInstalled) continue;
|
|
26059
|
-
printInfo(` ${c.label} ${c.detail} \u2713`);
|
|
26060
|
-
} else {
|
|
26061
|
-
printWarn(` ${c.label}: ${c.detail}`);
|
|
26062
|
-
if (c.remedy) printWarn(` ${c.remedy}`);
|
|
26063
|
-
}
|
|
26064
|
-
}
|
|
26065
|
-
if (prereqs.blocked) {
|
|
26066
|
-
printError("A required prerequisite is missing \u2014 cannot continue.");
|
|
26067
|
-
process.exit(1);
|
|
26068
|
-
}
|
|
26069
|
-
return prereqs.checks.some((c) => c.id === "claude" && c.status === "ok");
|
|
26070
|
-
}
|
|
26071
|
-
async function scaffoldProject(step, defaultsOnly) {
|
|
26072
|
-
step("Knowledge base, .gitignore and CLAUDE.md");
|
|
26073
|
-
await (0, import_promises17.mkdir)(VERITY_DIR, { recursive: true });
|
|
26074
|
-
await ensureMemoryDir();
|
|
26075
|
-
const ignoreResult = ensureVerityGitignore();
|
|
26076
|
-
if (ignoreResult === "failed") {
|
|
26077
|
-
printWarn(" .gitignore: could not write the Verity block \u2014 add it manually");
|
|
26078
|
-
printWarn(" (.verity/ holds copies of analyzed files, including any secret the gate flagged)");
|
|
26079
|
-
} else if (ignoreResult === "conflict") {
|
|
26080
|
-
printWarn(" .gitignore: the Verity block is in place but git still ignores .verity/standard.yaml");
|
|
26081
|
-
printWarn(" Something outside this file covers it \u2014 a global (~/.gitignore) or nested");
|
|
26082
|
-
printWarn(" .gitignore, or a pattern we do not recognise. Check: git check-ignore -v .verity/standard.yaml");
|
|
26083
|
-
printWarn(" Until it is fixed, the Standard and the knowledge graph cannot be committed.");
|
|
26084
|
-
} else if (ignoreResult === "repaired") {
|
|
26085
|
-
printInfo(" .gitignore: rewrote `.verity/` to `.verity/*` so the standard stays committable \u2713");
|
|
26086
|
-
} else {
|
|
26087
|
-
printInfo(` .gitignore: Verity block ${ignoreResult === "added" ? "added" : "already covered"} \u2713`);
|
|
26088
|
-
}
|
|
26089
|
-
const tracked = committedVerityState();
|
|
26090
|
-
if (tracked.length > 0) {
|
|
26091
|
-
printWarn(` ${tracked.length} Verity state file(s) are tracked in git (e.g. ${tracked[0]}).`);
|
|
26092
|
-
const untrack = defaultsOnly ? false : await promptYes(" Untrack them now (files stay on disk)? [Y/n] ", { nonInteractive: false });
|
|
26093
|
-
if (untrack) {
|
|
26094
|
-
const result = untrackVerityState();
|
|
26095
|
-
if (result === "untracked") printInfo(" Untracked (staged) \u2014 commit to finish \u2713");
|
|
26096
|
-
else if (result === "failed") printWarn(' Could not untrack \u2014 run "git rm -r --cached .verity" manually');
|
|
26097
|
-
} else {
|
|
26098
|
-
printWarn(" Left tracked. Fix with: git rm -r --cached .verity && git add .verity/standard.yaml .verity/memory");
|
|
26099
|
-
}
|
|
26100
|
-
}
|
|
26101
|
-
try {
|
|
26102
|
-
await ensureClaudeMdPointer();
|
|
26103
|
-
printInfo(" CLAUDE.md instructions \u2713");
|
|
26104
|
-
} catch (err) {
|
|
26105
|
-
printWarn(` Could not update CLAUDE.md: ${err.message}`);
|
|
26106
|
-
}
|
|
26107
|
-
}
|
|
26108
25786
|
function registerInitCommand(program2) {
|
|
26109
|
-
program2.command("init").alias("setup").description("Set up Verity in the current project (asks the setup questions, then hands off to /verity-setup)").option("--force", "Reinstall the skills even when they are already up to date (hooks are always reconciled)").option("-y, --yes", "Take the recommended answer for every question (no prompts)").option("--no-setup", "Skip the /verity-setup handoff at the end").option(
|
|
26110
|
-
"--plugin-mode",
|
|
26111
|
-
"The Claude Code plugin owns the skills and hooks: install neither, and remove any this project already has"
|
|
26112
|
-
).option("--no-adopt", "Don't offer this repository's existing Standard from the service; synthesize a new one").action(async (opts) => {
|
|
25787
|
+
program2.command("init").alias("setup").description("Set up Verity in the current project (asks the setup questions, then hands off to /verity-setup)").option("--force", "Reinstall the skills even when they are already up to date (hooks are always reconciled)").option("-y, --yes", "Take the recommended answer for every question (no prompts)").option("--no-setup", "Skip the /verity-setup handoff at the end").option("--no-adopt", "Don't offer this repository's existing Standard from the service; synthesize a new one").action(async (opts) => {
|
|
26113
25788
|
const force = opts.force ?? false;
|
|
26114
25789
|
const wantsHandoff = opts.setup !== false;
|
|
26115
25790
|
const wantsAdopt = opts.adopt !== false;
|
|
26116
25791
|
const defaultsOnly = (opts.yes ?? false) || !interactive();
|
|
26117
|
-
const pluginMode = opts.pluginMode ?? pluginActiveHere();
|
|
26118
25792
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
26119
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
25793
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs49.existsSync)(m));
|
|
26120
25794
|
if (!isProject) {
|
|
26121
25795
|
printError("No project detected in the current directory.");
|
|
26122
25796
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -26147,13 +25821,43 @@ function registerInitCommand(program2) {
|
|
|
26147
25821
|
}
|
|
26148
25822
|
console.log("");
|
|
26149
25823
|
}
|
|
26150
|
-
|
|
25824
|
+
step("Checking prerequisites");
|
|
25825
|
+
const prereqs = await checkPrereqs({ install: true });
|
|
25826
|
+
for (const c of prereqs.checks) {
|
|
25827
|
+
if (c.status === "ok") {
|
|
25828
|
+
if (c.justInstalled) continue;
|
|
25829
|
+
printInfo(` ${c.label} ${c.detail} \u2713`);
|
|
25830
|
+
} else {
|
|
25831
|
+
printWarn(` ${c.label}: ${c.detail}`);
|
|
25832
|
+
if (c.remedy) printWarn(` ${c.remedy}`);
|
|
25833
|
+
}
|
|
25834
|
+
}
|
|
25835
|
+
if (prereqs.blocked) {
|
|
25836
|
+
printError("A required prerequisite is missing \u2014 cannot continue.");
|
|
25837
|
+
process.exit(1);
|
|
25838
|
+
}
|
|
25839
|
+
const claudeInstalled = prereqs.checks.some((c) => c.id === "claude" && c.status === "ok");
|
|
26151
25840
|
console.log("");
|
|
26152
|
-
|
|
26153
|
-
|
|
26154
|
-
|
|
26155
|
-
|
|
25841
|
+
step("Installing skills");
|
|
25842
|
+
const dataDir = resolveDataDir2();
|
|
25843
|
+
const skillsSource = (0, import_node_path33.join)(dataDir, "skills");
|
|
25844
|
+
const skillsDest = ".claude/skills";
|
|
25845
|
+
let skillsInstalled = 0;
|
|
25846
|
+
for (const skill of SKILLS) {
|
|
25847
|
+
const src = (0, import_node_path33.join)(skillsSource, skill);
|
|
25848
|
+
const dest = (0, import_node_path33.join)(skillsDest, skill);
|
|
25849
|
+
if (!(0, import_node_fs49.existsSync)(src)) {
|
|
25850
|
+
printWarn(` Skill data not found: ${skill}`);
|
|
25851
|
+
continue;
|
|
25852
|
+
}
|
|
25853
|
+
if ((0, import_node_fs49.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
25854
|
+
skillsInstalled++;
|
|
25855
|
+
continue;
|
|
25856
|
+
}
|
|
25857
|
+
await copyDir(src, dest);
|
|
25858
|
+
skillsInstalled++;
|
|
26156
25859
|
}
|
|
25860
|
+
printInfo(` ${skillsInstalled}/${SKILLS.length} skills installed to .claude/skills/ \u2713`);
|
|
26157
25861
|
step(defaultsOnly ? "Setup answers (defaults)" : "Your setup answers");
|
|
26158
25862
|
const previous = await readSetupState();
|
|
26159
25863
|
const answers = await askSetupQuestions(defaultsOnly, previous);
|
|
@@ -26161,20 +25865,54 @@ function registerInitCommand(program2) {
|
|
|
26161
25865
|
if (defaultsOnly) {
|
|
26162
25866
|
printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
|
|
26163
25867
|
}
|
|
26164
|
-
|
|
25868
|
+
step("Knowledge base, .gitignore and CLAUDE.md");
|
|
25869
|
+
await (0, import_promises17.mkdir)(VERITY_DIR, { recursive: true });
|
|
25870
|
+
await ensureMemoryDir();
|
|
25871
|
+
const ignoreResult = ensureVerityGitignore();
|
|
25872
|
+
if (ignoreResult === "failed") {
|
|
25873
|
+
printWarn(" .gitignore: could not write the Verity block \u2014 add it manually");
|
|
25874
|
+
printWarn(" (.verity/ holds copies of analyzed files, including any secret the gate flagged)");
|
|
25875
|
+
} else if (ignoreResult === "conflict") {
|
|
25876
|
+
printWarn(" .gitignore: the Verity block is in place but git still ignores .verity/standard.yaml");
|
|
25877
|
+
printWarn(" Something outside this file covers it \u2014 a global (~/.gitignore) or nested");
|
|
25878
|
+
printWarn(" .gitignore, or a pattern we do not recognise. Check: git check-ignore -v .verity/standard.yaml");
|
|
25879
|
+
printWarn(" Until it is fixed, the Standard and the knowledge graph cannot be committed.");
|
|
25880
|
+
} else if (ignoreResult === "repaired") {
|
|
25881
|
+
printInfo(" .gitignore: rewrote `.verity/` to `.verity/*` so the standard stays committable \u2713");
|
|
25882
|
+
} else {
|
|
25883
|
+
printInfo(` .gitignore: Verity block ${ignoreResult === "added" ? "added" : "already covered"} \u2713`);
|
|
25884
|
+
}
|
|
25885
|
+
const tracked = committedVerityState();
|
|
25886
|
+
if (tracked.length > 0) {
|
|
25887
|
+
printWarn(` ${tracked.length} Verity state file(s) are tracked in git (e.g. ${tracked[0]}).`);
|
|
25888
|
+
const untrack = defaultsOnly ? false : await promptYes(" Untrack them now (files stay on disk)? [Y/n] ", { nonInteractive: false });
|
|
25889
|
+
if (untrack) {
|
|
25890
|
+
const result = untrackVerityState();
|
|
25891
|
+
if (result === "untracked") printInfo(" Untracked (staged) \u2014 commit to finish \u2713");
|
|
25892
|
+
else if (result === "failed") printWarn(' Could not untrack \u2014 run "git rm -r --cached .verity" manually');
|
|
25893
|
+
} else {
|
|
25894
|
+
printWarn(" Left tracked. Fix with: git rm -r --cached .verity && git add .verity/standard.yaml .verity/memory");
|
|
25895
|
+
}
|
|
25896
|
+
}
|
|
25897
|
+
try {
|
|
25898
|
+
await ensureClaudeMdPointer();
|
|
25899
|
+
printInfo(" CLAUDE.md instructions \u2713");
|
|
25900
|
+
} catch (err) {
|
|
25901
|
+
printWarn(` Could not update CLAUDE.md: ${err.message}`);
|
|
25902
|
+
}
|
|
26165
25903
|
const globalVerityDir = (0, import_node_path33.join)(process.env.HOME ?? "", ".verity");
|
|
26166
25904
|
await (0, import_promises17.mkdir)(globalVerityDir, { recursive: true });
|
|
26167
25905
|
console.log("");
|
|
26168
25906
|
step("Wiring Claude Code hooks");
|
|
26169
|
-
|
|
26170
|
-
|
|
26171
|
-
|
|
26172
|
-
|
|
26173
|
-
|
|
26174
|
-
|
|
26175
|
-
|
|
26176
|
-
|
|
26177
|
-
|
|
25907
|
+
await applyMomentSelection(moments);
|
|
25908
|
+
const hookStatus = await checkAllVerityHooks();
|
|
25909
|
+
printInfo(` Stop (verity analyze): ${hookStatus.stop ? "on" : "off"}`);
|
|
25910
|
+
printInfo(` Pre-commit gate: ${hookStatus.guardOn.includes("commit") ? "on" : "off"}`);
|
|
25911
|
+
printInfo(` Pre-push/PR gate: ${hookStatus.guardOn.includes("push") ? "on" : "off"}`);
|
|
25912
|
+
printInfo(` Intent + baseline + compact + session-end: always on \u2713`);
|
|
25913
|
+
if (!hookStatus.stop && hookStatus.guardOn.length === 0) {
|
|
25914
|
+
printWarn(" No analysis moment is active \u2014 code changes will NOT be reviewed.");
|
|
25915
|
+
printWarn(" Enable one: verity hooks install --moments stop");
|
|
26178
25916
|
}
|
|
26179
25917
|
console.log("");
|
|
26180
25918
|
step("Sign in to Verity (optional)");
|
|
@@ -26217,7 +25955,7 @@ function registerInitCommand(program2) {
|
|
|
26217
25955
|
}
|
|
26218
25956
|
step("Your project's Standard");
|
|
26219
25957
|
let haveStandard = false;
|
|
26220
|
-
if ((0,
|
|
25958
|
+
if ((0, import_node_fs49.existsSync)(projectPath(STANDARD_FILE))) {
|
|
26221
25959
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
26222
25960
|
haveStandard = true;
|
|
26223
25961
|
} else {
|
|
@@ -26244,7 +25982,7 @@ function registerInitCommand(program2) {
|
|
|
26244
25982
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
26245
25983
|
init: {
|
|
26246
25984
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26247
|
-
cli_version: true ? "0.32.0-experimental.
|
|
25985
|
+
cli_version: true ? "0.32.0-experimental.f0746f7" : "dev"
|
|
26248
25986
|
}
|
|
26249
25987
|
});
|
|
26250
25988
|
} catch (err) {
|
|
@@ -26253,13 +25991,9 @@ function registerInitCommand(program2) {
|
|
|
26253
25991
|
console.log("");
|
|
26254
25992
|
printInfo("This machine is set up.");
|
|
26255
25993
|
console.log("");
|
|
26256
|
-
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
console.log(" .claude/skills/verity-*/ 8 skills (setup, analyze, status, feedback,");
|
|
26260
|
-
console.log(" learn, memory, insights, reflect)");
|
|
26261
|
-
console.log(" .claude/settings.json hooks, reconciled to your chosen moments");
|
|
26262
|
-
}
|
|
25994
|
+
console.log(" .claude/skills/verity-*/ 8 skills (setup, analyze, status, feedback,");
|
|
25995
|
+
console.log(" learn, memory, insights, reflect)");
|
|
25996
|
+
console.log(" .claude/settings.json hooks, reconciled to your chosen moments");
|
|
26263
25997
|
console.log(" .verity/memory/ knowledge base (commit to git)");
|
|
26264
25998
|
console.log(" .verity/standard.yaml the Standard the gate enforces");
|
|
26265
25999
|
console.log(" .codacy/codacy.config.json static-analysis patterns (validated)");
|
|
@@ -26283,7 +26017,7 @@ function registerInitCommand(program2) {
|
|
|
26283
26017
|
}
|
|
26284
26018
|
|
|
26285
26019
|
// src/commands/uninstall.ts
|
|
26286
|
-
var
|
|
26020
|
+
var import_node_fs50 = require("node:fs");
|
|
26287
26021
|
var import_node_path34 = require("node:path");
|
|
26288
26022
|
var SKILL_NAMES = [
|
|
26289
26023
|
"verity-setup",
|
|
@@ -26304,10 +26038,10 @@ function registerUninstallCommand(program2) {
|
|
|
26304
26038
|
const skillsRoot = projectPath(".claude/skills");
|
|
26305
26039
|
for (const name of SKILL_NAMES) {
|
|
26306
26040
|
const dir = (0, import_node_path34.join)(skillsRoot, name);
|
|
26307
|
-
if ((0,
|
|
26041
|
+
if ((0, import_node_fs50.existsSync)(dir)) {
|
|
26308
26042
|
actions.push({
|
|
26309
26043
|
label: `Remove .claude/skills/${name}/`,
|
|
26310
|
-
apply: () => (0,
|
|
26044
|
+
apply: () => (0, import_node_fs50.rmSync)(dir, { recursive: true, force: true })
|
|
26311
26045
|
});
|
|
26312
26046
|
}
|
|
26313
26047
|
}
|
|
@@ -26321,24 +26055,24 @@ function registerUninstallCommand(program2) {
|
|
|
26321
26055
|
});
|
|
26322
26056
|
}
|
|
26323
26057
|
const verityDir = projectPath(VERITY_DIR);
|
|
26324
|
-
if ((0,
|
|
26058
|
+
if ((0, import_node_fs50.existsSync)(verityDir)) {
|
|
26325
26059
|
actions.push({
|
|
26326
26060
|
label: `Remove ${VERITY_DIR}/`,
|
|
26327
|
-
apply: () => (0,
|
|
26061
|
+
apply: () => (0, import_node_fs50.rmSync)(verityDir, { recursive: true, force: true })
|
|
26328
26062
|
});
|
|
26329
26063
|
}
|
|
26330
26064
|
if (!keepVerityMd) {
|
|
26331
26065
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
26332
|
-
if ((0,
|
|
26066
|
+
if ((0, import_node_fs50.existsSync)(verityMd)) {
|
|
26333
26067
|
actions.push({
|
|
26334
26068
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
26335
|
-
apply: () => (0,
|
|
26069
|
+
apply: () => (0, import_node_fs50.rmSync)(verityMd, { force: true })
|
|
26336
26070
|
});
|
|
26337
26071
|
}
|
|
26338
26072
|
}
|
|
26339
26073
|
const cleanupEmptyDir = (path) => {
|
|
26340
|
-
if ((0,
|
|
26341
|
-
(0,
|
|
26074
|
+
if ((0, import_node_fs50.existsSync)(path) && (0, import_node_fs50.statSync)(path).isDirectory() && (0, import_node_fs50.readdirSync)(path).length === 0) {
|
|
26075
|
+
(0, import_node_fs50.rmdirSync)(path);
|
|
26342
26076
|
}
|
|
26343
26077
|
};
|
|
26344
26078
|
actions.push({
|
|
@@ -26350,10 +26084,10 @@ function registerUninstallCommand(program2) {
|
|
|
26350
26084
|
});
|
|
26351
26085
|
const home = process.env.HOME ?? "";
|
|
26352
26086
|
const globalVerityDir = (0, import_node_path34.join)(home, ".verity");
|
|
26353
|
-
if (purgeGlobal && (0,
|
|
26087
|
+
if (purgeGlobal && (0, import_node_fs50.existsSync)(globalVerityDir)) {
|
|
26354
26088
|
actions.push({
|
|
26355
26089
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
26356
|
-
apply: () => (0,
|
|
26090
|
+
apply: () => (0, import_node_fs50.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
26357
26091
|
});
|
|
26358
26092
|
}
|
|
26359
26093
|
if (actions.length === 0) {
|
|
@@ -26547,7 +26281,7 @@ function registerTaskCommands(program2) {
|
|
|
26547
26281
|
}
|
|
26548
26282
|
|
|
26549
26283
|
// src/commands/reset.ts
|
|
26550
|
-
var
|
|
26284
|
+
var import_node_fs51 = require("node:fs");
|
|
26551
26285
|
var import_node_path35 = require("node:path");
|
|
26552
26286
|
function registerResetCommand(program2) {
|
|
26553
26287
|
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) => {
|
|
@@ -26585,11 +26319,11 @@ function registerResetCommand(program2) {
|
|
|
26585
26319
|
}
|
|
26586
26320
|
const cacheDir = projectPath(CACHE_DIR);
|
|
26587
26321
|
let purged = 0;
|
|
26588
|
-
if ((0,
|
|
26589
|
-
for (const entry of (0,
|
|
26322
|
+
if ((0, import_node_fs51.existsSync)(cacheDir)) {
|
|
26323
|
+
for (const entry of (0, import_node_fs51.readdirSync)(cacheDir)) {
|
|
26590
26324
|
if (entry.startsWith("pending-")) {
|
|
26591
26325
|
try {
|
|
26592
|
-
(0,
|
|
26326
|
+
(0, import_node_fs51.unlinkSync)((0, import_node_path35.join)(cacheDir, entry));
|
|
26593
26327
|
purged++;
|
|
26594
26328
|
} catch {
|
|
26595
26329
|
}
|
|
@@ -26604,19 +26338,19 @@ function registerResetCommand(program2) {
|
|
|
26604
26338
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
26605
26339
|
];
|
|
26606
26340
|
for (const file of filesToClear) {
|
|
26607
|
-
if ((0,
|
|
26341
|
+
if ((0, import_node_fs51.existsSync)(file)) {
|
|
26608
26342
|
try {
|
|
26609
|
-
(0,
|
|
26343
|
+
(0, import_node_fs51.writeFileSync)(file, "");
|
|
26610
26344
|
} catch {
|
|
26611
26345
|
}
|
|
26612
26346
|
}
|
|
26613
26347
|
}
|
|
26614
26348
|
if (opts.all) {
|
|
26615
26349
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
26616
|
-
if ((0,
|
|
26617
|
-
for (const entry of (0,
|
|
26350
|
+
if ((0, import_node_fs51.existsSync)(logsDir)) {
|
|
26351
|
+
for (const entry of (0, import_node_fs51.readdirSync)(logsDir)) {
|
|
26618
26352
|
try {
|
|
26619
|
-
(0,
|
|
26353
|
+
(0, import_node_fs51.unlinkSync)((0, import_node_path35.join)(logsDir, entry));
|
|
26620
26354
|
} catch {
|
|
26621
26355
|
}
|
|
26622
26356
|
}
|
|
@@ -26924,8 +26658,8 @@ function registerTelemetryCommands(program2) {
|
|
|
26924
26658
|
}
|
|
26925
26659
|
|
|
26926
26660
|
// src/cli.ts
|
|
26927
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.32.0-experimental.
|
|
26928
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.0-experimental.
|
|
26661
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.32.0-experimental.f0746f7").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) => {
|
|
26662
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.0-experimental.f0746f7");
|
|
26929
26663
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
26930
26664
|
try {
|
|
26931
26665
|
await foldLegacyLocalCredential();
|