@codacy/verity-cli 0.29.4-experimental.7126d67 → 0.29.4-experimental.7475da6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/verity.js +402 -140
- package/data/skills/verity-setup/SKILL.md +21 -8
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10502,6 +10502,7 @@ var GITHUB_APP_INSTALL_URL = `https://github.com/apps/${GITHUB_APP_SLUG}/install
|
|
|
10502
10502
|
function githubAppInstallUrl(accountId) {
|
|
10503
10503
|
return accountId != null ? `https://github.com/apps/${GITHUB_APP_SLUG}/installations/new/permissions?target_id=${accountId}` : GITHUB_APP_INSTALL_URL;
|
|
10504
10504
|
}
|
|
10505
|
+
var ADVISORY_EPISODE_FILE = `${VERITY_DIR}/.advisory-episode`;
|
|
10505
10506
|
|
|
10506
10507
|
// src/lib/output.ts
|
|
10507
10508
|
var RED = "\x1B[0;31m";
|
|
@@ -15515,6 +15516,33 @@ ${addedLines}`,
|
|
|
15515
15516
|
}
|
|
15516
15517
|
return { diffs, has_snapshots: true };
|
|
15517
15518
|
}
|
|
15519
|
+
function ensureSnapshotGitignored() {
|
|
15520
|
+
let content = "";
|
|
15521
|
+
try {
|
|
15522
|
+
content = (0, import_node_fs15.readFileSync)(".gitignore", "utf-8");
|
|
15523
|
+
} catch {
|
|
15524
|
+
}
|
|
15525
|
+
let ignored = null;
|
|
15526
|
+
try {
|
|
15527
|
+
(0, import_node_child_process6.execSync)("git check-ignore -q -- .verity/.snapshot/__probe__", { stdio: "pipe" });
|
|
15528
|
+
ignored = true;
|
|
15529
|
+
} catch (err) {
|
|
15530
|
+
ignored = err.status === 1 ? false : null;
|
|
15531
|
+
}
|
|
15532
|
+
if (ignored === true) return "covered";
|
|
15533
|
+
if (ignored === null) {
|
|
15534
|
+
const lines = content.split("\n").map((l) => l.trim());
|
|
15535
|
+
const covering = [".verity/.snapshot/", ".verity/.snapshot", ".verity/", ".verity", ".verity/*"];
|
|
15536
|
+
if (lines.some((l) => covering.includes(l))) return "covered";
|
|
15537
|
+
}
|
|
15538
|
+
try {
|
|
15539
|
+
const block = "# Verity \u2014 snapshots of analyzed files (machine state, never commit)\n.verity/.snapshot/\n";
|
|
15540
|
+
(0, import_node_fs15.writeFileSync)(".gitignore", content ? content + (content.endsWith("\n") ? "" : "\n") + "\n" + block : block);
|
|
15541
|
+
return "added";
|
|
15542
|
+
} catch {
|
|
15543
|
+
return "failed";
|
|
15544
|
+
}
|
|
15545
|
+
}
|
|
15518
15546
|
function saveSnapshots(files) {
|
|
15519
15547
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
15520
15548
|
for (const file of files) {
|
|
@@ -15559,7 +15587,7 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
15559
15587
|
try {
|
|
15560
15588
|
const entries = (0, import_node_fs15.readdirSync)(dir, { withFileTypes: true });
|
|
15561
15589
|
for (const entry of entries) {
|
|
15562
|
-
if (entry.name.
|
|
15590
|
+
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
15563
15591
|
const fullPath = (0, import_node_path14.join)(dir, entry.name);
|
|
15564
15592
|
if (entry.isDirectory()) {
|
|
15565
15593
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
@@ -17148,6 +17176,39 @@ async function bootstrap(run) {
|
|
|
17148
17176
|
Object.assign(run, { actionSummary, assistantResponse, baseline, baselineSessionId, reachability, sessionId, stopReason, tokenResult, transcriptPath, turnId });
|
|
17149
17177
|
}
|
|
17150
17178
|
|
|
17179
|
+
// src/lib/self-scope.ts
|
|
17180
|
+
var LEGACY_GATE_SKILLS = /* @__PURE__ */ new Set([
|
|
17181
|
+
"gate-setup",
|
|
17182
|
+
"gate-analyze",
|
|
17183
|
+
"gate-review",
|
|
17184
|
+
"gate-status",
|
|
17185
|
+
"gate-feedback",
|
|
17186
|
+
"gate-insights",
|
|
17187
|
+
"gate-learn",
|
|
17188
|
+
"gate-memory",
|
|
17189
|
+
"gate-reflect"
|
|
17190
|
+
]);
|
|
17191
|
+
function isVerityOwned(path) {
|
|
17192
|
+
const segments = path.replace(/\\/g, "/").split("/");
|
|
17193
|
+
for (let i = 0; i < segments.length; i++) {
|
|
17194
|
+
const seg = segments[i];
|
|
17195
|
+
if (seg === ".verity" || seg === ".codacy") return true;
|
|
17196
|
+
if (i === segments.length - 1 && (seg === "VERITY.md" || seg === "GATE.md")) return true;
|
|
17197
|
+
if (seg === ".claude" && segments[i + 1] === "skills" && typeof segments[i + 2] === "string") {
|
|
17198
|
+
const skill = segments[i + 2];
|
|
17199
|
+
if (skill.startsWith("verity-") || LEGACY_GATE_SKILLS.has(skill)) return true;
|
|
17200
|
+
}
|
|
17201
|
+
if (seg === ".claude" && segments[i + 1] === "settings.json") return true;
|
|
17202
|
+
}
|
|
17203
|
+
return false;
|
|
17204
|
+
}
|
|
17205
|
+
function partitionVerityOwned(paths) {
|
|
17206
|
+
const kept = [];
|
|
17207
|
+
const owned = [];
|
|
17208
|
+
for (const p of paths) (isVerityOwned(p) ? owned : kept).push(p);
|
|
17209
|
+
return { kept, owned };
|
|
17210
|
+
}
|
|
17211
|
+
|
|
17151
17212
|
// src/lib/channel.ts
|
|
17152
17213
|
var MAX_AGENT_CONTEXT_CHARS = 1500;
|
|
17153
17214
|
var MAX_AGENT_ITEMS = 5;
|
|
@@ -17157,6 +17218,29 @@ function renderItem(label2, text, patternId, file, line) {
|
|
|
17157
17218
|
const id = patternId ? ` [${patternId}]` : "";
|
|
17158
17219
|
return `- ${label2}${text}${where}${id}`;
|
|
17159
17220
|
}
|
|
17221
|
+
function channelInputFrom(response, intentRepeat = 0, priorPendingFingerprints = []) {
|
|
17222
|
+
const metadata = response.metadata ?? {};
|
|
17223
|
+
const intent = response.intent_alignment ?? {};
|
|
17224
|
+
return {
|
|
17225
|
+
intentRepeat,
|
|
17226
|
+
priorPendingFingerprints,
|
|
17227
|
+
gateDecision: String(response.gate_decision ?? ""),
|
|
17228
|
+
findings: response.findings ?? [],
|
|
17229
|
+
pendingItems: response.pending_items ?? [],
|
|
17230
|
+
reviewStatus: metadata.review_status,
|
|
17231
|
+
coverage: metadata.coverage,
|
|
17232
|
+
intentVerdict: intent.verdict,
|
|
17233
|
+
intentGaps: intent.gaps
|
|
17234
|
+
};
|
|
17235
|
+
}
|
|
17236
|
+
function classifyChannelContent(input) {
|
|
17237
|
+
const refusal = input.reviewStatus === "not_reviewed" || input.reviewStatus === "no_authorship_evidence";
|
|
17238
|
+
const intentFlag = input.intentVerdict === "misaligned" || input.intentVerdict === "partial";
|
|
17239
|
+
const advisory = (input.findings ?? []).some((f) => f.scope !== "pre-existing") || (input.pendingItems ?? []).some(
|
|
17240
|
+
(p) => p.pattern_id !== "intent-misalignment" && !!(p.description ?? p.title ?? p.reason)
|
|
17241
|
+
);
|
|
17242
|
+
return { refusal, intentFlag, advisory };
|
|
17243
|
+
}
|
|
17160
17244
|
function buildAgentContext(input) {
|
|
17161
17245
|
const lines = [];
|
|
17162
17246
|
if (input.reviewStatus === "not_reviewed") {
|
|
@@ -17242,7 +17326,7 @@ function channelSilence(input) {
|
|
|
17242
17326
|
// src/lib/cli-version.ts
|
|
17243
17327
|
function cliVersion() {
|
|
17244
17328
|
try {
|
|
17245
|
-
return true ? "0.29.4-experimental.
|
|
17329
|
+
return true ? "0.29.4-experimental.7475da6" : "dev";
|
|
17246
17330
|
} catch {
|
|
17247
17331
|
return "dev";
|
|
17248
17332
|
}
|
|
@@ -17564,9 +17648,10 @@ async function scope(run) {
|
|
|
17564
17648
|
const { assistantResponse } = run;
|
|
17565
17649
|
const { files: allChanged, hasRecentCommitFiles } = getChangedFiles();
|
|
17566
17650
|
run.changedUniverse = allChanged;
|
|
17567
|
-
const
|
|
17568
|
-
const
|
|
17569
|
-
const
|
|
17651
|
+
const { kept: external } = partitionVerityOwned(allChanged);
|
|
17652
|
+
const analyzable = filterAnalyzable(external);
|
|
17653
|
+
const reviewable = filterReviewable(external);
|
|
17654
|
+
const securityFiles = filterSecurity(external);
|
|
17570
17655
|
const noFilesChanged = analyzable.length === 0 && reviewable.length === 0 && securityFiles.length === 0;
|
|
17571
17656
|
if (noFilesChanged && !assistantResponse) {
|
|
17572
17657
|
await passAndExit(run, "No analyzable files changed", "no-analyzable-files");
|
|
@@ -18059,26 +18144,50 @@ function narrowToRecent(files, sessionId) {
|
|
|
18059
18144
|
});
|
|
18060
18145
|
return recent.length > 0 ? recent : files;
|
|
18061
18146
|
}
|
|
18062
|
-
function
|
|
18063
|
-
|
|
18147
|
+
function readIteration(currentCommit, _contentHash) {
|
|
18148
|
+
return Math.max(1, readBlockState(currentCommit).attempts);
|
|
18149
|
+
}
|
|
18150
|
+
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
18151
|
+
function readBlockState(currentCommit, opts) {
|
|
18152
|
+
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
18153
|
+
if (!(0, import_node_fs22.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
18064
18154
|
try {
|
|
18065
18155
|
const stored = (0, import_node_fs22.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
18066
|
-
const
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
if (isNaN(iter)) return { iteration: 1, fingerprint: null };
|
|
18072
|
-
if (storedCommit !== currentCommit) return { iteration: 1, fingerprint: null };
|
|
18073
|
-
if (storedTimestamp > 0) {
|
|
18074
|
-
const elapsed = Math.floor(Date.now() / 1e3) - storedTimestamp;
|
|
18075
|
-
if (elapsed > 600) return { iteration: 1, fingerprint: null };
|
|
18076
|
-
}
|
|
18077
|
-
return { iteration: iter, fingerprint };
|
|
18156
|
+
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
18157
|
+
if (!parsed) return NO_BLOCKS;
|
|
18158
|
+
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
18159
|
+
if (parsed.ts > 0 && Math.floor(Date.now() / 1e3) - parsed.ts > 600) return NO_BLOCKS;
|
|
18160
|
+
return { attempts: parsed.attempts, blocks: parsed.blocks, fingerprint: parsed.fingerprint };
|
|
18078
18161
|
} catch {
|
|
18079
|
-
return
|
|
18162
|
+
return NO_BLOCKS;
|
|
18080
18163
|
}
|
|
18081
18164
|
}
|
|
18165
|
+
function parseJsonState(raw) {
|
|
18166
|
+
const o = JSON.parse(raw);
|
|
18167
|
+
const attempts = typeof o.attempts === "number" ? o.attempts : NaN;
|
|
18168
|
+
if (isNaN(attempts)) return null;
|
|
18169
|
+
return {
|
|
18170
|
+
attempts,
|
|
18171
|
+
blocks: typeof o.blocks === "number" ? o.blocks : attempts,
|
|
18172
|
+
fingerprint: typeof o.fingerprint === "string" && o.fingerprint ? o.fingerprint : null,
|
|
18173
|
+
commit: typeof o.commit === "string" ? o.commit : "",
|
|
18174
|
+
ts: typeof o.ts === "number" ? o.ts : 0
|
|
18175
|
+
};
|
|
18176
|
+
}
|
|
18177
|
+
function parseLegacyState(raw) {
|
|
18178
|
+
const parts = raw.split(":");
|
|
18179
|
+
const n = parseInt(parts[0], 10);
|
|
18180
|
+
if (isNaN(n)) return null;
|
|
18181
|
+
return {
|
|
18182
|
+
attempts: n,
|
|
18183
|
+
// The old file has no separate block count; the old counter is the closest
|
|
18184
|
+
// honest answer, and it errs toward releasing sooner rather than later.
|
|
18185
|
+
blocks: n,
|
|
18186
|
+
fingerprint: parts.slice(3).join(":") || null,
|
|
18187
|
+
commit: parts[1] ?? "",
|
|
18188
|
+
ts: parseInt(parts[2] ?? "0", 10)
|
|
18189
|
+
};
|
|
18190
|
+
}
|
|
18082
18191
|
function findingsFingerprint(findings) {
|
|
18083
18192
|
const keys = findings.map((f) => `${String(f.pattern_id ?? "?")}|${String(f.file ?? "?")}`).filter((k) => k !== "?|?");
|
|
18084
18193
|
return [...new Set(keys)].sort().join(",");
|
|
@@ -18088,11 +18197,22 @@ function isSameProblem(previous, current) {
|
|
|
18088
18197
|
const prev = new Set(previous.split(","));
|
|
18089
18198
|
return current.split(",").some((k) => prev.has(k));
|
|
18090
18199
|
}
|
|
18091
|
-
function
|
|
18200
|
+
function writeBlockState(commit, state) {
|
|
18092
18201
|
(0, import_node_fs22.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
18093
|
-
|
|
18094
|
-
|
|
18095
|
-
|
|
18202
|
+
(0, import_node_fs22.writeFileSync)(
|
|
18203
|
+
ITERATION_FILE,
|
|
18204
|
+
JSON.stringify({
|
|
18205
|
+
v: 2,
|
|
18206
|
+
attempts: state.attempts,
|
|
18207
|
+
blocks: state.blocks,
|
|
18208
|
+
commit,
|
|
18209
|
+
ts: Math.floor(Date.now() / 1e3),
|
|
18210
|
+
fingerprint: state.fingerprint ?? void 0
|
|
18211
|
+
})
|
|
18212
|
+
);
|
|
18213
|
+
}
|
|
18214
|
+
function resetBlockState(commit) {
|
|
18215
|
+
writeBlockState(commit, { attempts: 0, blocks: 0, fingerprint: null });
|
|
18096
18216
|
}
|
|
18097
18217
|
|
|
18098
18218
|
// src/lib/fold.ts
|
|
@@ -18690,13 +18810,13 @@ async function evidence(run) {
|
|
|
18690
18810
|
snapshotResult = generateSnapshotDiffs(codeDelta.files);
|
|
18691
18811
|
}
|
|
18692
18812
|
currentCommit = getCurrentCommit();
|
|
18693
|
-
iteration =
|
|
18813
|
+
iteration = readIteration(currentCommit);
|
|
18694
18814
|
}
|
|
18695
18815
|
}
|
|
18696
18816
|
if (analysisMode === "plan") {
|
|
18697
18817
|
recordAnalysisStart();
|
|
18698
18818
|
currentCommit = getCurrentCommit();
|
|
18699
|
-
iteration =
|
|
18819
|
+
iteration = readIteration(currentCommit);
|
|
18700
18820
|
}
|
|
18701
18821
|
Object.assign(run, { analysisMode, codeDelta, contentHash, currentCommit, earlyFold, iteration, snapshotResult, staticResults });
|
|
18702
18822
|
}
|
|
@@ -18792,7 +18912,8 @@ function gatherContextFiles(contextPaths, deltaFiles) {
|
|
|
18792
18912
|
// src/commands/analyze/phases/07-context-files.ts
|
|
18793
18913
|
async function contextFiles(run) {
|
|
18794
18914
|
const { codeDelta, contextFilePaths } = run;
|
|
18795
|
-
const
|
|
18915
|
+
const { kept: externalContext } = partitionVerityOwned(contextFilePaths ?? []);
|
|
18916
|
+
const contextFiles2 = gatherContextFiles(externalContext, codeDelta.files);
|
|
18796
18917
|
for (const f of codeDelta.files) {
|
|
18797
18918
|
f.role = "delta";
|
|
18798
18919
|
}
|
|
@@ -19362,6 +19483,54 @@ async function workingMemory(run) {
|
|
|
19362
19483
|
Object.assign(run, { incrementReport, memory, memorySession, reachability });
|
|
19363
19484
|
}
|
|
19364
19485
|
|
|
19486
|
+
// src/lib/note-budget.ts
|
|
19487
|
+
var import_node_fs28 = require("node:fs");
|
|
19488
|
+
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
19489
|
+
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
19490
|
+
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
19491
|
+
function resolveEpisode(prev, signals) {
|
|
19492
|
+
if (!prev) return { ...FRESH, tasksCompleted: signals.tasksCompleted, ts: signals.now };
|
|
19493
|
+
if (signals.humanSpoke) return { ...FRESH, tasksCompleted: signals.tasksCompleted, ts: signals.now };
|
|
19494
|
+
if (signals.rawFail) return { ...FRESH, tasksCompleted: signals.tasksCompleted, ts: signals.now };
|
|
19495
|
+
if (prev.tasksCompleted !== signals.tasksCompleted) {
|
|
19496
|
+
return { ...FRESH, tasksCompleted: signals.tasksCompleted, ts: signals.now };
|
|
19497
|
+
}
|
|
19498
|
+
if (prev.ts > 0 && signals.now - prev.ts > EPISODE_STALE_SECONDS) {
|
|
19499
|
+
return { ...FRESH, tasksCompleted: signals.tasksCompleted, ts: signals.now };
|
|
19500
|
+
}
|
|
19501
|
+
return prev;
|
|
19502
|
+
}
|
|
19503
|
+
function advisoryBudgetSpent(episode, rawDecision) {
|
|
19504
|
+
const budget = ADVISORY_BUDGET[rawDecision] ?? ADVISORY_BUDGET.WARN;
|
|
19505
|
+
return episode.delivered >= budget;
|
|
19506
|
+
}
|
|
19507
|
+
function readAdvisoryEpisode(sessionId) {
|
|
19508
|
+
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
19509
|
+
if (!(0, import_node_fs28.existsSync)(file)) return null;
|
|
19510
|
+
try {
|
|
19511
|
+
const o = JSON.parse((0, import_node_fs28.readFileSync)(file, "utf-8")) ?? {};
|
|
19512
|
+
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
19513
|
+
if (isNaN(delivered)) return null;
|
|
19514
|
+
return {
|
|
19515
|
+
delivered,
|
|
19516
|
+
tasksCompleted: typeof o.tasksCompleted === "number" ? o.tasksCompleted : 0,
|
|
19517
|
+
ts: typeof o.ts === "number" ? o.ts : 0
|
|
19518
|
+
};
|
|
19519
|
+
} catch {
|
|
19520
|
+
return null;
|
|
19521
|
+
}
|
|
19522
|
+
}
|
|
19523
|
+
function writeAdvisoryEpisode(episode, sessionId) {
|
|
19524
|
+
try {
|
|
19525
|
+
(0, import_node_fs28.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
19526
|
+
(0, import_node_fs28.writeFileSync)(
|
|
19527
|
+
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
19528
|
+
JSON.stringify({ v: 1, ...episode })
|
|
19529
|
+
);
|
|
19530
|
+
} catch {
|
|
19531
|
+
}
|
|
19532
|
+
}
|
|
19533
|
+
|
|
19365
19534
|
// src/lib/run-mode.ts
|
|
19366
19535
|
function parseAutonomousEnv(raw) {
|
|
19367
19536
|
if (raw === void 0) return void 0;
|
|
@@ -19455,7 +19624,13 @@ async function buildRequest(run) {
|
|
|
19455
19624
|
excluded_by_reason: excludedByReason,
|
|
19456
19625
|
// was the transcript itself truncated? The 256 KB window means "this turn"
|
|
19457
19626
|
// can quietly mean "the last 256 KB of it".
|
|
19458
|
-
transcript_windowed: actionSummary?.transcript_windowed ?? null
|
|
19627
|
+
transcript_windowed: actionSummary?.transcript_windowed ?? null,
|
|
19628
|
+
// The advisory budget's fleet counter-metric (note-budget.ts): deliveries in
|
|
19629
|
+
// the episode as of the PREVIOUS turn — this runs before phase 13 updates
|
|
19630
|
+
// the state, so the number is one turn lagged by construction. The
|
|
19631
|
+
// degenerate win for the budget is a dead channel that looks like clean
|
|
19632
|
+
// code; this is what makes "did delivery rate collapse" a query.
|
|
19633
|
+
advisory_delivered_prior: readAdvisoryEpisode(run.baselineSessionId)?.delivered ?? 0
|
|
19459
19634
|
};
|
|
19460
19635
|
const requestBody = {
|
|
19461
19636
|
coverage_telemetry: coverageTelemetry,
|
|
@@ -19594,7 +19769,8 @@ async function buildRequest(run) {
|
|
|
19594
19769
|
}
|
|
19595
19770
|
const noHumanPrompt = (conversation?.prompts?.length ?? 0) === 0;
|
|
19596
19771
|
const w4Task = noHumanPrompt && isExplicitlyAutonomous() ? resolveTaskContext() : null;
|
|
19597
|
-
const
|
|
19772
|
+
const planApprovalActive = foldResult?.planApproval?.activeSinceLastPrompt === true;
|
|
19773
|
+
const hasIntent = (conversation?.prompts?.length ?? 0) > 0 || specs.length > 0 || plans.length > 0 || !!assistantResponse || !!w4Task || planApprovalActive;
|
|
19598
19774
|
if (hasIntent) {
|
|
19599
19775
|
const intentContext = {};
|
|
19600
19776
|
if (conversation && conversation.prompts.length > 0) {
|
|
@@ -19626,7 +19802,7 @@ async function buildRequest(run) {
|
|
|
19626
19802
|
intentContext.user_prompt = w4Task.goal;
|
|
19627
19803
|
logEvent("w4_issue_anchor", { issue: w4Task.number, via: w4Task.via });
|
|
19628
19804
|
}
|
|
19629
|
-
if (
|
|
19805
|
+
if (planApprovalActive) {
|
|
19630
19806
|
intentContext.plan_approved = true;
|
|
19631
19807
|
logEvent("plan_approval_carried", { approvals: foldResult.planApproval.approvals });
|
|
19632
19808
|
}
|
|
@@ -19649,14 +19825,14 @@ async function buildRequest(run) {
|
|
|
19649
19825
|
}
|
|
19650
19826
|
|
|
19651
19827
|
// src/lib/offline.ts
|
|
19652
|
-
var
|
|
19828
|
+
var import_node_fs29 = require("node:fs");
|
|
19653
19829
|
var import_node_crypto11 = require("node:crypto");
|
|
19654
19830
|
function cacheRequest(body) {
|
|
19655
19831
|
try {
|
|
19656
|
-
(0,
|
|
19832
|
+
(0, import_node_fs29.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
19657
19833
|
const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
|
|
19658
19834
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
19659
|
-
(0,
|
|
19835
|
+
(0, import_node_fs29.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
|
|
19660
19836
|
} catch {
|
|
19661
19837
|
}
|
|
19662
19838
|
}
|
|
@@ -19775,10 +19951,10 @@ async function transmit(run) {
|
|
|
19775
19951
|
}
|
|
19776
19952
|
|
|
19777
19953
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
19778
|
-
var
|
|
19954
|
+
var import_node_fs30 = require("node:fs");
|
|
19779
19955
|
var import_node_path23 = require("node:path");
|
|
19780
19956
|
async function reconcile(run) {
|
|
19781
|
-
const { actionSummary, allChanged, analyzable, baseline, codeDelta, contentHash, conversation, decision, memory, memorySession, response, reviewable, securityFiles, turnId } = run;
|
|
19957
|
+
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run;
|
|
19782
19958
|
const sentPaths = codeDelta.files.map((f) => f.path);
|
|
19783
19959
|
let openElsewhere = [];
|
|
19784
19960
|
if (memorySession) {
|
|
@@ -19786,7 +19962,7 @@ async function reconcile(run) {
|
|
|
19786
19962
|
const st = foldDossier(memorySession.d);
|
|
19787
19963
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
|
|
19788
19964
|
try {
|
|
19789
|
-
const src = (0,
|
|
19965
|
+
const src = (0, import_node_fs30.readFileSync)((0, import_node_path23.join)(repoRoot(), file), "utf8").split("\n");
|
|
19790
19966
|
const at = src[line - 1];
|
|
19791
19967
|
return at === void 0 ? null : lineSha(at);
|
|
19792
19968
|
} catch {
|
|
@@ -19796,6 +19972,7 @@ async function reconcile(run) {
|
|
|
19796
19972
|
} catch {
|
|
19797
19973
|
}
|
|
19798
19974
|
}
|
|
19975
|
+
const { kept: externalChanged, owned: verityOwned } = partitionVerityOwned(allChanged);
|
|
19799
19976
|
const reviewCoverage = {
|
|
19800
19977
|
reviewed: sentPaths,
|
|
19801
19978
|
// Declared drops from the stages that DO report themselves today. The other
|
|
@@ -19837,11 +20014,20 @@ async function reconcile(run) {
|
|
|
19837
20014
|
stage: "baseline-scoping",
|
|
19838
20015
|
kind: "policy"
|
|
19839
20016
|
})),
|
|
20017
|
+
// ⚠ VERITY'S OWN FILES, named as such — not laundered into the
|
|
20018
|
+
// extension bucket below, where "we do not review our own installer's
|
|
20019
|
+
// dirt" would read as "a changed README". See self-scope.ts.
|
|
20020
|
+
...verityOwned.map((path) => ({
|
|
20021
|
+
path,
|
|
20022
|
+
reason: "verity-owned",
|
|
20023
|
+
stage: "self-scope",
|
|
20024
|
+
kind: "policy"
|
|
20025
|
+
})),
|
|
19840
20026
|
// The extension allowlist. POLICY: a changed README was never going to be
|
|
19841
20027
|
// reviewed, and calling that a coverage gap would downgrade nearly every
|
|
19842
20028
|
// PASS to WARN until WARN meant nothing. Recorded so the ledger balances and
|
|
19843
20029
|
// so "what did Verity ignore entirely" is answerable.
|
|
19844
|
-
...
|
|
20030
|
+
...externalChanged.filter((p) => !analyzable.includes(p) && !reviewable.includes(p) && !securityFiles.includes(p)).map((path) => ({
|
|
19845
20031
|
path,
|
|
19846
20032
|
reason: "not-a-reviewed-file-type",
|
|
19847
20033
|
stage: "extension-allowlist",
|
|
@@ -19878,6 +20064,29 @@ async function reconcile(run) {
|
|
|
19878
20064
|
decision
|
|
19879
20065
|
});
|
|
19880
20066
|
}
|
|
20067
|
+
const episodeSignals = {
|
|
20068
|
+
humanSpoke: (conversation?.prompts?.length ?? 0) > 0,
|
|
20069
|
+
rawFail: decision === "FAIL",
|
|
20070
|
+
tasksCompleted: (foldResult?.tasks ?? []).filter((t) => t.status === "completed").length,
|
|
20071
|
+
now: Math.floor(Date.now() / 1e3)
|
|
20072
|
+
};
|
|
20073
|
+
let episode = resolveEpisode(readAdvisoryEpisode(baselineSessionId), episodeSignals);
|
|
20074
|
+
const contentClass = classifyChannelContent(channelInputFrom(response));
|
|
20075
|
+
const wouldCarryAdvisory = contentClass.advisory || openElsewhere.length > 0;
|
|
20076
|
+
if (decision !== "FAIL" && !silenced && wouldCarryAdvisory && !contentClass.refusal && !contentClass.intentFlag && advisoryBudgetSpent(episode, decision)) {
|
|
20077
|
+
silenced = "note-budget";
|
|
20078
|
+
logEvent("channel_silenced", {
|
|
20079
|
+
reason: silenced,
|
|
20080
|
+
run_id: response.run_id ?? turnId,
|
|
20081
|
+
decision,
|
|
20082
|
+
episode_delivered: episode.delivered
|
|
20083
|
+
});
|
|
20084
|
+
}
|
|
20085
|
+
const deliveringAdvisory = decision !== "FAIL" && !silenced && wouldCarryAdvisory;
|
|
20086
|
+
writeAdvisoryEpisode(
|
|
20087
|
+
{ ...episode, delivered: episode.delivered + (deliveringAdvisory ? 1 : 0), ts: episodeSignals.now },
|
|
20088
|
+
baselineSessionId
|
|
20089
|
+
);
|
|
19881
20090
|
let intentRepeatCount = 0;
|
|
19882
20091
|
const priorPendingFingerprints = memorySession ? (() => {
|
|
19883
20092
|
try {
|
|
@@ -19964,6 +20173,39 @@ ${YELLOW2}${note}${NC2}
|
|
|
19964
20173
|
return exit(0);
|
|
19965
20174
|
}
|
|
19966
20175
|
|
|
20176
|
+
// src/lib/may-block.ts
|
|
20177
|
+
var HARD_BLOCK_CEILING = 5;
|
|
20178
|
+
function mayBlock(input) {
|
|
20179
|
+
const ceiling = input.ceiling ?? HARD_BLOCK_CEILING;
|
|
20180
|
+
if (input.reviewedFileCount === 0 && input.staticFindingCount === 0) {
|
|
20181
|
+
return { block: false, release: "no-code-reviewed" };
|
|
20182
|
+
}
|
|
20183
|
+
if (input.cycleCutFired) {
|
|
20184
|
+
return { block: false, release: "nothing-moved" };
|
|
20185
|
+
}
|
|
20186
|
+
if (input.attempts > input.maxIterations) {
|
|
20187
|
+
return { block: false, release: "same-problem-cap" };
|
|
20188
|
+
}
|
|
20189
|
+
if (input.blocks > ceiling) {
|
|
20190
|
+
return { block: false, release: "block-ceiling" };
|
|
20191
|
+
}
|
|
20192
|
+
return { block: true, release: null };
|
|
20193
|
+
}
|
|
20194
|
+
function describeRelease(release, input) {
|
|
20195
|
+
const ceiling = input.ceiling ?? HARD_BLOCK_CEILING;
|
|
20196
|
+
const open = input.findingCount > 0 ? `${input.findingCount} finding(s) remain OPEN and were NOT fixed. Human review required before deploying.` : "Human review required before deploying.";
|
|
20197
|
+
switch (release) {
|
|
20198
|
+
case "no-code-reviewed":
|
|
20199
|
+
return `Verity: WARN \u2014 NOT BLOCKING: no code was reviewed on this turn, so there is nothing here to fix. Reported as advice instead. ${open}`;
|
|
20200
|
+
case "nothing-moved":
|
|
20201
|
+
return `Verity: WARN \u2014 NOT BLOCKING: nothing has changed since the last verdict, so re-raising it cannot move anything forward. ${open}`;
|
|
20202
|
+
case "same-problem-cap":
|
|
20203
|
+
return `Verity: WARN \u2014 self-healing limit (${input.maxIterations}) reached on the same finding. NO LONGER BLOCKING, but ${open}`;
|
|
20204
|
+
case "block-ceiling":
|
|
20205
|
+
return `Verity: WARN \u2014 ${ceiling} consecutive blocking verdicts reached; releasing the block so this cannot loop. ${open}`;
|
|
20206
|
+
}
|
|
20207
|
+
}
|
|
20208
|
+
|
|
19967
20209
|
// src/lib/remediation-guard.ts
|
|
19968
20210
|
var TOOL_CONFIG_PATTERNS = [
|
|
19969
20211
|
/(^|\/)\.codacy\//,
|
|
@@ -20006,19 +20248,7 @@ function screenRemediation(fix, findingFile) {
|
|
|
20006
20248
|
|
|
20007
20249
|
// src/commands/analyze/phases/14-render.ts
|
|
20008
20250
|
function agentContextFor(response, intentRepeat = 0, priorPendingFingerprints = []) {
|
|
20009
|
-
|
|
20010
|
-
const intent = response.intent_alignment ?? {};
|
|
20011
|
-
return buildAgentContext({
|
|
20012
|
-
intentRepeat,
|
|
20013
|
-
priorPendingFingerprints,
|
|
20014
|
-
gateDecision: String(response.gate_decision ?? ""),
|
|
20015
|
-
findings: response.findings ?? [],
|
|
20016
|
-
pendingItems: response.pending_items ?? [],
|
|
20017
|
-
reviewStatus: metadata.review_status,
|
|
20018
|
-
coverage: metadata.coverage,
|
|
20019
|
-
intentVerdict: intent.verdict,
|
|
20020
|
-
intentGaps: intent.gaps
|
|
20021
|
-
});
|
|
20251
|
+
return buildAgentContext(channelInputFrom(response, intentRepeat, priorPendingFingerprints));
|
|
20022
20252
|
}
|
|
20023
20253
|
async function render(run) {
|
|
20024
20254
|
const { opts, globals } = run;
|
|
@@ -20112,38 +20342,63 @@ async function render(run) {
|
|
|
20112
20342
|
reverify_by: response.reverify_by
|
|
20113
20343
|
});
|
|
20114
20344
|
const grantNudge = grantWarning ? ` \u26A0\uFE0F ${grantWarning}` : "";
|
|
20115
|
-
let
|
|
20345
|
+
let release = null;
|
|
20116
20346
|
let effectiveDecision = decision;
|
|
20117
20347
|
if (decision === "FAIL") {
|
|
20118
|
-
const
|
|
20348
|
+
const findings = response.findings ?? [];
|
|
20349
|
+
const blocking = findings.filter((f) => {
|
|
20119
20350
|
const sev = String(f.severity ?? "").toLowerCase();
|
|
20120
20351
|
return sev === "critical" || sev === "high";
|
|
20121
20352
|
});
|
|
20122
20353
|
const fingerprint = findingsFingerprint(blocking);
|
|
20123
|
-
const prior =
|
|
20354
|
+
const prior = readBlockState(currentCommit, {
|
|
20355
|
+
newUserPrompt: (conversation?.prompts?.length ?? 0) > 0
|
|
20356
|
+
});
|
|
20124
20357
|
const sameProblem = isSameProblem(prior.fingerprint, fingerprint);
|
|
20125
|
-
const nextIteration = sameProblem ? prior.iteration + 1 : 1;
|
|
20126
20358
|
const maxIterations = parseInt(opts.maxIterations, 10);
|
|
20127
|
-
|
|
20128
|
-
|
|
20129
|
-
|
|
20130
|
-
|
|
20359
|
+
const attempts = sameProblem ? prior.attempts + 1 : 1;
|
|
20360
|
+
const blocks = prior.blocks + 1;
|
|
20361
|
+
const decisionNow = mayBlock({
|
|
20362
|
+
reviewedFileCount: codeDelta.files.length,
|
|
20363
|
+
staticFindingCount: run.staticResults?.findings?.length ?? 0,
|
|
20364
|
+
cycleCutFired: silenced !== null,
|
|
20365
|
+
attempts,
|
|
20366
|
+
blocks,
|
|
20367
|
+
maxIterations
|
|
20368
|
+
});
|
|
20369
|
+
if (decisionNow.block) {
|
|
20370
|
+
writeBlockState(currentCommit, { attempts, blocks, fingerprint });
|
|
20371
|
+
iteration = attempts;
|
|
20372
|
+
} else {
|
|
20373
|
+
release = decisionNow.release;
|
|
20131
20374
|
effectiveDecision = "WARN";
|
|
20132
|
-
logEvent("
|
|
20375
|
+
logEvent("block_released", {
|
|
20376
|
+
reason: release,
|
|
20377
|
+
attempts,
|
|
20378
|
+
blocks,
|
|
20379
|
+
reviewed_files: codeDelta.files.length,
|
|
20380
|
+
cycle_cut: silenced,
|
|
20381
|
+
fingerprint
|
|
20382
|
+
});
|
|
20133
20383
|
}
|
|
20134
20384
|
}
|
|
20135
|
-
if (
|
|
20385
|
+
if (release) {
|
|
20136
20386
|
const findings = response.findings ?? [];
|
|
20137
20387
|
const lines = findings.slice(0, 5).map((f) => ` [${String(f.severity ?? "?").toUpperCase()}] ${String(f.title ?? f.message ?? "")} (${String(f.file ?? "?")}:${String(f.line ?? "?")})`);
|
|
20388
|
+
const summary = describeRelease(release, {
|
|
20389
|
+
findingCount: findings.length,
|
|
20390
|
+
maxIterations: parseInt(opts.maxIterations, 10)
|
|
20391
|
+
});
|
|
20138
20392
|
emitVerdict({
|
|
20139
20393
|
proposed: "WARN",
|
|
20140
20394
|
changed: run.changedUniverse,
|
|
20141
20395
|
coverage: reviewCoverage,
|
|
20142
|
-
userSummary:
|
|
20143
|
-
${lines.join("\n")}
|
|
20396
|
+
userSummary: lines.length > 0 ? `${summary}
|
|
20397
|
+
${lines.join("\n")}` : summary,
|
|
20144
20398
|
agentContext: null,
|
|
20145
20399
|
silenced: true
|
|
20146
20400
|
});
|
|
20401
|
+
return;
|
|
20147
20402
|
}
|
|
20148
20403
|
switch (effectiveDecision) {
|
|
20149
20404
|
case "FAIL": {
|
|
@@ -20242,7 +20497,7 @@ ${YELLOW}${grantNudge.trim()}${NC}
|
|
|
20242
20497
|
break;
|
|
20243
20498
|
}
|
|
20244
20499
|
case "PASS": {
|
|
20245
|
-
|
|
20500
|
+
resetBlockState(currentCommit);
|
|
20246
20501
|
if (watermarkHash) recordPassHash(watermarkHash, baselineSessionId);
|
|
20247
20502
|
if (!watermarkIsPartial && currentCommit && currentCommit !== "no-git") writeBaselineSha(currentCommit);
|
|
20248
20503
|
let userSummary = response.user_summary ?? "Verity: PASS";
|
|
@@ -20263,6 +20518,7 @@ ${YELLOW}${grantNudge.trim()}${NC}
|
|
|
20263
20518
|
break;
|
|
20264
20519
|
}
|
|
20265
20520
|
case "WARN": {
|
|
20521
|
+
if (decision !== "FAIL") resetBlockState(currentCommit);
|
|
20266
20522
|
if (watermarkHash) recordPassHash(watermarkHash, baselineSessionId);
|
|
20267
20523
|
if (!watermarkIsPartial && currentCommit && currentCommit !== "no-git") writeBaselineSha(currentCommit);
|
|
20268
20524
|
let userSummary = response.user_summary ?? "Verity: WARN";
|
|
@@ -20361,7 +20617,7 @@ async function runAnalyze(opts, globals) {
|
|
|
20361
20617
|
}
|
|
20362
20618
|
|
|
20363
20619
|
// src/commands/baseline.ts
|
|
20364
|
-
var
|
|
20620
|
+
var import_node_fs31 = require("node:fs");
|
|
20365
20621
|
function registerBaselineCommands(program2) {
|
|
20366
20622
|
const baseline = program2.command("baseline").description("Manage the task-start working-tree baseline");
|
|
20367
20623
|
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) => {
|
|
@@ -20370,7 +20626,7 @@ function registerBaselineCommands(program2) {
|
|
|
20370
20626
|
process.chdir(repoRoot());
|
|
20371
20627
|
} catch {
|
|
20372
20628
|
}
|
|
20373
|
-
if (!(0,
|
|
20629
|
+
if (!(0, import_node_fs31.existsSync)(VERITY_DIR)) {
|
|
20374
20630
|
process.exit(0);
|
|
20375
20631
|
}
|
|
20376
20632
|
let sessionId = opts.sessionId;
|
|
@@ -20410,7 +20666,7 @@ async function readStdin() {
|
|
|
20410
20666
|
}
|
|
20411
20667
|
|
|
20412
20668
|
// src/commands/review.ts
|
|
20413
|
-
var
|
|
20669
|
+
var import_node_fs32 = require("node:fs");
|
|
20414
20670
|
function registerReviewCommand(program2) {
|
|
20415
20671
|
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) => {
|
|
20416
20672
|
const globals = program2.opts();
|
|
@@ -20429,7 +20685,7 @@ async function runReview(opts, globals) {
|
|
|
20429
20685
|
const securityFiles = filterSecurity(allFiles);
|
|
20430
20686
|
let staticResults;
|
|
20431
20687
|
if (isCodacyAvailable()) {
|
|
20432
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
20688
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs32.existsSync)(f) || resolveFile(f) !== null);
|
|
20433
20689
|
staticResults = runCodacyAnalysis(scannable);
|
|
20434
20690
|
} else {
|
|
20435
20691
|
staticResults = {
|
|
@@ -20455,10 +20711,10 @@ async function runReview(opts, globals) {
|
|
|
20455
20711
|
const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
|
|
20456
20712
|
specs = [];
|
|
20457
20713
|
for (const p of specPaths) {
|
|
20458
|
-
if (!(0,
|
|
20714
|
+
if (!(0, import_node_fs32.existsSync)(p)) continue;
|
|
20459
20715
|
try {
|
|
20460
|
-
const { readFileSync:
|
|
20461
|
-
const content =
|
|
20716
|
+
const { readFileSync: readFileSync19 } = await import("node:fs");
|
|
20717
|
+
const content = readFileSync19(p, "utf-8");
|
|
20462
20718
|
specs.push({ path: p, content: content.slice(0, 10240) });
|
|
20463
20719
|
} catch {
|
|
20464
20720
|
}
|
|
@@ -20515,7 +20771,7 @@ async function runReview(opts, globals) {
|
|
|
20515
20771
|
}
|
|
20516
20772
|
|
|
20517
20773
|
// src/commands/guard.ts
|
|
20518
|
-
var
|
|
20774
|
+
var import_node_fs33 = require("node:fs");
|
|
20519
20775
|
var import_node_path24 = require("node:path");
|
|
20520
20776
|
var GUARD_BLOCK_CAP = 2;
|
|
20521
20777
|
var GUARD_ITER_FILE = (0, import_node_path24.join)(VERITY_DIR, ".guard-iteration");
|
|
@@ -20582,7 +20838,7 @@ function classifyCommand2(command, on) {
|
|
|
20582
20838
|
}
|
|
20583
20839
|
function readIterMap() {
|
|
20584
20840
|
try {
|
|
20585
|
-
const raw = JSON.parse((0,
|
|
20841
|
+
const raw = JSON.parse((0, import_node_fs33.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
20586
20842
|
if (raw && typeof raw === "object") {
|
|
20587
20843
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
20588
20844
|
return { [raw.moment]: raw.count };
|
|
@@ -20602,10 +20858,10 @@ function readIter(moment) {
|
|
|
20602
20858
|
}
|
|
20603
20859
|
function writeIter(moment, count) {
|
|
20604
20860
|
try {
|
|
20605
|
-
(0,
|
|
20861
|
+
(0, import_node_fs33.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
20606
20862
|
const map = readIterMap();
|
|
20607
20863
|
map[moment] = count;
|
|
20608
|
-
(0,
|
|
20864
|
+
(0, import_node_fs33.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
20609
20865
|
} catch {
|
|
20610
20866
|
}
|
|
20611
20867
|
}
|
|
@@ -20615,10 +20871,10 @@ function resetIter(moment) {
|
|
|
20615
20871
|
if (!(moment in map)) return;
|
|
20616
20872
|
delete map[moment];
|
|
20617
20873
|
if (Object.keys(map).length === 0) {
|
|
20618
|
-
if ((0,
|
|
20874
|
+
if ((0, import_node_fs33.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs33.unlinkSync)(GUARD_ITER_FILE);
|
|
20619
20875
|
} else {
|
|
20620
|
-
(0,
|
|
20621
|
-
(0,
|
|
20876
|
+
(0, import_node_fs33.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
20877
|
+
(0, import_node_fs33.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
20622
20878
|
}
|
|
20623
20879
|
} catch {
|
|
20624
20880
|
}
|
|
@@ -20682,7 +20938,7 @@ function buildGuardRequest(moment, files, iter, sessionId, command) {
|
|
|
20682
20938
|
const securityFiles = filterSecurity(files);
|
|
20683
20939
|
let staticResults;
|
|
20684
20940
|
if (isCodacyAvailable()) {
|
|
20685
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
20941
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs33.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
20686
20942
|
staticResults = runCodacyAnalysis(scannable);
|
|
20687
20943
|
} else {
|
|
20688
20944
|
staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
|
|
@@ -20727,7 +20983,7 @@ function emitAllowNotice(userMsg, agentMsg) {
|
|
|
20727
20983
|
async function runGuard(opts, globals) {
|
|
20728
20984
|
const on = opts.on.split(",").map((s) => s.trim()).filter((s) => s === "commit" || s === "push");
|
|
20729
20985
|
const { command, cwd, sessionId } = await readPreToolUseStdin();
|
|
20730
|
-
if (cwd && (0,
|
|
20986
|
+
if (cwd && (0, import_node_fs33.existsSync)(cwd)) {
|
|
20731
20987
|
try {
|
|
20732
20988
|
process.chdir(cwd);
|
|
20733
20989
|
} catch {
|
|
@@ -20833,14 +21089,14 @@ function writeBlockMessage(moment, response) {
|
|
|
20833
21089
|
}
|
|
20834
21090
|
|
|
20835
21091
|
// src/commands/init.ts
|
|
20836
|
-
var
|
|
21092
|
+
var import_node_fs35 = require("node:fs");
|
|
20837
21093
|
var import_promises13 = require("node:fs/promises");
|
|
20838
21094
|
var import_node_path26 = require("node:path");
|
|
20839
21095
|
var import_node_child_process10 = require("node:child_process");
|
|
20840
21096
|
var readline2 = __toESM(require("node:readline/promises"));
|
|
20841
21097
|
|
|
20842
21098
|
// src/commands/migrate.ts
|
|
20843
|
-
var
|
|
21099
|
+
var import_node_fs34 = require("node:fs");
|
|
20844
21100
|
var import_node_path25 = require("node:path");
|
|
20845
21101
|
var import_node_child_process9 = require("node:child_process");
|
|
20846
21102
|
|
|
@@ -20972,10 +21228,10 @@ async function runMigration(opts = {}) {
|
|
|
20972
21228
|
function migrateProjectDir(root, actions) {
|
|
20973
21229
|
const gateDir = (0, import_node_path25.join)(root, ".gate");
|
|
20974
21230
|
const verityDir = (0, import_node_path25.join)(root, ".verity");
|
|
20975
|
-
if ((0,
|
|
21231
|
+
if ((0, import_node_fs34.existsSync)(gateDir) && !(0, import_node_fs34.existsSync)(verityDir)) {
|
|
20976
21232
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
20977
21233
|
}
|
|
20978
|
-
if ((0,
|
|
21234
|
+
if ((0, import_node_fs34.existsSync)(gateDir) && (0, import_node_fs34.existsSync)(verityDir)) {
|
|
20979
21235
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
20980
21236
|
}
|
|
20981
21237
|
return false;
|
|
@@ -20996,13 +21252,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
20996
21252
|
}
|
|
20997
21253
|
}
|
|
20998
21254
|
if (moved) {
|
|
20999
|
-
if ((0,
|
|
21255
|
+
if ((0, import_node_fs34.existsSync)(gateDir)) {
|
|
21000
21256
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
21001
21257
|
if (carried > 0) {
|
|
21002
21258
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
21003
21259
|
}
|
|
21004
21260
|
try {
|
|
21005
|
-
(0,
|
|
21261
|
+
(0, import_node_fs34.rmSync)(gateDir, { recursive: true, force: true });
|
|
21006
21262
|
} catch {
|
|
21007
21263
|
}
|
|
21008
21264
|
}
|
|
@@ -21018,7 +21274,7 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
21018
21274
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
21019
21275
|
}
|
|
21020
21276
|
try {
|
|
21021
|
-
(0,
|
|
21277
|
+
(0, import_node_fs34.rmSync)(gateDir, { recursive: true, force: true });
|
|
21022
21278
|
} catch {
|
|
21023
21279
|
}
|
|
21024
21280
|
return carried > 0;
|
|
@@ -21027,9 +21283,9 @@ function migrateGlobalCredentials(home, actions) {
|
|
|
21027
21283
|
if (!home) return;
|
|
21028
21284
|
const gateCreds = (0, import_node_path25.join)(home, ".gate", "credentials");
|
|
21029
21285
|
const verityCreds = (0, import_node_path25.join)(home, ".verity", "credentials");
|
|
21030
|
-
if (!(0,
|
|
21031
|
-
if (!(0,
|
|
21032
|
-
(0,
|
|
21286
|
+
if (!(0, import_node_fs34.existsSync)(gateCreds)) return;
|
|
21287
|
+
if (!(0, import_node_fs34.existsSync)(verityCreds)) {
|
|
21288
|
+
(0, import_node_fs34.mkdirSync)((0, import_node_path25.join)(home, ".verity"), { recursive: true });
|
|
21033
21289
|
moveFile(gateCreds, verityCreds);
|
|
21034
21290
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
21035
21291
|
return;
|
|
@@ -21052,7 +21308,7 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
21052
21308
|
}
|
|
21053
21309
|
async function migrateClaudeMd(root, actions) {
|
|
21054
21310
|
const claudeMd = (0, import_node_path25.join)(root, "CLAUDE.md");
|
|
21055
|
-
const hadLegacyBlock = (0,
|
|
21311
|
+
const hadLegacyBlock = (0, import_node_fs34.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
21056
21312
|
if (!hadLegacyBlock) return;
|
|
21057
21313
|
try {
|
|
21058
21314
|
await ensureClaudeMdPointer(root);
|
|
@@ -21064,7 +21320,7 @@ async function migrateClaudeMd(root, actions) {
|
|
|
21064
21320
|
function migrateStandardFile(root, actions) {
|
|
21065
21321
|
const gateMd = (0, import_node_path25.join)(root, "GATE.md");
|
|
21066
21322
|
const verityMd = (0, import_node_path25.join)(root, "VERITY.md");
|
|
21067
|
-
if (!(0,
|
|
21323
|
+
if (!(0, import_node_fs34.existsSync)(gateMd) || (0, import_node_fs34.existsSync)(verityMd)) return;
|
|
21068
21324
|
let moved = false;
|
|
21069
21325
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
21070
21326
|
try {
|
|
@@ -21076,12 +21332,12 @@ function migrateStandardFile(root, actions) {
|
|
|
21076
21332
|
if (!moved) moveFile(gateMd, verityMd);
|
|
21077
21333
|
const content = readFileSyncSafe(verityMd);
|
|
21078
21334
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
21079
|
-
if (refreshed !== content) (0,
|
|
21335
|
+
if (refreshed !== content) (0, import_node_fs34.writeFileSync)(verityMd, refreshed);
|
|
21080
21336
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
21081
21337
|
}
|
|
21082
21338
|
async function migrateTelemetryHeaders(root, actions) {
|
|
21083
21339
|
const file = (0, import_node_path25.join)(root, ".claude", "settings.local.json");
|
|
21084
|
-
if (!(0,
|
|
21340
|
+
if (!(0, import_node_fs34.existsSync)(file)) return;
|
|
21085
21341
|
let settings;
|
|
21086
21342
|
try {
|
|
21087
21343
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -21129,14 +21385,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
21129
21385
|
}
|
|
21130
21386
|
if (toAppend.length > 0) {
|
|
21131
21387
|
const sep = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
21132
|
-
(0,
|
|
21388
|
+
(0, import_node_fs34.writeFileSync)(verityCreds, verityContent + sep + toAppend.join("\n") + "\n");
|
|
21133
21389
|
}
|
|
21134
|
-
(0,
|
|
21390
|
+
(0, import_node_fs34.rmSync)(gateCreds, { force: true });
|
|
21135
21391
|
return toAppend.length;
|
|
21136
21392
|
}
|
|
21137
21393
|
function readFileSyncSafe(path) {
|
|
21138
21394
|
try {
|
|
21139
|
-
return (0,
|
|
21395
|
+
return (0, import_node_fs34.readFileSync)(path, "utf-8");
|
|
21140
21396
|
} catch {
|
|
21141
21397
|
return "";
|
|
21142
21398
|
}
|
|
@@ -21151,35 +21407,35 @@ function hasStagedChanges(root) {
|
|
|
21151
21407
|
}
|
|
21152
21408
|
function moveDir(from, to) {
|
|
21153
21409
|
try {
|
|
21154
|
-
(0,
|
|
21410
|
+
(0, import_node_fs34.renameSync)(from, to);
|
|
21155
21411
|
} catch (err) {
|
|
21156
21412
|
if (err.code !== "EXDEV") throw err;
|
|
21157
|
-
(0,
|
|
21158
|
-
(0,
|
|
21413
|
+
(0, import_node_fs34.cpSync)(from, to, { recursive: true });
|
|
21414
|
+
(0, import_node_fs34.rmSync)(from, { recursive: true, force: true });
|
|
21159
21415
|
}
|
|
21160
21416
|
}
|
|
21161
21417
|
function moveFile(from, to) {
|
|
21162
21418
|
try {
|
|
21163
|
-
(0,
|
|
21419
|
+
(0, import_node_fs34.renameSync)(from, to);
|
|
21164
21420
|
} catch (err) {
|
|
21165
21421
|
if (err.code !== "EXDEV") throw err;
|
|
21166
|
-
(0,
|
|
21167
|
-
(0,
|
|
21422
|
+
(0, import_node_fs34.cpSync)(from, to);
|
|
21423
|
+
(0, import_node_fs34.rmSync)(from, { force: true });
|
|
21168
21424
|
}
|
|
21169
21425
|
}
|
|
21170
21426
|
function carryLegacyContents(gateDir, verityDir) {
|
|
21171
21427
|
let copied = 0;
|
|
21172
21428
|
const walk = (relDir) => {
|
|
21173
21429
|
const srcDir = (0, import_node_path25.join)(gateDir, relDir);
|
|
21174
|
-
for (const entry of (0,
|
|
21430
|
+
for (const entry of (0, import_node_fs34.readdirSync)(srcDir)) {
|
|
21175
21431
|
const rel = relDir ? (0, import_node_path25.join)(relDir, entry) : entry;
|
|
21176
21432
|
const src = (0, import_node_path25.join)(gateDir, rel);
|
|
21177
21433
|
const dest = (0, import_node_path25.join)(verityDir, rel);
|
|
21178
|
-
if ((0,
|
|
21434
|
+
if ((0, import_node_fs34.statSync)(src).isDirectory()) {
|
|
21179
21435
|
walk(rel);
|
|
21180
|
-
} else if (!(0,
|
|
21181
|
-
(0,
|
|
21182
|
-
(0,
|
|
21436
|
+
} else if (!(0, import_node_fs34.existsSync)(dest)) {
|
|
21437
|
+
(0, import_node_fs34.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
|
|
21438
|
+
(0, import_node_fs34.cpSync)(src, dest);
|
|
21183
21439
|
copied++;
|
|
21184
21440
|
}
|
|
21185
21441
|
}
|
|
@@ -21190,20 +21446,20 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
21190
21446
|
async function needsMigration(root = repoRoot()) {
|
|
21191
21447
|
const gateDir = (0, import_node_path25.join)(root, ".gate");
|
|
21192
21448
|
const verityDir = (0, import_node_path25.join)(root, ".verity");
|
|
21193
|
-
if ((0,
|
|
21194
|
-
if ((0,
|
|
21195
|
-
if ((0,
|
|
21449
|
+
if ((0, import_node_fs34.existsSync)(gateDir) && !(0, import_node_fs34.existsSync)(verityDir)) return true;
|
|
21450
|
+
if ((0, import_node_fs34.existsSync)(gateDir) && (0, import_node_fs34.existsSync)(verityDir)) {
|
|
21451
|
+
if ((0, import_node_fs34.existsSync)((0, import_node_path25.join)(gateDir, "credentials")) && !(0, import_node_fs34.existsSync)((0, import_node_path25.join)(verityDir, "credentials"))) {
|
|
21196
21452
|
return true;
|
|
21197
21453
|
}
|
|
21198
|
-
if ((0,
|
|
21454
|
+
if ((0, import_node_fs34.existsSync)((0, import_node_path25.join)(gateDir, "memory")) && !(0, import_node_fs34.existsSync)((0, import_node_path25.join)(verityDir, "memory"))) {
|
|
21199
21455
|
return true;
|
|
21200
21456
|
}
|
|
21201
21457
|
}
|
|
21202
21458
|
const claudeMd = (0, import_node_path25.join)(root, "CLAUDE.md");
|
|
21203
|
-
if ((0,
|
|
21459
|
+
if ((0, import_node_fs34.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
21204
21460
|
return true;
|
|
21205
21461
|
}
|
|
21206
|
-
if ((0,
|
|
21462
|
+
if ((0, import_node_fs34.existsSync)((0, import_node_path25.join)(root, "GATE.md")) && !(0, import_node_fs34.existsSync)((0, import_node_path25.join)(root, "VERITY.md"))) {
|
|
21207
21463
|
return true;
|
|
21208
21464
|
}
|
|
21209
21465
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -21345,7 +21601,7 @@ function resolveDataDir() {
|
|
|
21345
21601
|
// local dev: running from repo root
|
|
21346
21602
|
];
|
|
21347
21603
|
for (const candidate of candidates) {
|
|
21348
|
-
if ((0,
|
|
21604
|
+
if ((0, import_node_fs35.existsSync)((0, import_node_path26.join)(candidate, "skills"))) {
|
|
21349
21605
|
return candidate;
|
|
21350
21606
|
}
|
|
21351
21607
|
}
|
|
@@ -21361,7 +21617,7 @@ function registerInitCommand(program2) {
|
|
|
21361
21617
|
program2.command("init").description("Initialize Verity in the current project").option("--force", "Overwrite existing skills and hooks").action(async (opts) => {
|
|
21362
21618
|
const force = opts.force ?? false;
|
|
21363
21619
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
21364
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
21620
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs35.existsSync)(m));
|
|
21365
21621
|
if (!isProject) {
|
|
21366
21622
|
printError("No project detected in the current directory.");
|
|
21367
21623
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -21431,14 +21687,14 @@ function registerInitCommand(program2) {
|
|
|
21431
21687
|
for (const skill of skills) {
|
|
21432
21688
|
const src = (0, import_node_path26.join)(skillsSource, skill);
|
|
21433
21689
|
const dest = (0, import_node_path26.join)(skillsDest, skill);
|
|
21434
|
-
if (!(0,
|
|
21690
|
+
if (!(0, import_node_fs35.existsSync)(src)) {
|
|
21435
21691
|
printWarn(` Skill data not found: ${skill}`);
|
|
21436
21692
|
continue;
|
|
21437
21693
|
}
|
|
21438
|
-
if ((0,
|
|
21694
|
+
if ((0, import_node_fs35.existsSync)(dest) && !force) {
|
|
21439
21695
|
const srcSkill = (0, import_node_path26.join)(src, "SKILL.md");
|
|
21440
21696
|
const destSkill = (0, import_node_path26.join)(dest, "SKILL.md");
|
|
21441
|
-
if ((0,
|
|
21697
|
+
if ((0, import_node_fs35.existsSync)(destSkill)) {
|
|
21442
21698
|
try {
|
|
21443
21699
|
const srcContent = await (0, import_promises13.readFile)(srcSkill, "utf-8");
|
|
21444
21700
|
const destContent = await (0, import_promises13.readFile)(destSkill, "utf-8");
|
|
@@ -21469,6 +21725,12 @@ function registerInitCommand(program2) {
|
|
|
21469
21725
|
}
|
|
21470
21726
|
await (0, import_promises13.mkdir)(VERITY_DIR, { recursive: true });
|
|
21471
21727
|
await ensureMemoryDir();
|
|
21728
|
+
const ignoreResult = ensureSnapshotGitignored();
|
|
21729
|
+
if (ignoreResult === "failed") {
|
|
21730
|
+
printWarn(" .gitignore: could not add .verity/.snapshot/ \u2014 add it manually (it holds copies of analyzed files)");
|
|
21731
|
+
} else {
|
|
21732
|
+
printInfo(` .gitignore: .verity/.snapshot/ ${ignoreResult === "added" ? "added" : "already covered"} \u2713`);
|
|
21733
|
+
}
|
|
21472
21734
|
try {
|
|
21473
21735
|
await ensureClaudeMdPointer();
|
|
21474
21736
|
printInfo(" CLAUDE.md memory pointer \u2713");
|
|
@@ -21510,7 +21772,7 @@ function registerInitCommand(program2) {
|
|
|
21510
21772
|
}
|
|
21511
21773
|
|
|
21512
21774
|
// src/commands/uninstall.ts
|
|
21513
|
-
var
|
|
21775
|
+
var import_node_fs36 = require("node:fs");
|
|
21514
21776
|
var import_node_path27 = require("node:path");
|
|
21515
21777
|
var SKILL_NAMES = [
|
|
21516
21778
|
"verity-setup",
|
|
@@ -21531,10 +21793,10 @@ function registerUninstallCommand(program2) {
|
|
|
21531
21793
|
const skillsRoot = projectPath(".claude/skills");
|
|
21532
21794
|
for (const name of SKILL_NAMES) {
|
|
21533
21795
|
const dir = (0, import_node_path27.join)(skillsRoot, name);
|
|
21534
|
-
if ((0,
|
|
21796
|
+
if ((0, import_node_fs36.existsSync)(dir)) {
|
|
21535
21797
|
actions.push({
|
|
21536
21798
|
label: `Remove .claude/skills/${name}/`,
|
|
21537
|
-
apply: () => (0,
|
|
21799
|
+
apply: () => (0, import_node_fs36.rmSync)(dir, { recursive: true, force: true })
|
|
21538
21800
|
});
|
|
21539
21801
|
}
|
|
21540
21802
|
}
|
|
@@ -21548,24 +21810,24 @@ function registerUninstallCommand(program2) {
|
|
|
21548
21810
|
});
|
|
21549
21811
|
}
|
|
21550
21812
|
const verityDir = projectPath(VERITY_DIR);
|
|
21551
|
-
if ((0,
|
|
21813
|
+
if ((0, import_node_fs36.existsSync)(verityDir)) {
|
|
21552
21814
|
actions.push({
|
|
21553
21815
|
label: `Remove ${VERITY_DIR}/`,
|
|
21554
|
-
apply: () => (0,
|
|
21816
|
+
apply: () => (0, import_node_fs36.rmSync)(verityDir, { recursive: true, force: true })
|
|
21555
21817
|
});
|
|
21556
21818
|
}
|
|
21557
21819
|
if (!keepVerityMd) {
|
|
21558
21820
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
21559
|
-
if ((0,
|
|
21821
|
+
if ((0, import_node_fs36.existsSync)(verityMd)) {
|
|
21560
21822
|
actions.push({
|
|
21561
21823
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
21562
|
-
apply: () => (0,
|
|
21824
|
+
apply: () => (0, import_node_fs36.rmSync)(verityMd, { force: true })
|
|
21563
21825
|
});
|
|
21564
21826
|
}
|
|
21565
21827
|
}
|
|
21566
21828
|
const cleanupEmptyDir = (path) => {
|
|
21567
|
-
if ((0,
|
|
21568
|
-
(0,
|
|
21829
|
+
if ((0, import_node_fs36.existsSync)(path) && (0, import_node_fs36.statSync)(path).isDirectory() && (0, import_node_fs36.readdirSync)(path).length === 0) {
|
|
21830
|
+
(0, import_node_fs36.rmdirSync)(path);
|
|
21569
21831
|
}
|
|
21570
21832
|
};
|
|
21571
21833
|
actions.push({
|
|
@@ -21577,10 +21839,10 @@ function registerUninstallCommand(program2) {
|
|
|
21577
21839
|
});
|
|
21578
21840
|
const home = process.env.HOME ?? "";
|
|
21579
21841
|
const globalVerityDir = (0, import_node_path27.join)(home, ".verity");
|
|
21580
|
-
if (purgeGlobal && (0,
|
|
21842
|
+
if (purgeGlobal && (0, import_node_fs36.existsSync)(globalVerityDir)) {
|
|
21581
21843
|
actions.push({
|
|
21582
21844
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
21583
|
-
apply: () => (0,
|
|
21845
|
+
apply: () => (0, import_node_fs36.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
21584
21846
|
});
|
|
21585
21847
|
}
|
|
21586
21848
|
if (actions.length === 0) {
|
|
@@ -21774,7 +22036,7 @@ function registerTaskCommands(program2) {
|
|
|
21774
22036
|
}
|
|
21775
22037
|
|
|
21776
22038
|
// src/commands/reset.ts
|
|
21777
|
-
var
|
|
22039
|
+
var import_node_fs37 = require("node:fs");
|
|
21778
22040
|
var import_node_path28 = require("node:path");
|
|
21779
22041
|
function registerResetCommand(program2) {
|
|
21780
22042
|
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) => {
|
|
@@ -21812,11 +22074,11 @@ function registerResetCommand(program2) {
|
|
|
21812
22074
|
}
|
|
21813
22075
|
const cacheDir = projectPath(CACHE_DIR);
|
|
21814
22076
|
let purged = 0;
|
|
21815
|
-
if ((0,
|
|
21816
|
-
for (const entry of (0,
|
|
22077
|
+
if ((0, import_node_fs37.existsSync)(cacheDir)) {
|
|
22078
|
+
for (const entry of (0, import_node_fs37.readdirSync)(cacheDir)) {
|
|
21817
22079
|
if (entry.startsWith("pending-")) {
|
|
21818
22080
|
try {
|
|
21819
|
-
(0,
|
|
22081
|
+
(0, import_node_fs37.unlinkSync)((0, import_node_path28.join)(cacheDir, entry));
|
|
21820
22082
|
purged++;
|
|
21821
22083
|
} catch {
|
|
21822
22084
|
}
|
|
@@ -21831,19 +22093,19 @@ function registerResetCommand(program2) {
|
|
|
21831
22093
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
21832
22094
|
];
|
|
21833
22095
|
for (const file of filesToClear) {
|
|
21834
|
-
if ((0,
|
|
22096
|
+
if ((0, import_node_fs37.existsSync)(file)) {
|
|
21835
22097
|
try {
|
|
21836
|
-
(0,
|
|
22098
|
+
(0, import_node_fs37.writeFileSync)(file, "");
|
|
21837
22099
|
} catch {
|
|
21838
22100
|
}
|
|
21839
22101
|
}
|
|
21840
22102
|
}
|
|
21841
22103
|
if (opts.all) {
|
|
21842
22104
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
21843
|
-
if ((0,
|
|
21844
|
-
for (const entry of (0,
|
|
22105
|
+
if ((0, import_node_fs37.existsSync)(logsDir)) {
|
|
22106
|
+
for (const entry of (0, import_node_fs37.readdirSync)(logsDir)) {
|
|
21845
22107
|
try {
|
|
21846
|
-
(0,
|
|
22108
|
+
(0, import_node_fs37.unlinkSync)((0, import_node_path28.join)(logsDir, entry));
|
|
21847
22109
|
} catch {
|
|
21848
22110
|
}
|
|
21849
22111
|
}
|
|
@@ -22151,8 +22413,8 @@ function registerTelemetryCommands(program2) {
|
|
|
22151
22413
|
}
|
|
22152
22414
|
|
|
22153
22415
|
// src/cli.ts
|
|
22154
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.29.4-experimental.
|
|
22155
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.29.4-experimental.
|
|
22416
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.29.4-experimental.7475da6").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) => {
|
|
22417
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.29.4-experimental.7475da6");
|
|
22156
22418
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
22157
22419
|
try {
|
|
22158
22420
|
await foldLegacyLocalCredential();
|
|
@@ -711,18 +711,31 @@ to-be-pushed diff before it lands.
|
|
|
711
711
|
Add these entries to `.gitignore` (create it if it doesn't exist, append if it does):
|
|
712
712
|
|
|
713
713
|
```
|
|
714
|
-
# Verity
|
|
715
|
-
.
|
|
716
|
-
.verity
|
|
717
|
-
.
|
|
718
|
-
|
|
719
|
-
.verity/.last-pass-hash
|
|
720
|
-
.verity/.last-intent
|
|
721
|
-
.verity/.memory-sync-state.json
|
|
714
|
+
# Verity — machine-local state. Everything in .verity/ is ignored EXCEPT the
|
|
715
|
+
# shared standard and the knowledge graph, which are meant to be committed.
|
|
716
|
+
.verity/*
|
|
717
|
+
!.verity/standard.yaml
|
|
718
|
+
!.verity/memory/
|
|
722
719
|
.verity/memory/log.md
|
|
723
720
|
.claude/settings.local.json
|
|
724
721
|
```
|
|
725
722
|
|
|
723
|
+
This is a whitelist on purpose: `.verity/` accumulates state files over time
|
|
724
|
+
(`.snapshot/` holds byte-for-byte copies of analyzed files — including any
|
|
725
|
+
secret the gate just flagged — plus `.cache/`, `.logs/`, `.baseline`,
|
|
726
|
+
`.task-context`, session-suffixed `.last-analysis.*` files, and whatever comes
|
|
727
|
+
next). Enumerating them one by one is how `.snapshot/` ended up committed in a
|
|
728
|
+
real repo; ignoring everything and re-including the two shared artifacts means
|
|
729
|
+
a future state file can never repeat that.
|
|
730
|
+
|
|
731
|
+
**If the repo previously committed Verity state** (check with
|
|
732
|
+
`git ls-files .verity`), untrack everything except the shared artifacts once:
|
|
733
|
+
|
|
734
|
+
```bash
|
|
735
|
+
git rm -r --cached .verity
|
|
736
|
+
git add .verity/standard.yaml .verity/memory
|
|
737
|
+
```
|
|
738
|
+
|
|
726
739
|
`.claude/settings.local.json` is machine-local Claude Code config (telemetry endpoint + an
|
|
727
740
|
`otelHeadersHelper` reference — no token). `verity telemetry install` adds this entry
|
|
728
741
|
automatically.
|
package/package.json
CHANGED