@codacy/verity-cli 0.33.3-experimental.53cd005 → 0.33.3-experimental.5a3f573
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 +25 -0
- package/README.md +3 -0
- package/bin/verity.js +1082 -773
- package/data/skills/verity-init/SKILL.md +174 -76
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -15677,9 +15677,34 @@ async function githubCanSeeRepo(owner, repo, token) {
|
|
|
15677
15677
|
if (res.ok) return { ok: true, data: true };
|
|
15678
15678
|
return { ok: false, error: `GitHub repo lookup failed (HTTP ${res.status})` };
|
|
15679
15679
|
}
|
|
15680
|
-
|
|
15681
|
-
|
|
15682
|
-
|
|
15680
|
+
var CONTROL_CHARS = /[\u0000-\u001f\u007f]/;
|
|
15681
|
+
function isSafeText(v) {
|
|
15682
|
+
return typeof v === "string" && v.length > 0 && v.length < 2048 && !CONTROL_CHARS.test(v);
|
|
15683
|
+
}
|
|
15684
|
+
var GITHUB_DEVICE_VERIFICATION_URL = "https://github.com/login/device";
|
|
15685
|
+
function isGithubDeviceUrl(v) {
|
|
15686
|
+
if (!isSafeText(v)) return false;
|
|
15687
|
+
let url;
|
|
15688
|
+
try {
|
|
15689
|
+
url = new URL(v);
|
|
15690
|
+
} catch {
|
|
15691
|
+
return false;
|
|
15692
|
+
}
|
|
15693
|
+
return url.protocol === "https:" && url.hostname === "github.com" && url.port === "" && url.username === "" && url.password === "" && url.pathname === "/login/device" && url.search === "" && url.hash === "";
|
|
15694
|
+
}
|
|
15695
|
+
async function requestDeviceCode() {
|
|
15696
|
+
if (process.env.VERITY_PROVIDER_TOKEN) {
|
|
15697
|
+
return {
|
|
15698
|
+
ok: true,
|
|
15699
|
+
data: {
|
|
15700
|
+
device_code: "provider-token-override",
|
|
15701
|
+
user_code: "OVER-RIDE",
|
|
15702
|
+
verification_uri: GITHUB_DEVICE_VERIFICATION_URL,
|
|
15703
|
+
expires_in: 900,
|
|
15704
|
+
interval: 0
|
|
15705
|
+
}
|
|
15706
|
+
};
|
|
15707
|
+
}
|
|
15683
15708
|
let dc;
|
|
15684
15709
|
try {
|
|
15685
15710
|
const res = await fetch(GITHUB_DEVICE_CODE_URL, {
|
|
@@ -15700,15 +15725,40 @@ async function githubDeviceFlow() {
|
|
|
15700
15725
|
error: "GitHub did not return a device code (is Device Flow enabled on the OAuth app?)"
|
|
15701
15726
|
};
|
|
15702
15727
|
}
|
|
15703
|
-
|
|
15704
|
-
|
|
15705
|
-
|
|
15728
|
+
if (!isSafeText(dc.device_code) || !isSafeText(dc.user_code) || !isGithubDeviceUrl(dc.verification_uri)) {
|
|
15729
|
+
return { ok: false, error: "GitHub returned invalid device-flow data" };
|
|
15730
|
+
}
|
|
15731
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : null;
|
|
15732
|
+
if (dc.expires_in != null && num(dc.expires_in) === null) {
|
|
15733
|
+
return { ok: false, error: "GitHub returned invalid device-flow data" };
|
|
15734
|
+
}
|
|
15735
|
+
if (dc.interval != null && num(dc.interval) === null) {
|
|
15736
|
+
return { ok: false, error: "GitHub returned invalid device-flow data" };
|
|
15737
|
+
}
|
|
15738
|
+
return {
|
|
15739
|
+
ok: true,
|
|
15740
|
+
data: {
|
|
15741
|
+
device_code: dc.device_code,
|
|
15742
|
+
user_code: dc.user_code,
|
|
15743
|
+
// The canonical form, not the string as received: what is shown and saved
|
|
15744
|
+
// is exactly the page the check above accepted.
|
|
15745
|
+
verification_uri: GITHUB_DEVICE_VERIFICATION_URL,
|
|
15746
|
+
// || (not ??) so a falsy/zero value from the provider floors to a safe
|
|
15747
|
+
// default — a 0 interval would otherwise spin a tight polling loop.
|
|
15748
|
+
expires_in: dc.expires_in || 900,
|
|
15749
|
+
interval: dc.interval || 5
|
|
15750
|
+
}
|
|
15751
|
+
};
|
|
15752
|
+
}
|
|
15753
|
+
async function pollDeviceToken(dc, opts) {
|
|
15754
|
+
const override = process.env.VERITY_PROVIDER_TOKEN;
|
|
15755
|
+
if (override) return { ok: true, data: override };
|
|
15756
|
+
const waitUntil = Math.min(opts.waitUntil ?? opts.codeExpiresAt, opts.codeExpiresAt);
|
|
15706
15757
|
const spinner = startSpinner(`Waiting for you to approve in the browser \xB7 code ${dc.user_code}`);
|
|
15707
|
-
const deadline = Date.now() + (dc.expires_in || 900) * 1e3;
|
|
15708
15758
|
let interval = dc.interval || 5;
|
|
15709
15759
|
try {
|
|
15710
|
-
while (Date.now() <
|
|
15711
|
-
await sleep(interval * 1e3);
|
|
15760
|
+
while (Date.now() < waitUntil) {
|
|
15761
|
+
await sleep(Math.min(interval * 1e3, Math.max(0, waitUntil - Date.now())));
|
|
15712
15762
|
let data;
|
|
15713
15763
|
try {
|
|
15714
15764
|
const res = await fetch(GITHUB_ACCESS_TOKEN_URL, {
|
|
@@ -15736,18 +15786,36 @@ async function githubDeviceFlow() {
|
|
|
15736
15786
|
interval += 5;
|
|
15737
15787
|
break;
|
|
15738
15788
|
case "access_denied":
|
|
15739
|
-
return { ok: false, error: "Authorization was denied on GitHub." };
|
|
15789
|
+
return { ok: false, error: "Authorization was denied on GitHub.", reason: "denied" };
|
|
15740
15790
|
case "expired_token":
|
|
15741
|
-
return { ok: false, error:
|
|
15791
|
+
return { ok: false, error: 'The authorization code expired. Run "verity login" again.', reason: "expired" };
|
|
15742
15792
|
default:
|
|
15743
|
-
if (data.error) return { ok: false, error: `GitHub auth error: ${data.error}
|
|
15793
|
+
if (data.error) return { ok: false, error: `GitHub auth error: ${data.error}`, reason: "error" };
|
|
15744
15794
|
}
|
|
15745
15795
|
}
|
|
15746
|
-
|
|
15796
|
+
if (Date.now() >= opts.codeExpiresAt) {
|
|
15797
|
+
return { ok: false, error: 'The authorization code expired. Run "verity login" again.', reason: "expired" };
|
|
15798
|
+
}
|
|
15799
|
+
return { ok: false, error: "Still waiting for approval on GitHub.", reason: "waiting" };
|
|
15747
15800
|
} finally {
|
|
15748
15801
|
spinner.stop();
|
|
15749
15802
|
}
|
|
15750
15803
|
}
|
|
15804
|
+
async function githubDeviceFlow() {
|
|
15805
|
+
const override = process.env.VERITY_PROVIDER_TOKEN;
|
|
15806
|
+
if (override) return { ok: true, data: override };
|
|
15807
|
+
const code = await requestDeviceCode();
|
|
15808
|
+
if (!code.ok) return code;
|
|
15809
|
+
const dc = code.data;
|
|
15810
|
+
printInfo("");
|
|
15811
|
+
printInfo(`To authorize Verity, open: ${dc.verification_uri}`);
|
|
15812
|
+
printInfo(`And enter the code: ${dc.user_code}`);
|
|
15813
|
+
const polled = await pollDeviceToken(dc, { codeExpiresAt: Date.now() + dc.expires_in * 1e3 });
|
|
15814
|
+
if (!polled.ok) {
|
|
15815
|
+
return { ok: false, error: polled.reason === "waiting" ? "Timed out waiting for GitHub authorization." : polled.error };
|
|
15816
|
+
}
|
|
15817
|
+
return { ok: true, data: polled.data };
|
|
15818
|
+
}
|
|
15751
15819
|
|
|
15752
15820
|
// src/lib/register.ts
|
|
15753
15821
|
var isInteractive = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
@@ -15842,11 +15910,14 @@ function deviceLabel() {
|
|
|
15842
15910
|
}
|
|
15843
15911
|
async function loginOnce(opts) {
|
|
15844
15912
|
const usingTokenOverride = Boolean(process.env.VERITY_PROVIDER_TOKEN);
|
|
15845
|
-
|
|
15846
|
-
if (!
|
|
15847
|
-
|
|
15913
|
+
let providerToken = opts.providerToken;
|
|
15914
|
+
if (!providerToken) {
|
|
15915
|
+
const providerAuth = await githubDeviceFlow();
|
|
15916
|
+
if (!providerAuth.ok) {
|
|
15917
|
+
return { ok: false, error: providerAuth.error };
|
|
15918
|
+
}
|
|
15919
|
+
providerToken = providerAuth.data;
|
|
15848
15920
|
}
|
|
15849
|
-
const providerToken = providerAuth.data;
|
|
15850
15921
|
const parsed = opts.remote ? parseRemote(opts.remote) : null;
|
|
15851
15922
|
if (!usingTokenOverride && parsed && parsed.provider === "github") {
|
|
15852
15923
|
const installed2 = await ensureAppInstalled(parsed.owner, parsed.repo, providerToken);
|
|
@@ -15989,6 +16060,71 @@ function registerAuthCommands(program2) {
|
|
|
15989
16060
|
});
|
|
15990
16061
|
}
|
|
15991
16062
|
|
|
16063
|
+
// src/lib/pending-login.ts
|
|
16064
|
+
var import_node_fs4 = require("node:fs");
|
|
16065
|
+
var import_node_path4 = require("node:path");
|
|
16066
|
+
function pendingLoginPath() {
|
|
16067
|
+
return `${process.env.HOME}/.verity/pending-login.json`;
|
|
16068
|
+
}
|
|
16069
|
+
function savePendingLogin(dc, serviceUrl, now = Date.now()) {
|
|
16070
|
+
const record = {
|
|
16071
|
+
version: 1,
|
|
16072
|
+
device_code: dc.device_code,
|
|
16073
|
+
user_code: dc.user_code,
|
|
16074
|
+
verification_uri: dc.verification_uri,
|
|
16075
|
+
interval: dc.interval,
|
|
16076
|
+
expires_at: new Date(now + dc.expires_in * 1e3).toISOString(),
|
|
16077
|
+
service_url: serviceUrl,
|
|
16078
|
+
created_at: new Date(now).toISOString()
|
|
16079
|
+
};
|
|
16080
|
+
const path = pendingLoginPath();
|
|
16081
|
+
(0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
|
|
16082
|
+
clearPendingLogin();
|
|
16083
|
+
(0, import_node_fs4.writeFileSync)(path, JSON.stringify(record, null, 2) + "\n", { mode: 384, flag: "wx" });
|
|
16084
|
+
try {
|
|
16085
|
+
(0, import_node_fs4.chmodSync)(path, 384);
|
|
16086
|
+
} catch {
|
|
16087
|
+
}
|
|
16088
|
+
return record;
|
|
16089
|
+
}
|
|
16090
|
+
function readPendingLogin(now = Date.now()) {
|
|
16091
|
+
const path = pendingLoginPath();
|
|
16092
|
+
if (!(0, import_node_fs4.existsSync)(path)) return { status: "none" };
|
|
16093
|
+
try {
|
|
16094
|
+
if ((0, import_node_fs4.lstatSync)(path).isSymbolicLink()) return { status: "invalid", reason: "it is a symlink" };
|
|
16095
|
+
} catch {
|
|
16096
|
+
return { status: "none" };
|
|
16097
|
+
}
|
|
16098
|
+
let parsed;
|
|
16099
|
+
try {
|
|
16100
|
+
parsed = JSON.parse((0, import_node_fs4.readFileSync)(path, "utf-8"));
|
|
16101
|
+
} catch {
|
|
16102
|
+
return { status: "invalid", reason: "it is not valid JSON" };
|
|
16103
|
+
}
|
|
16104
|
+
const r = parsed;
|
|
16105
|
+
const str3 = isSafeText;
|
|
16106
|
+
if (!r || typeof r !== "object" || r.version !== 1 || !str3(r.device_code) || !str3(r.user_code) || !str3(r.verification_uri) || !str3(r.service_url) || !str3(r.expires_at) || // ⚠ A NEGATIVE INTERVAL IS A TIGHT LOOP. pollDeviceToken floors only a falsy
|
|
16107
|
+
// one, so -1 would poll GitHub back to back until it answered slow_down.
|
|
16108
|
+
typeof r.interval !== "number" || !Number.isFinite(r.interval) || r.interval < 0) {
|
|
16109
|
+
return { status: "invalid", reason: "it is missing fields" };
|
|
16110
|
+
}
|
|
16111
|
+
if (!isGithubDeviceUrl(r.verification_uri)) {
|
|
16112
|
+
return { status: "invalid", reason: "its verification link is not GitHub's device page" };
|
|
16113
|
+
}
|
|
16114
|
+
const expires = Date.parse(r.expires_at);
|
|
16115
|
+
if (!Number.isFinite(expires)) return { status: "invalid", reason: "its expiry is not a date" };
|
|
16116
|
+
const record = r;
|
|
16117
|
+
return expires <= now ? { status: "expired", record } : { status: "ok", record };
|
|
16118
|
+
}
|
|
16119
|
+
function clearPendingLogin() {
|
|
16120
|
+
try {
|
|
16121
|
+
(0, import_node_fs4.unlinkSync)(pendingLoginPath());
|
|
16122
|
+
return true;
|
|
16123
|
+
} catch {
|
|
16124
|
+
return false;
|
|
16125
|
+
}
|
|
16126
|
+
}
|
|
16127
|
+
|
|
15992
16128
|
// src/lib/login-report.ts
|
|
15993
16129
|
async function reportLoginOutcome(out2, opts = {}) {
|
|
15994
16130
|
const identity = out2.email ?? (out2.userId != null ? `user #${out2.userId}` : "your account");
|
|
@@ -16055,8 +16191,24 @@ async function reportLoginOutcome(out2, opts = {}) {
|
|
|
16055
16191
|
|
|
16056
16192
|
// src/commands/login.ts
|
|
16057
16193
|
function registerLoginCommand(program2) {
|
|
16058
|
-
program2.command("login").description("Log in to Verity (one GitHub login grants access to all your repositories)").option("--force", "Re-authenticate even if already logged in").action(async (opts) => {
|
|
16194
|
+
program2.command("login").description("Log in to Verity (one GitHub login grants access to all your repositories)").option("--force", "Re-authenticate even if already logged in").option("--start", "Show the GitHub code and return at once (finish with --finish); prints JSON").option("--finish", "Wait for approval of the code --start showed, then log in; prints JSON").option("--wait <seconds>", "With --finish: how long to wait for approval before returning", "100").option("--cancel", "Discard a code --start showed that will not be approved").action(async (opts) => {
|
|
16059
16195
|
const globals = program2.opts();
|
|
16196
|
+
const modes = [opts.start, opts.finish, opts.cancel].filter(Boolean).length;
|
|
16197
|
+
if (modes > 1) {
|
|
16198
|
+
printError("Use one of --start, --finish or --cancel.");
|
|
16199
|
+
process.exit(1);
|
|
16200
|
+
}
|
|
16201
|
+
if (opts.cancel) {
|
|
16202
|
+
const removed = clearPendingLogin();
|
|
16203
|
+
printInfo(removed ? "Discarded the pending sign-in." : "No sign-in was pending.");
|
|
16204
|
+
printJson({ status: removed ? "cancelled" : "no_pending" });
|
|
16205
|
+
return;
|
|
16206
|
+
}
|
|
16207
|
+
const split = !!(opts.start || opts.finish);
|
|
16208
|
+
if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE || process.env.CLAUDE_SESSION_ID)) {
|
|
16209
|
+
printWarn("Inside a Claude Code session the code below may not be visible until this command ends.");
|
|
16210
|
+
printWarn(' Use "verity login --start", then "verity login --finish" once it is approved.');
|
|
16211
|
+
}
|
|
16060
16212
|
const resolution = await resolveServiceUrlForAuth(globals.serviceUrl);
|
|
16061
16213
|
if (resolution.source === "default") {
|
|
16062
16214
|
printInfo(`No Verity service configured on this machine \u2014 using the default: ${resolution.url}`);
|
|
@@ -16069,6 +16221,10 @@ function registerLoginCommand(program2) {
|
|
|
16069
16221
|
printInfo(" Completing login updates ~/.verity/credentials against the live service.");
|
|
16070
16222
|
}
|
|
16071
16223
|
const remote = currentRemote();
|
|
16224
|
+
if (opts.finish) {
|
|
16225
|
+
await finishSplitLogin({ serviceUrl, remote, verbose: globals.verbose, waitSeconds: opts.wait });
|
|
16226
|
+
return;
|
|
16227
|
+
}
|
|
16072
16228
|
if (remote && !parseRemote(remote)) {
|
|
16073
16229
|
printWarn(`This repository's origin remote is not a recognizable git URL: ${remote}`);
|
|
16074
16230
|
printInfo(" Verity cannot identify the repository from it, so runs here will not be saved.");
|
|
@@ -16083,6 +16239,14 @@ function registerLoginCommand(program2) {
|
|
|
16083
16239
|
if (!nudge && !upgrade) {
|
|
16084
16240
|
printInfo(`Already logged in as ${who.data.email ?? `user #${who.data.user_id}`}. \u2713`);
|
|
16085
16241
|
printInfo(" Re-authenticate with: verity login --force");
|
|
16242
|
+
if (split) {
|
|
16243
|
+
printJson({
|
|
16244
|
+
status: "logged_in",
|
|
16245
|
+
email: who.data.email ?? null,
|
|
16246
|
+
repo_covered: who.data.grant_status != null,
|
|
16247
|
+
already: true
|
|
16248
|
+
});
|
|
16249
|
+
}
|
|
16086
16250
|
return;
|
|
16087
16251
|
}
|
|
16088
16252
|
if (nudge) {
|
|
@@ -16098,6 +16262,34 @@ function registerLoginCommand(program2) {
|
|
|
16098
16262
|
printWarn("Could not confirm your current login state with the service \u2014 proceeding to log in.");
|
|
16099
16263
|
}
|
|
16100
16264
|
}
|
|
16265
|
+
if (opts.start) {
|
|
16266
|
+
const code = await requestDeviceCode();
|
|
16267
|
+
if (!code.ok) {
|
|
16268
|
+
printError(`Login failed: ${code.error}`);
|
|
16269
|
+
printJson({ status: "failed", error: code.error });
|
|
16270
|
+
process.exit(1);
|
|
16271
|
+
}
|
|
16272
|
+
let pending;
|
|
16273
|
+
try {
|
|
16274
|
+
pending = savePendingLogin(code.data, serviceUrl);
|
|
16275
|
+
} catch (err2) {
|
|
16276
|
+
const error = `could not save the pending sign-in: ${err2.message}`;
|
|
16277
|
+
printError(`Login failed: ${error}`);
|
|
16278
|
+
printJson({ status: "failed", error });
|
|
16279
|
+
process.exit(1);
|
|
16280
|
+
}
|
|
16281
|
+
printInfo(`To authorize Verity, open: ${pending.verification_uri}`);
|
|
16282
|
+
printInfo(`And enter the code: ${pending.user_code}`);
|
|
16283
|
+
printInfo(` Then run "verity login --finish". The code expires at ${pending.expires_at}.`);
|
|
16284
|
+
printJson({
|
|
16285
|
+
status: "pending",
|
|
16286
|
+
verification_uri: pending.verification_uri,
|
|
16287
|
+
user_code: pending.user_code,
|
|
16288
|
+
expires_at: pending.expires_at,
|
|
16289
|
+
service_url: pending.service_url
|
|
16290
|
+
});
|
|
16291
|
+
return;
|
|
16292
|
+
}
|
|
16101
16293
|
printInfo("Authenticating with GitHub\u2026");
|
|
16102
16294
|
const result = await loginOnce({ serviceUrl, remote: remote || void 0, verbose: globals.verbose });
|
|
16103
16295
|
if (!result.ok) {
|
|
@@ -16107,6 +16299,64 @@ function registerLoginCommand(program2) {
|
|
|
16107
16299
|
await reportLoginOutcome(result.data, { remote: remote || void 0, verbose: globals.verbose });
|
|
16108
16300
|
});
|
|
16109
16301
|
}
|
|
16302
|
+
var MAX_WAIT_SECONDS = 600;
|
|
16303
|
+
async function finishSplitLogin(opts) {
|
|
16304
|
+
function fail(status, error, clear) {
|
|
16305
|
+
if (clear) clearPendingLogin();
|
|
16306
|
+
printError(`Login failed: ${error}`);
|
|
16307
|
+
printJson({ status, error });
|
|
16308
|
+
process.exit(1);
|
|
16309
|
+
}
|
|
16310
|
+
const wait = Number(String(opts.waitSeconds ?? "100").trim());
|
|
16311
|
+
if (!Number.isInteger(wait) || wait < 0 || wait > MAX_WAIT_SECONDS) {
|
|
16312
|
+
fail("invalid", `--wait must be a whole number of seconds from 0 to ${MAX_WAIT_SECONDS}`, false);
|
|
16313
|
+
}
|
|
16314
|
+
const read2 = readPendingLogin();
|
|
16315
|
+
if (read2.status === "none") fail("no_pending", 'no sign-in is pending \u2014 run "verity login --start" first', false);
|
|
16316
|
+
if (read2.status === "invalid") fail("invalid", `the pending sign-in is unusable (${read2.reason}) \u2014 run "verity login --start" again`, true);
|
|
16317
|
+
if (read2.status === "expired") fail("expired", 'the code expired before it was approved \u2014 run "verity login --start" again', true);
|
|
16318
|
+
const pending = read2.record;
|
|
16319
|
+
if (pending.service_url !== opts.serviceUrl) {
|
|
16320
|
+
fail(
|
|
16321
|
+
"service_changed",
|
|
16322
|
+
`the sign-in was started for ${pending.service_url}, but this machine now resolves ${opts.serviceUrl} \u2014 run "verity login --start" again`,
|
|
16323
|
+
true
|
|
16324
|
+
);
|
|
16325
|
+
}
|
|
16326
|
+
const polled = await pollDeviceToken(pending, {
|
|
16327
|
+
codeExpiresAt: Date.parse(pending.expires_at),
|
|
16328
|
+
waitUntil: Date.now() + wait * 1e3
|
|
16329
|
+
});
|
|
16330
|
+
if (!polled.ok) {
|
|
16331
|
+
if (polled.reason === "waiting") {
|
|
16332
|
+
printInfo(`Not approved yet. Enter ${pending.user_code} at ${pending.verification_uri}, then run "verity login --finish" again.`);
|
|
16333
|
+
printJson({
|
|
16334
|
+
status: "pending",
|
|
16335
|
+
verification_uri: pending.verification_uri,
|
|
16336
|
+
user_code: pending.user_code,
|
|
16337
|
+
expires_at: pending.expires_at
|
|
16338
|
+
});
|
|
16339
|
+
process.exit(2);
|
|
16340
|
+
}
|
|
16341
|
+
fail(polled.reason, polled.error, true);
|
|
16342
|
+
}
|
|
16343
|
+
clearPendingLogin();
|
|
16344
|
+
const result = await loginOnce({
|
|
16345
|
+
serviceUrl: opts.serviceUrl,
|
|
16346
|
+
remote: opts.remote || void 0,
|
|
16347
|
+
verbose: opts.verbose,
|
|
16348
|
+
providerToken: polled.data
|
|
16349
|
+
});
|
|
16350
|
+
if (!result.ok) fail("failed", result.error, false);
|
|
16351
|
+
const data = result.data;
|
|
16352
|
+
await reportLoginOutcome(data, { remote: opts.remote || void 0, verbose: opts.verbose });
|
|
16353
|
+
printJson({
|
|
16354
|
+
status: "logged_in",
|
|
16355
|
+
email: data.email ?? null,
|
|
16356
|
+
repo_count: data.repoCount,
|
|
16357
|
+
expires_at: data.expiresAt ?? null
|
|
16358
|
+
});
|
|
16359
|
+
}
|
|
16110
16360
|
|
|
16111
16361
|
// src/commands/token.ts
|
|
16112
16362
|
function registerTokenCommand(program2) {
|
|
@@ -16424,11 +16674,11 @@ function registerLogoutCommand(program2) {
|
|
|
16424
16674
|
|
|
16425
16675
|
// src/lib/hooks.ts
|
|
16426
16676
|
var import_promises4 = require("node:fs/promises");
|
|
16427
|
-
var
|
|
16677
|
+
var import_node_path6 = require("node:path");
|
|
16428
16678
|
|
|
16429
16679
|
// src/lib/json-file.ts
|
|
16430
16680
|
var import_promises3 = require("node:fs/promises");
|
|
16431
|
-
var
|
|
16681
|
+
var import_node_path5 = require("node:path");
|
|
16432
16682
|
function jsonSemanticEqual(a, b) {
|
|
16433
16683
|
if (a === b) return true;
|
|
16434
16684
|
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
|
|
@@ -16474,7 +16724,7 @@ async function writeJsonFilePreservingStyle(file, value) {
|
|
|
16474
16724
|
const indent = currentRaw !== null ? detectJsonIndent(currentRaw) : 2;
|
|
16475
16725
|
const next = JSON.stringify(value, null, indent) + "\n";
|
|
16476
16726
|
if (next === currentRaw) return false;
|
|
16477
|
-
await (0, import_promises3.mkdir)((0,
|
|
16727
|
+
await (0, import_promises3.mkdir)((0, import_node_path5.dirname)(file), { recursive: true });
|
|
16478
16728
|
await (0, import_promises3.writeFile)(file, next);
|
|
16479
16729
|
return true;
|
|
16480
16730
|
}
|
|
@@ -16659,13 +16909,13 @@ async function writeSettings(settings) {
|
|
|
16659
16909
|
}
|
|
16660
16910
|
async function readSettingsAt(root) {
|
|
16661
16911
|
try {
|
|
16662
|
-
return JSON.parse(await (0, import_promises4.readFile)((0,
|
|
16912
|
+
return JSON.parse(await (0, import_promises4.readFile)((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
|
|
16663
16913
|
} catch {
|
|
16664
16914
|
return {};
|
|
16665
16915
|
}
|
|
16666
16916
|
}
|
|
16667
16917
|
async function writeSettingsAt(root, settings) {
|
|
16668
|
-
await writeJsonFilePreservingStyle((0,
|
|
16918
|
+
await writeJsonFilePreservingStyle((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), settings);
|
|
16669
16919
|
}
|
|
16670
16920
|
async function hasLegacyHooksAt(root) {
|
|
16671
16921
|
const settings = await readSettingsAt(root);
|
|
@@ -16854,8 +17104,8 @@ async function applyMomentSelection(moments) {
|
|
|
16854
17104
|
}
|
|
16855
17105
|
|
|
16856
17106
|
// src/lib/project-config.ts
|
|
16857
|
-
var
|
|
16858
|
-
var
|
|
17107
|
+
var import_node_fs5 = require("node:fs");
|
|
17108
|
+
var import_node_path7 = require("node:path");
|
|
16859
17109
|
var DEFAULTS = { git_moments: [] };
|
|
16860
17110
|
function isMoment(value) {
|
|
16861
17111
|
return value === "commit" || value === "push";
|
|
@@ -16865,8 +17115,8 @@ function parseMoments(raw) {
|
|
|
16865
17115
|
}
|
|
16866
17116
|
function readConfigFile(path) {
|
|
16867
17117
|
try {
|
|
16868
|
-
if (!(0,
|
|
16869
|
-
const raw = JSON.parse((0,
|
|
17118
|
+
if (!(0, import_node_fs5.existsSync)(path)) return null;
|
|
17119
|
+
const raw = JSON.parse((0, import_node_fs5.readFileSync)(path, "utf-8"));
|
|
16870
17120
|
const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
|
|
16871
17121
|
const source2 = raw.git_moments_source === "user" || raw.git_moments_source === "init" ? raw.git_moments_source : void 0;
|
|
16872
17122
|
return {
|
|
@@ -16883,7 +17133,7 @@ function candidates() {
|
|
|
16883
17133
|
const out2 = [{ path: local, source: "local" }];
|
|
16884
17134
|
const main = mainWorktreeRoot();
|
|
16885
17135
|
if (main) {
|
|
16886
|
-
const inherited = (0,
|
|
17136
|
+
const inherited = (0, import_node_path7.join)(main, PROJECT_CONFIG_FILE);
|
|
16887
17137
|
if (inherited !== local) out2.push({ path: inherited, source: "main-worktree" });
|
|
16888
17138
|
}
|
|
16889
17139
|
return out2;
|
|
@@ -16904,8 +17154,8 @@ function writeProjectConfig(patch) {
|
|
|
16904
17154
|
...patch
|
|
16905
17155
|
};
|
|
16906
17156
|
const target = projectPath(PROJECT_CONFIG_FILE);
|
|
16907
|
-
(0,
|
|
16908
|
-
(0,
|
|
17157
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path7.dirname)(target), { recursive: true });
|
|
17158
|
+
(0, import_node_fs5.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
|
|
16909
17159
|
return next;
|
|
16910
17160
|
}
|
|
16911
17161
|
function resolveGuardMoments(explicit) {
|
|
@@ -16914,11 +17164,11 @@ function resolveGuardMoments(explicit) {
|
|
|
16914
17164
|
}
|
|
16915
17165
|
|
|
16916
17166
|
// src/lib/plugin-ownership.ts
|
|
16917
|
-
var
|
|
17167
|
+
var import_node_fs8 = require("node:fs");
|
|
16918
17168
|
|
|
16919
17169
|
// src/lib/which.ts
|
|
16920
|
-
var
|
|
16921
|
-
var
|
|
17170
|
+
var import_node_fs6 = require("node:fs");
|
|
17171
|
+
var import_node_path8 = require("node:path");
|
|
16922
17172
|
function executableExtensions(platform4, pathext) {
|
|
16923
17173
|
if (platform4 !== "win32") return [""];
|
|
16924
17174
|
const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
@@ -16936,14 +17186,14 @@ function whichSync(bin, opts = {}) {
|
|
|
16936
17186
|
if (!rawPath) return null;
|
|
16937
17187
|
const exts = executableExtensions(platform4, opts.pathext ?? process.env.PATHEXT);
|
|
16938
17188
|
const real = opts.real ?? true;
|
|
16939
|
-
for (const dir of rawPath.split(
|
|
17189
|
+
for (const dir of rawPath.split(import_node_path8.delimiter)) {
|
|
16940
17190
|
if (!dir) continue;
|
|
16941
17191
|
for (const ext of exts) {
|
|
16942
|
-
const candidate = (0,
|
|
17192
|
+
const candidate = (0, import_node_path8.join)(dir, bin + ext);
|
|
16943
17193
|
try {
|
|
16944
|
-
if (!(0,
|
|
16945
|
-
if (platform4 !== "win32") (0,
|
|
16946
|
-
return real ? (0,
|
|
17194
|
+
if (!(0, import_node_fs6.statSync)(candidate).isFile()) continue;
|
|
17195
|
+
if (platform4 !== "win32") (0, import_node_fs6.accessSync)(candidate, import_node_fs6.constants.X_OK);
|
|
17196
|
+
return real ? (0, import_node_fs6.realpathSync)(candidate) : candidate;
|
|
16947
17197
|
} catch {
|
|
16948
17198
|
continue;
|
|
16949
17199
|
}
|
|
@@ -16954,10 +17204,10 @@ function whichSync(bin, opts = {}) {
|
|
|
16954
17204
|
|
|
16955
17205
|
// src/lib/plugin-ownership.ts
|
|
16956
17206
|
var import_node_os2 = require("node:os");
|
|
16957
|
-
var
|
|
17207
|
+
var import_node_path9 = require("node:path");
|
|
16958
17208
|
|
|
16959
17209
|
// src/lib/stderr-log.ts
|
|
16960
|
-
var
|
|
17210
|
+
var import_node_fs7 = require("node:fs");
|
|
16961
17211
|
var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
|
|
16962
17212
|
var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
16963
17213
|
function scrub(s) {
|
|
@@ -16970,9 +17220,9 @@ function append(text) {
|
|
|
16970
17220
|
try {
|
|
16971
17221
|
const dir = projectPath(DEBUG_LOG_DIR);
|
|
16972
17222
|
const file = projectPath(STDERR_LOG_FILE);
|
|
16973
|
-
(0,
|
|
17223
|
+
(0, import_node_fs7.mkdirSync)(dir, { recursive: true });
|
|
16974
17224
|
rotateIfNeeded(file);
|
|
16975
|
-
(0,
|
|
17225
|
+
(0, import_node_fs7.appendFileSync)(file, text);
|
|
16976
17226
|
} catch {
|
|
16977
17227
|
}
|
|
16978
17228
|
}
|
|
@@ -17011,7 +17261,7 @@ function logToFileOnly(text) {
|
|
|
17011
17261
|
}
|
|
17012
17262
|
|
|
17013
17263
|
// src/lib/plugin-ownership.ts
|
|
17014
|
-
var
|
|
17264
|
+
var CONTROL_CHARS2 = /[\u0000-\u001f\u007f]/;
|
|
17015
17265
|
function isPluginInvocation() {
|
|
17016
17266
|
return !!process.env.VERITY_PLUGIN_ROOT;
|
|
17017
17267
|
}
|
|
@@ -17020,11 +17270,11 @@ function markerPath() {
|
|
|
17020
17270
|
}
|
|
17021
17271
|
function readMarker() {
|
|
17022
17272
|
try {
|
|
17023
|
-
if (!(0,
|
|
17024
|
-
const raw = JSON.parse((0,
|
|
17273
|
+
if (!(0, import_node_fs8.existsSync)(markerPath())) return null;
|
|
17274
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(markerPath(), "utf-8"));
|
|
17025
17275
|
const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
|
|
17026
|
-
if (!pluginRoot ||
|
|
17027
|
-
const version = typeof raw.version === "string" && !
|
|
17276
|
+
if (!pluginRoot || CONTROL_CHARS2.test(pluginRoot)) return null;
|
|
17277
|
+
const version = typeof raw.version === "string" && !CONTROL_CHARS2.test(raw.version) ? raw.version : null;
|
|
17028
17278
|
return {
|
|
17029
17279
|
session_id: typeof raw.session_id === "string" ? raw.session_id : null,
|
|
17030
17280
|
plugin_root: pluginRoot,
|
|
@@ -17039,23 +17289,23 @@ function recordPluginOwnership(sessionId) {
|
|
|
17039
17289
|
const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
17040
17290
|
if (!pluginRoot) return;
|
|
17041
17291
|
try {
|
|
17042
|
-
(0,
|
|
17292
|
+
(0, import_node_fs8.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
17043
17293
|
const marker = {
|
|
17044
17294
|
session_id: sessionId,
|
|
17045
17295
|
plugin_root: pluginRoot,
|
|
17046
17296
|
version: process.env.VERITY_PLUGIN_VERSION || null,
|
|
17047
17297
|
ts: Math.floor(Date.now() / 1e3)
|
|
17048
17298
|
};
|
|
17049
|
-
(0,
|
|
17299
|
+
(0, import_node_fs8.writeFileSync)(markerPath(), JSON.stringify(marker));
|
|
17050
17300
|
} catch {
|
|
17051
17301
|
}
|
|
17052
17302
|
}
|
|
17053
17303
|
function claudeConfigDir() {
|
|
17054
|
-
return process.env.CLAUDE_CONFIG_DIR || (0,
|
|
17304
|
+
return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path9.join)((0, import_node_os2.homedir)(), ".claude");
|
|
17055
17305
|
}
|
|
17056
17306
|
function readJsonFile(path) {
|
|
17057
17307
|
try {
|
|
17058
|
-
const parsed = JSON.parse((0,
|
|
17308
|
+
const parsed = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf-8"));
|
|
17059
17309
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
17060
17310
|
} catch {
|
|
17061
17311
|
return null;
|
|
@@ -17063,9 +17313,9 @@ function readJsonFile(path) {
|
|
|
17063
17313
|
}
|
|
17064
17314
|
function enabledPluginSetting(key) {
|
|
17065
17315
|
const files = [
|
|
17066
|
-
projectPath((0,
|
|
17067
|
-
projectPath((0,
|
|
17068
|
-
(0,
|
|
17316
|
+
projectPath((0, import_node_path9.join)(".claude", "settings.local.json")),
|
|
17317
|
+
projectPath((0, import_node_path9.join)(".claude", "settings.json")),
|
|
17318
|
+
(0, import_node_path9.join)(claudeConfigDir(), "settings.json")
|
|
17069
17319
|
];
|
|
17070
17320
|
for (const file of files) {
|
|
17071
17321
|
const map = readJsonFile(file)?.enabledPlugins;
|
|
@@ -17077,11 +17327,11 @@ function enabledPluginSetting(key) {
|
|
|
17077
17327
|
}
|
|
17078
17328
|
function marketplaceLocations() {
|
|
17079
17329
|
const out2 = /* @__PURE__ */ new Map();
|
|
17080
|
-
const known = readJsonFile((0,
|
|
17330
|
+
const known = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
17081
17331
|
if (!known) return out2;
|
|
17082
17332
|
for (const [name2, entry] of Object.entries(known)) {
|
|
17083
17333
|
const loc2 = entry?.installLocation;
|
|
17084
|
-
if (typeof loc2 === "string" && loc2) out2.set(name2, (0,
|
|
17334
|
+
if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path9.resolve)(loc2));
|
|
17085
17335
|
}
|
|
17086
17336
|
return out2;
|
|
17087
17337
|
}
|
|
@@ -17095,7 +17345,7 @@ function globalVerityVersion() {
|
|
|
17095
17345
|
const entry = verityPathEntry();
|
|
17096
17346
|
if (!entry) return null;
|
|
17097
17347
|
try {
|
|
17098
|
-
const pkg = readJsonFile((0,
|
|
17348
|
+
const pkg = readJsonFile((0, import_node_path9.join)((0, import_node_path9.dirname)((0, import_node_fs8.realpathSync)(entry)), "..", "package.json"));
|
|
17099
17349
|
if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
|
|
17100
17350
|
return pkg.version;
|
|
17101
17351
|
} catch {
|
|
@@ -17112,7 +17362,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
|
|
|
17112
17362
|
function marketplaceConflict() {
|
|
17113
17363
|
const wanted = VERITY_MARKETPLACE;
|
|
17114
17364
|
for (const file of ["settings.json", "settings.local.json"]) {
|
|
17115
|
-
const path = (0,
|
|
17365
|
+
const path = (0, import_node_path9.join)(claudeConfigDir(), file);
|
|
17116
17366
|
const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
|
|
17117
17367
|
const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
|
|
17118
17368
|
if (entry2 && typeof entry2 === "object") {
|
|
@@ -17122,7 +17372,7 @@ function marketplaceConflict() {
|
|
|
17122
17372
|
}
|
|
17123
17373
|
}
|
|
17124
17374
|
}
|
|
17125
|
-
const known = readJsonFile((0,
|
|
17375
|
+
const known = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
17126
17376
|
const entry = known?.[wanted];
|
|
17127
17377
|
if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
|
|
17128
17378
|
return { name: wanted, declaredAs: describeSource(entry.source) };
|
|
@@ -17143,7 +17393,7 @@ function describeSource(src) {
|
|
|
17143
17393
|
return target ? `${kind} \u2192 ${target}` : kind;
|
|
17144
17394
|
}
|
|
17145
17395
|
function legacyMarketplaceInstall() {
|
|
17146
|
-
const plugins = readJsonFile((0,
|
|
17396
|
+
const plugins = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17147
17397
|
if (!plugins || typeof plugins !== "object") return null;
|
|
17148
17398
|
for (const key of Object.keys(plugins)) {
|
|
17149
17399
|
const at = key.lastIndexOf("@");
|
|
@@ -17155,13 +17405,13 @@ function legacyMarketplaceInstall() {
|
|
|
17155
17405
|
}
|
|
17156
17406
|
function realpathOr(p) {
|
|
17157
17407
|
try {
|
|
17158
|
-
return
|
|
17408
|
+
return import_node_fs8.realpathSync.native(p);
|
|
17159
17409
|
} catch {
|
|
17160
|
-
return (0,
|
|
17410
|
+
return (0, import_node_path9.resolve)(p);
|
|
17161
17411
|
}
|
|
17162
17412
|
}
|
|
17163
17413
|
function isWithin(want, dir) {
|
|
17164
|
-
return want === dir || want.startsWith(dir +
|
|
17414
|
+
return want === dir || want.startsWith(dir + import_node_path9.sep);
|
|
17165
17415
|
}
|
|
17166
17416
|
function entryAppliesHere(entry, here) {
|
|
17167
17417
|
const e = entry;
|
|
@@ -17171,9 +17421,9 @@ function entryAppliesHere(entry, here) {
|
|
|
17171
17421
|
return forProject === here;
|
|
17172
17422
|
}
|
|
17173
17423
|
function registrySays(pluginRoot) {
|
|
17174
|
-
const plugins = readJsonFile((0,
|
|
17424
|
+
const plugins = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17175
17425
|
if (!plugins || typeof plugins !== "object") return "unverified";
|
|
17176
|
-
const want = (0,
|
|
17426
|
+
const want = (0, import_node_path9.resolve)(pluginRoot);
|
|
17177
17427
|
const here = realpathOr(repoRoot());
|
|
17178
17428
|
const markets = marketplaceLocations();
|
|
17179
17429
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -17182,15 +17432,15 @@ function registrySays(pluginRoot) {
|
|
|
17182
17432
|
const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
|
|
17183
17433
|
const claims = applicable.some((entry) => {
|
|
17184
17434
|
const installPath = entry?.installPath;
|
|
17185
|
-
return typeof installPath === "string" && (0,
|
|
17435
|
+
return typeof installPath === "string" && (0, import_node_path9.resolve)(installPath) === want;
|
|
17186
17436
|
}) || source2 !== void 0 && applicable.length > 0 && isWithin(want, source2);
|
|
17187
17437
|
if (claims) {
|
|
17188
17438
|
if (enabledPluginSetting(key) === false) return "gone";
|
|
17189
|
-
return (0,
|
|
17439
|
+
return (0, import_node_fs8.existsSync)(pluginRoot) ? "live" : "gone";
|
|
17190
17440
|
}
|
|
17191
17441
|
}
|
|
17192
|
-
const managed = (0,
|
|
17193
|
-
return want === managed || want.startsWith(managed +
|
|
17442
|
+
const managed = (0, import_node_path9.resolve)((0, import_node_path9.join)(claudeConfigDir(), "plugins", "cache"));
|
|
17443
|
+
return want === managed || want.startsWith(managed + import_node_path9.sep) ? "gone" : "unverified";
|
|
17194
17444
|
}
|
|
17195
17445
|
var _live = /* @__PURE__ */ new Map();
|
|
17196
17446
|
function pluginLiveness(pluginRoot) {
|
|
@@ -17204,7 +17454,7 @@ function clearStalePluginMarker() {
|
|
|
17204
17454
|
const marker = readMarker();
|
|
17205
17455
|
if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
|
|
17206
17456
|
try {
|
|
17207
|
-
(0,
|
|
17457
|
+
(0, import_node_fs8.rmSync)(markerPath(), { force: true });
|
|
17208
17458
|
} catch {
|
|
17209
17459
|
return null;
|
|
17210
17460
|
}
|
|
@@ -17232,7 +17482,7 @@ function pluginActiveHere() {
|
|
|
17232
17482
|
return activePluginInstall() !== null;
|
|
17233
17483
|
}
|
|
17234
17484
|
function registeredVerityPlugin() {
|
|
17235
|
-
const plugins = readJsonFile((0,
|
|
17485
|
+
const plugins = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17236
17486
|
if (!plugins || typeof plugins !== "object") return null;
|
|
17237
17487
|
const here = realpathOr(repoRoot());
|
|
17238
17488
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -17242,7 +17492,7 @@ function registeredVerityPlugin() {
|
|
|
17242
17492
|
for (const entry of Array.isArray(value) ? value : []) {
|
|
17243
17493
|
const e = entry;
|
|
17244
17494
|
const installPath = typeof e.installPath === "string" ? e.installPath : "";
|
|
17245
|
-
if (!installPath || !(0,
|
|
17495
|
+
if (!installPath || !(0, import_node_fs8.existsSync)(installPath)) continue;
|
|
17246
17496
|
if (!entryAppliesHere(entry, here)) continue;
|
|
17247
17497
|
return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
|
|
17248
17498
|
}
|
|
@@ -17294,28 +17544,28 @@ async function resolveHookWiring() {
|
|
|
17294
17544
|
}
|
|
17295
17545
|
|
|
17296
17546
|
// src/lib/cli-provenance.ts
|
|
17297
|
-
var
|
|
17547
|
+
var import_node_fs9 = require("node:fs");
|
|
17298
17548
|
var import_node_os3 = require("node:os");
|
|
17299
|
-
var
|
|
17549
|
+
var import_node_path10 = require("node:path");
|
|
17300
17550
|
var CLI_PACKAGE = "@codacy/verity-cli";
|
|
17301
|
-
var CLI_ENTRY = (0,
|
|
17551
|
+
var CLI_ENTRY = (0, import_node_path10.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
|
|
17302
17552
|
function readJson(path) {
|
|
17303
17553
|
try {
|
|
17304
|
-
const parsed = JSON.parse((0,
|
|
17554
|
+
const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf-8"));
|
|
17305
17555
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
17306
17556
|
} catch {
|
|
17307
17557
|
return null;
|
|
17308
17558
|
}
|
|
17309
17559
|
}
|
|
17310
17560
|
function versionUnder(base) {
|
|
17311
|
-
const entry = (0,
|
|
17312
|
-
if (!(0,
|
|
17313
|
-
const pkg = readJson((0,
|
|
17561
|
+
const entry = (0, import_node_path10.join)(base, CLI_ENTRY);
|
|
17562
|
+
if (!(0, import_node_fs9.existsSync)(entry)) return null;
|
|
17563
|
+
const pkg = readJson((0, import_node_path10.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
|
|
17314
17564
|
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
17315
17565
|
}
|
|
17316
17566
|
function versionForEntry(entry) {
|
|
17317
17567
|
try {
|
|
17318
|
-
const pkg = readJson((0,
|
|
17568
|
+
const pkg = readJson((0, import_node_path10.join)((0, import_node_path10.dirname)((0, import_node_fs9.realpathSync)(entry)), "..", "package.json"));
|
|
17319
17569
|
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
17320
17570
|
} catch {
|
|
17321
17571
|
return null;
|
|
@@ -17323,16 +17573,16 @@ function versionForEntry(entry) {
|
|
|
17323
17573
|
}
|
|
17324
17574
|
function resolveHooksCli(pluginRoot) {
|
|
17325
17575
|
const override = process.env.VERITY_CLI_PATH;
|
|
17326
|
-
if (override && (0,
|
|
17576
|
+
if (override && (0, import_node_fs9.existsSync)(override)) {
|
|
17327
17577
|
return { version: versionForEntry(override), rung: "override" };
|
|
17328
17578
|
}
|
|
17329
17579
|
const fromPlugin = versionUnder(pluginRoot);
|
|
17330
17580
|
if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
|
|
17331
|
-
if ((0,
|
|
17332
|
-
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0,
|
|
17581
|
+
if ((0, import_node_fs9.existsSync)((0, import_node_path10.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
|
|
17582
|
+
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path10.join)((0, import_node_os3.homedir)(), ".verity", "plugin-cli");
|
|
17333
17583
|
const fromData = versionUnder(dataDir);
|
|
17334
17584
|
if (fromData !== null) return { version: fromData, rung: "plugin-data" };
|
|
17335
|
-
if ((0,
|
|
17585
|
+
if ((0, import_node_fs9.existsSync)((0, import_node_path10.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
|
|
17336
17586
|
const global = globalVerityVersion();
|
|
17337
17587
|
if (global !== null) return { version: global, rung: "global" };
|
|
17338
17588
|
return null;
|
|
@@ -17434,7 +17684,7 @@ function pluginCliInvocation() {
|
|
|
17434
17684
|
return resolverCommand(root);
|
|
17435
17685
|
}
|
|
17436
17686
|
function resolverCommand(root) {
|
|
17437
|
-
return `node ${JSON.stringify((0,
|
|
17687
|
+
return `node ${JSON.stringify((0, import_node_path10.join)(root, "scripts", "verity.mjs"))}`;
|
|
17438
17688
|
}
|
|
17439
17689
|
|
|
17440
17690
|
// src/commands/hooks.ts
|
|
@@ -17574,7 +17824,7 @@ var import_node_crypto9 = require("node:crypto");
|
|
|
17574
17824
|
|
|
17575
17825
|
// src/lib/conversation-buffer.ts
|
|
17576
17826
|
var import_promises5 = require("node:fs/promises");
|
|
17577
|
-
var
|
|
17827
|
+
var import_node_fs10 = require("node:fs");
|
|
17578
17828
|
var import_node_child_process5 = require("node:child_process");
|
|
17579
17829
|
var import_node_crypto = require("node:crypto");
|
|
17580
17830
|
function stripImageReferences(text) {
|
|
@@ -17610,7 +17860,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
17610
17860
|
}
|
|
17611
17861
|
async function readAndClearConversationBuffer(currentSessionId) {
|
|
17612
17862
|
try {
|
|
17613
|
-
if ((0,
|
|
17863
|
+
if ((0, import_node_fs10.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
17614
17864
|
const entries = await readBufferEntries();
|
|
17615
17865
|
let mine = entries;
|
|
17616
17866
|
let others = [];
|
|
@@ -17634,7 +17884,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
|
|
|
17634
17884
|
};
|
|
17635
17885
|
}
|
|
17636
17886
|
}
|
|
17637
|
-
if ((0,
|
|
17887
|
+
if ((0, import_node_fs10.existsSync)(INTENT_FILE)) {
|
|
17638
17888
|
try {
|
|
17639
17889
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
17640
17890
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -17927,9 +18177,9 @@ function isCommandOnlyTurn(input) {
|
|
|
17927
18177
|
|
|
17928
18178
|
// src/lib/context-identity.ts
|
|
17929
18179
|
var import_node_crypto2 = require("node:crypto");
|
|
17930
|
-
var
|
|
18180
|
+
var import_node_fs11 = require("node:fs");
|
|
17931
18181
|
var import_node_os4 = require("node:os");
|
|
17932
|
-
var
|
|
18182
|
+
var import_node_path11 = require("node:path");
|
|
17933
18183
|
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
17934
18184
|
"",
|
|
17935
18185
|
"-",
|
|
@@ -17967,7 +18217,7 @@ function contextIdentity(input) {
|
|
|
17967
18217
|
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
17968
18218
|
let resolved = rawTree;
|
|
17969
18219
|
try {
|
|
17970
|
-
resolved =
|
|
18220
|
+
resolved = import_node_fs11.realpathSync.native(rawTree);
|
|
17971
18221
|
} catch {
|
|
17972
18222
|
}
|
|
17973
18223
|
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
@@ -17983,13 +18233,13 @@ function contextIdentity(input) {
|
|
|
17983
18233
|
}
|
|
17984
18234
|
function verityHome() {
|
|
17985
18235
|
const override = process.env.VERITY_HOME;
|
|
17986
|
-
return override && override.trim() ? (0,
|
|
18236
|
+
return override && override.trim() ? (0, import_node_path11.resolve)(override) : (0, import_node_path11.join)((0, import_node_os4.homedir)(), ".verity");
|
|
17987
18237
|
}
|
|
17988
18238
|
function dossierDir(identity) {
|
|
17989
|
-
return (0,
|
|
18239
|
+
return (0, import_node_path11.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
17990
18240
|
}
|
|
17991
18241
|
function treeDir(identity) {
|
|
17992
|
-
return (0,
|
|
18242
|
+
return (0, import_node_path11.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
|
|
17993
18243
|
}
|
|
17994
18244
|
function scopeIdentity(token, sessionId) {
|
|
17995
18245
|
const t = (token ?? "").trim();
|
|
@@ -18004,8 +18254,8 @@ function sessionScopeKey(token, sessionId) {
|
|
|
18004
18254
|
|
|
18005
18255
|
// src/lib/task-context-buffer.ts
|
|
18006
18256
|
var import_promises6 = require("node:fs/promises");
|
|
18007
|
-
var
|
|
18008
|
-
var
|
|
18257
|
+
var import_node_fs12 = require("node:fs");
|
|
18258
|
+
var import_node_path12 = require("node:path");
|
|
18009
18259
|
var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
|
|
18010
18260
|
var MAX_BUFFER_BYTES = 500 * 1024;
|
|
18011
18261
|
var MAX_PROMPT_CHARS = 2e3;
|
|
@@ -18044,7 +18294,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
|
|
|
18044
18294
|
}
|
|
18045
18295
|
async function readTaskContextBuffer(taskId) {
|
|
18046
18296
|
const filePath = bufferPath(taskId);
|
|
18047
|
-
if (!(0,
|
|
18297
|
+
if (!(0, import_node_fs12.existsSync)(filePath)) return null;
|
|
18048
18298
|
try {
|
|
18049
18299
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
18050
18300
|
if (!content.trim()) return null;
|
|
@@ -18078,12 +18328,12 @@ async function readTaskContextBuffer(taskId) {
|
|
|
18078
18328
|
}
|
|
18079
18329
|
async function cleanupTaskContextBuffers() {
|
|
18080
18330
|
try {
|
|
18081
|
-
if (!(0,
|
|
18331
|
+
if (!(0, import_node_fs12.existsSync)(TASK_CONTEXT_DIR)) return;
|
|
18082
18332
|
const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
|
|
18083
18333
|
const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
18084
18334
|
for (const file of files) {
|
|
18085
18335
|
if (!file.endsWith(".jsonl")) continue;
|
|
18086
|
-
const filePath = (0,
|
|
18336
|
+
const filePath = (0, import_node_path12.join)(TASK_CONTEXT_DIR, file);
|
|
18087
18337
|
try {
|
|
18088
18338
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
18089
18339
|
if (stats.mtimeMs < cutoffMs) {
|
|
@@ -18097,13 +18347,13 @@ async function cleanupTaskContextBuffers() {
|
|
|
18097
18347
|
}
|
|
18098
18348
|
function bufferPath(taskId) {
|
|
18099
18349
|
const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
18100
|
-
return (0,
|
|
18350
|
+
return (0, import_node_path12.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
|
|
18101
18351
|
}
|
|
18102
18352
|
async function appendEntry(taskId, entry) {
|
|
18103
18353
|
try {
|
|
18104
18354
|
await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
|
|
18105
18355
|
const filePath = bufferPath(taskId);
|
|
18106
|
-
if ((0,
|
|
18356
|
+
if ((0, import_node_fs12.existsSync)(filePath)) {
|
|
18107
18357
|
const stats = await (0, import_promises6.stat)(filePath);
|
|
18108
18358
|
if (stats.size >= MAX_BUFFER_BYTES) {
|
|
18109
18359
|
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
@@ -18114,7 +18364,7 @@ async function appendEntry(taskId, entry) {
|
|
|
18114
18364
|
}
|
|
18115
18365
|
}
|
|
18116
18366
|
const line2 = JSON.stringify(entry) + "\n";
|
|
18117
|
-
const existing = (0,
|
|
18367
|
+
const existing = (0, import_node_fs12.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
|
|
18118
18368
|
await (0, import_promises6.writeFile)(filePath, existing + line2);
|
|
18119
18369
|
} catch {
|
|
18120
18370
|
}
|
|
@@ -18122,20 +18372,20 @@ async function appendEntry(taskId, entry) {
|
|
|
18122
18372
|
|
|
18123
18373
|
// src/lib/memory-retrieval.ts
|
|
18124
18374
|
var import_promises8 = require("node:fs/promises");
|
|
18125
|
-
var
|
|
18126
|
-
var
|
|
18375
|
+
var import_node_fs15 = require("node:fs");
|
|
18376
|
+
var import_node_path15 = require("node:path");
|
|
18127
18377
|
|
|
18128
18378
|
// src/lib/org-mirror.ts
|
|
18129
|
-
var
|
|
18379
|
+
var import_node_fs13 = require("node:fs");
|
|
18130
18380
|
var import_promises7 = require("node:fs/promises");
|
|
18131
|
-
var
|
|
18381
|
+
var import_node_path13 = require("node:path");
|
|
18132
18382
|
var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
|
|
18133
18383
|
var STATE_FILE = ".org-pull-state.json";
|
|
18134
18384
|
var BODY_MAX = 8192;
|
|
18135
18385
|
function orgMirrorDir(remote = requestRemote()) {
|
|
18136
18386
|
const parsed = parseRemote(remote);
|
|
18137
18387
|
if (!parsed) return null;
|
|
18138
|
-
return (0,
|
|
18388
|
+
return (0, import_node_path13.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
|
|
18139
18389
|
}
|
|
18140
18390
|
function slugify(s) {
|
|
18141
18391
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
@@ -18201,7 +18451,7 @@ function parseOrgNode(content) {
|
|
|
18201
18451
|
}
|
|
18202
18452
|
async function readState(dir) {
|
|
18203
18453
|
try {
|
|
18204
|
-
const parsed = JSON.parse(await (0, import_promises7.readFile)((0,
|
|
18454
|
+
const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path13.join)(dir, STATE_FILE), "utf-8"));
|
|
18205
18455
|
return {
|
|
18206
18456
|
version: typeof parsed?.version === "string" ? parsed.version : null,
|
|
18207
18457
|
organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
|
|
@@ -18213,7 +18463,7 @@ async function readState(dir) {
|
|
|
18213
18463
|
}
|
|
18214
18464
|
async function writeState(dir, state) {
|
|
18215
18465
|
await (0, import_promises7.mkdir)(dir, { recursive: true });
|
|
18216
|
-
await (0, import_promises7.writeFile)((0,
|
|
18466
|
+
await (0, import_promises7.writeFile)((0, import_node_path13.join)(dir, STATE_FILE), JSON.stringify({
|
|
18217
18467
|
...state.version ? { version: state.version } : {},
|
|
18218
18468
|
organization: state.organization,
|
|
18219
18469
|
pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -18278,24 +18528,24 @@ async function pullOrgKnowledge(opts) {
|
|
|
18278
18528
|
for (const n of nodes) {
|
|
18279
18529
|
const rel = orgNodePath(n);
|
|
18280
18530
|
if (written.has(rel)) continue;
|
|
18281
|
-
await (0, import_promises7.mkdir)((0,
|
|
18282
|
-
await (0, import_promises7.writeFile)((0,
|
|
18531
|
+
await (0, import_promises7.mkdir)((0, import_node_path13.join)(dir, rel.split("/")[0]), { recursive: true });
|
|
18532
|
+
await (0, import_promises7.writeFile)((0, import_node_path13.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
|
|
18283
18533
|
written.add(rel);
|
|
18284
18534
|
}
|
|
18285
18535
|
for (const rel of state.files) {
|
|
18286
|
-
if (!written.has(rel)) await (0, import_promises7.rm)((0,
|
|
18536
|
+
if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path13.join)(dir, rel), { force: true });
|
|
18287
18537
|
}
|
|
18288
|
-
await (0, import_promises7.writeFile)((0,
|
|
18538
|
+
await (0, import_promises7.writeFile)((0, import_node_path13.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
|
|
18289
18539
|
await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
|
|
18290
18540
|
return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
|
|
18291
18541
|
}
|
|
18292
18542
|
async function readOrgMirror(remote = requestRemote()) {
|
|
18293
18543
|
const dir = orgMirrorDir(remote);
|
|
18294
|
-
if (!dir || !(0,
|
|
18544
|
+
if (!dir || !(0, import_node_fs13.existsSync)(dir)) return [];
|
|
18295
18545
|
const out2 = [];
|
|
18296
18546
|
for (const kind of ORG_KINDS) {
|
|
18297
|
-
const kindDir = (0,
|
|
18298
|
-
if (!(0,
|
|
18547
|
+
const kindDir = (0, import_node_path13.join)(dir, kind);
|
|
18548
|
+
if (!(0, import_node_fs13.existsSync)(kindDir)) continue;
|
|
18299
18549
|
let files;
|
|
18300
18550
|
try {
|
|
18301
18551
|
files = await (0, import_promises7.readdir)(kindDir);
|
|
@@ -18305,7 +18555,7 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
18305
18555
|
for (const file of files) {
|
|
18306
18556
|
if (!file.endsWith(".md")) continue;
|
|
18307
18557
|
try {
|
|
18308
|
-
const node = parseOrgNode(await (0, import_promises7.readFile)((0,
|
|
18558
|
+
const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path13.join)(kindDir, file), "utf-8"));
|
|
18309
18559
|
if (node) out2.push(node);
|
|
18310
18560
|
} catch {
|
|
18311
18561
|
}
|
|
@@ -18315,29 +18565,29 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
18315
18565
|
}
|
|
18316
18566
|
|
|
18317
18567
|
// src/lib/safe-read.ts
|
|
18318
|
-
var
|
|
18319
|
-
var
|
|
18320
|
-
var FLAGS =
|
|
18568
|
+
var import_node_fs14 = require("node:fs");
|
|
18569
|
+
var import_node_path14 = require("node:path");
|
|
18570
|
+
var FLAGS = import_node_fs14.constants;
|
|
18321
18571
|
var NOFOLLOW = FLAGS.O_NOFOLLOW;
|
|
18322
18572
|
var NONBLOCK = FLAGS.O_NONBLOCK;
|
|
18323
18573
|
function closeOpened(fd) {
|
|
18324
18574
|
try {
|
|
18325
|
-
(0,
|
|
18575
|
+
(0, import_node_fs14.closeSync)(fd);
|
|
18326
18576
|
} catch {
|
|
18327
18577
|
}
|
|
18328
18578
|
}
|
|
18329
18579
|
function isInsideRoot(realRoot, realPath) {
|
|
18330
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
18580
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path14.sep) ? realRoot : realRoot + import_node_path14.sep);
|
|
18331
18581
|
}
|
|
18332
18582
|
function sameOpenedFile(opened, current, nofollowAvailable) {
|
|
18333
18583
|
if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
|
|
18334
18584
|
return opened.ino === current.ino && opened.dev === current.dev;
|
|
18335
18585
|
}
|
|
18336
18586
|
function openRegularInRoot(root, path) {
|
|
18337
|
-
const full = (0,
|
|
18587
|
+
const full = (0, import_node_path14.isAbsolute)(path) ? path : (0, import_node_path14.join)(root, path);
|
|
18338
18588
|
let fd;
|
|
18339
18589
|
try {
|
|
18340
|
-
fd = (0,
|
|
18590
|
+
fd = (0, import_node_fs14.openSync)(full, import_node_fs14.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
|
|
18341
18591
|
} catch (err2) {
|
|
18342
18592
|
const code = err2.code;
|
|
18343
18593
|
if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
|
|
@@ -18345,18 +18595,18 @@ function openRegularInRoot(root, path) {
|
|
|
18345
18595
|
return { ok: false, reason: "unreadable" };
|
|
18346
18596
|
}
|
|
18347
18597
|
try {
|
|
18348
|
-
const opened = (0,
|
|
18598
|
+
const opened = (0, import_node_fs14.fstatSync)(fd, { bigint: true });
|
|
18349
18599
|
if (!opened.isFile()) {
|
|
18350
18600
|
closeOpened(fd);
|
|
18351
18601
|
return { ok: false, reason: "not-regular" };
|
|
18352
18602
|
}
|
|
18353
|
-
const realRoot =
|
|
18354
|
-
const realPath =
|
|
18603
|
+
const realRoot = import_node_fs14.realpathSync.native(root);
|
|
18604
|
+
const realPath = import_node_fs14.realpathSync.native(full);
|
|
18355
18605
|
if (!isInsideRoot(realRoot, realPath)) {
|
|
18356
18606
|
closeOpened(fd);
|
|
18357
18607
|
return { ok: false, reason: "outside-root" };
|
|
18358
18608
|
}
|
|
18359
|
-
const current = (0,
|
|
18609
|
+
const current = (0, import_node_fs14.statSync)(realPath, { bigint: true });
|
|
18360
18610
|
if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
|
|
18361
18611
|
closeOpened(fd);
|
|
18362
18612
|
return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
|
|
@@ -18378,7 +18628,7 @@ function readOpened(fd, size) {
|
|
|
18378
18628
|
const buffer = Buffer.alloc(size);
|
|
18379
18629
|
let offset = 0;
|
|
18380
18630
|
while (offset < size) {
|
|
18381
|
-
const n = (0,
|
|
18631
|
+
const n = (0, import_node_fs14.readSync)(fd, buffer, offset, size - offset, offset);
|
|
18382
18632
|
if (n === 0) break;
|
|
18383
18633
|
offset += n;
|
|
18384
18634
|
}
|
|
@@ -18693,14 +18943,14 @@ function parseFrontmatter(content) {
|
|
|
18693
18943
|
return { fm, body: match[2].trim() };
|
|
18694
18944
|
}
|
|
18695
18945
|
async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
|
|
18696
|
-
const hasRepoGraph = (0,
|
|
18946
|
+
const hasRepoGraph = (0, import_node_fs15.existsSync)(memoryDir());
|
|
18697
18947
|
const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
|
|
18698
18948
|
const promptTokens = tokenize(promptText);
|
|
18699
18949
|
const orgPromptTerms = orgTerms(promptText);
|
|
18700
18950
|
const nodes = [];
|
|
18701
18951
|
for (const domain of hasRepoGraph ? DOMAINS : []) {
|
|
18702
|
-
const domainDir = (0,
|
|
18703
|
-
if (!(0,
|
|
18952
|
+
const domainDir = (0, import_node_path15.join)(memoryDir(), domain);
|
|
18953
|
+
if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
|
|
18704
18954
|
try {
|
|
18705
18955
|
const files = await (0, import_promises8.readdir)(domainDir);
|
|
18706
18956
|
for (const file of files) {
|
|
@@ -18774,27 +19024,27 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
|
|
|
18774
19024
|
}
|
|
18775
19025
|
|
|
18776
19026
|
// src/lib/injection-record.ts
|
|
18777
|
-
var
|
|
19027
|
+
var import_node_fs17 = require("node:fs");
|
|
18778
19028
|
var import_node_crypto3 = require("node:crypto");
|
|
18779
19029
|
|
|
18780
19030
|
// src/lib/safe-write.ts
|
|
18781
|
-
var
|
|
18782
|
-
var
|
|
18783
|
-
var FLAGS2 =
|
|
19031
|
+
var import_node_fs16 = require("node:fs");
|
|
19032
|
+
var import_node_path16 = require("node:path");
|
|
19033
|
+
var FLAGS2 = import_node_fs16.constants;
|
|
18784
19034
|
var O_NOFOLLOW = FLAGS2.O_NOFOLLOW ?? 0;
|
|
18785
19035
|
var NOFOLLOW_AVAILABLE = O_NOFOLLOW !== 0;
|
|
18786
19036
|
function validateRoot(root) {
|
|
18787
19037
|
try {
|
|
18788
|
-
const parentReal = (0,
|
|
18789
|
-
const expected = (0,
|
|
19038
|
+
const parentReal = (0, import_node_fs16.realpathSync)((0, import_node_path16.dirname)(root));
|
|
19039
|
+
const expected = (0, import_node_path16.join)(parentReal, (0, import_node_path16.basename)(root));
|
|
18790
19040
|
try {
|
|
18791
|
-
(0,
|
|
19041
|
+
(0, import_node_fs16.mkdirSync)(expected);
|
|
18792
19042
|
} catch (e) {
|
|
18793
19043
|
if (e.code !== "EEXIST") return null;
|
|
18794
19044
|
}
|
|
18795
|
-
const st = (0,
|
|
19045
|
+
const st = (0, import_node_fs16.lstatSync)(expected, { bigint: true });
|
|
18796
19046
|
if (st.isSymbolicLink() || !st.isDirectory()) return null;
|
|
18797
|
-
if ((0,
|
|
19047
|
+
if ((0, import_node_fs16.realpathSync)(expected) !== expected) return null;
|
|
18798
19048
|
return { real: expected, dev: st.dev, ino: st.ino };
|
|
18799
19049
|
} catch {
|
|
18800
19050
|
return null;
|
|
@@ -18802,18 +19052,18 @@ function validateRoot(root) {
|
|
|
18802
19052
|
}
|
|
18803
19053
|
function rootUnchanged(root) {
|
|
18804
19054
|
try {
|
|
18805
|
-
const st = (0,
|
|
19055
|
+
const st = (0, import_node_fs16.lstatSync)(root.real, { bigint: true });
|
|
18806
19056
|
return !st.isSymbolicLink() && st.isDirectory() && st.dev === root.dev && st.ino === root.ino;
|
|
18807
19057
|
} catch {
|
|
18808
19058
|
return false;
|
|
18809
19059
|
}
|
|
18810
19060
|
}
|
|
18811
19061
|
function bareName(name2) {
|
|
18812
|
-
return !!name2 && name2 === (0,
|
|
19062
|
+
return !!name2 && name2 === (0, import_node_path16.basename)(name2) && name2 !== "." && name2 !== ".." && !name2.includes("\0");
|
|
18813
19063
|
}
|
|
18814
19064
|
function absentOrRegular(path) {
|
|
18815
19065
|
try {
|
|
18816
|
-
const st = (0,
|
|
19066
|
+
const st = (0, import_node_fs16.lstatSync)(path);
|
|
18817
19067
|
return st.isFile() && !st.isSymbolicLink();
|
|
18818
19068
|
} catch (e) {
|
|
18819
19069
|
return e.code === "ENOENT";
|
|
@@ -18821,11 +19071,11 @@ function absentOrRegular(path) {
|
|
|
18821
19071
|
}
|
|
18822
19072
|
function verifyOpened(fd, path, root) {
|
|
18823
19073
|
try {
|
|
18824
|
-
const opened = (0,
|
|
19074
|
+
const opened = (0, import_node_fs16.fstatSync)(fd, { bigint: true });
|
|
18825
19075
|
if (!opened.isFile() || opened.nlink !== 1n) return false;
|
|
18826
|
-
const real = (0,
|
|
19076
|
+
const real = (0, import_node_fs16.realpathSync)(path);
|
|
18827
19077
|
if (!isInsideRoot(root.real, real)) return false;
|
|
18828
|
-
const current = (0,
|
|
19078
|
+
const current = (0, import_node_fs16.statSync)(real, { bigint: true });
|
|
18829
19079
|
if (!sameOpenedFile(opened, current, NOFOLLOW_AVAILABLE)) return false;
|
|
18830
19080
|
return rootUnchanged(root);
|
|
18831
19081
|
} catch {
|
|
@@ -18834,21 +19084,21 @@ function verifyOpened(fd, path, root) {
|
|
|
18834
19084
|
}
|
|
18835
19085
|
function removeIfOurs(fd, path) {
|
|
18836
19086
|
try {
|
|
18837
|
-
const opened = (0,
|
|
18838
|
-
const at = (0,
|
|
18839
|
-
if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0,
|
|
19087
|
+
const opened = (0, import_node_fs16.fstatSync)(fd, { bigint: true });
|
|
19088
|
+
const at = (0, import_node_fs16.lstatSync)(path, { bigint: true });
|
|
19089
|
+
if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0, import_node_fs16.unlinkSync)(path);
|
|
18840
19090
|
} catch {
|
|
18841
19091
|
}
|
|
18842
19092
|
}
|
|
18843
19093
|
function openTarget(path, append2) {
|
|
18844
|
-
const base =
|
|
19094
|
+
const base = import_node_fs16.constants.O_WRONLY | (append2 ? import_node_fs16.constants.O_APPEND : 0) | O_NOFOLLOW;
|
|
18845
19095
|
try {
|
|
18846
|
-
return { fd: (0,
|
|
19096
|
+
return { fd: (0, import_node_fs16.openSync)(path, base), created: false };
|
|
18847
19097
|
} catch (e) {
|
|
18848
19098
|
if (e.code !== "ENOENT") return null;
|
|
18849
19099
|
}
|
|
18850
19100
|
try {
|
|
18851
|
-
return { fd: (0,
|
|
19101
|
+
return { fd: (0, import_node_fs16.openSync)(path, base | import_node_fs16.constants.O_CREAT | import_node_fs16.constants.O_EXCL, 384), created: true };
|
|
18852
19102
|
} catch {
|
|
18853
19103
|
return null;
|
|
18854
19104
|
}
|
|
@@ -18856,7 +19106,7 @@ function openTarget(path, append2) {
|
|
|
18856
19106
|
function writeVerified(root, name2, hooks, append2, write) {
|
|
18857
19107
|
const r = validateRoot(root);
|
|
18858
19108
|
if (!r || !bareName(name2)) return false;
|
|
18859
|
-
const path = (0,
|
|
19109
|
+
const path = (0, import_node_path16.join)(r.real, name2);
|
|
18860
19110
|
if (!absentOrRegular(path)) return false;
|
|
18861
19111
|
if (!runHook(hooks)) return false;
|
|
18862
19112
|
const opened = openTarget(path, append2);
|
|
@@ -18872,7 +19122,7 @@ function writeVerified(root, name2, hooks, append2, write) {
|
|
|
18872
19122
|
return false;
|
|
18873
19123
|
} finally {
|
|
18874
19124
|
try {
|
|
18875
|
-
(0,
|
|
19125
|
+
(0, import_node_fs16.closeSync)(opened.fd);
|
|
18876
19126
|
} catch {
|
|
18877
19127
|
}
|
|
18878
19128
|
}
|
|
@@ -18887,13 +19137,13 @@ function runHook(hooks) {
|
|
|
18887
19137
|
}
|
|
18888
19138
|
function appendInRoot(root, name2, text, hooks = {}) {
|
|
18889
19139
|
return writeVerified(root, name2, hooks, true, (fd) => {
|
|
18890
|
-
(0,
|
|
19140
|
+
(0, import_node_fs16.writeSync)(fd, text);
|
|
18891
19141
|
});
|
|
18892
19142
|
}
|
|
18893
19143
|
function replaceInRoot(root, name2, text, hooks = {}) {
|
|
18894
19144
|
return writeVerified(root, name2, hooks, false, (fd) => {
|
|
18895
|
-
(0,
|
|
18896
|
-
(0,
|
|
19145
|
+
(0, import_node_fs16.ftruncateSync)(fd, 0);
|
|
19146
|
+
(0, import_node_fs16.writeSync)(fd, text, 0);
|
|
18897
19147
|
});
|
|
18898
19148
|
}
|
|
18899
19149
|
|
|
@@ -18941,7 +19191,7 @@ function hashPrompt(prompt) {
|
|
|
18941
19191
|
function recordInjection(event) {
|
|
18942
19192
|
if (!appendInRoot(projectPath(VERITY_DIR), "injections.jsonl", JSON.stringify(event) + "\n")) return;
|
|
18943
19193
|
try {
|
|
18944
|
-
if ((0,
|
|
19194
|
+
if ((0, import_node_fs17.lstatSync)(recordPath()).size > COMPACT_AT_BYTES) writeEvents(readPendingInjections());
|
|
18945
19195
|
} catch {
|
|
18946
19196
|
}
|
|
18947
19197
|
}
|
|
@@ -18951,7 +19201,7 @@ function writeEvents(events) {
|
|
|
18951
19201
|
function readPendingInjections() {
|
|
18952
19202
|
try {
|
|
18953
19203
|
const p = recordPath();
|
|
18954
|
-
if (!(0,
|
|
19204
|
+
if (!(0, import_node_fs17.existsSync)(p)) return [];
|
|
18955
19205
|
const read2 = readRegularFileInRoot(projectPath(VERITY_DIR), "injections.jsonl", MAX_RECORD_BYTES);
|
|
18956
19206
|
if (!read2.ok) return [];
|
|
18957
19207
|
const out2 = [];
|
|
@@ -18971,13 +19221,13 @@ function readPendingInjections() {
|
|
|
18971
19221
|
|
|
18972
19222
|
// src/lib/memory-sync.ts
|
|
18973
19223
|
var import_promises9 = require("node:fs/promises");
|
|
18974
|
-
var
|
|
18975
|
-
var
|
|
19224
|
+
var import_node_fs20 = require("node:fs");
|
|
19225
|
+
var import_node_path18 = require("node:path");
|
|
18976
19226
|
var import_node_crypto4 = require("node:crypto");
|
|
18977
19227
|
|
|
18978
19228
|
// src/lib/gitignore.ts
|
|
18979
19229
|
var import_node_child_process6 = require("node:child_process");
|
|
18980
|
-
var
|
|
19230
|
+
var import_node_fs18 = require("node:fs");
|
|
18981
19231
|
var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
|
|
18982
19232
|
var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
|
|
18983
19233
|
var VERITY_GITIGNORE_BLOCK = [
|
|
@@ -19061,7 +19311,7 @@ function fenceMemoryLines(lines) {
|
|
|
19061
19311
|
function ensureVerityGitignore() {
|
|
19062
19312
|
let content = "";
|
|
19063
19313
|
try {
|
|
19064
|
-
content = (0,
|
|
19314
|
+
content = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
|
|
19065
19315
|
} catch {
|
|
19066
19316
|
}
|
|
19067
19317
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -19088,7 +19338,7 @@ function ensureVerityGitignore() {
|
|
|
19088
19338
|
const sep5 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
19089
19339
|
text = text + sep5 + VERITY_GITIGNORE_BLOCK;
|
|
19090
19340
|
}
|
|
19091
|
-
if (text !== content) (0,
|
|
19341
|
+
if (text !== content) (0, import_node_fs18.writeFileSync)(".gitignore", text);
|
|
19092
19342
|
return verified(
|
|
19093
19343
|
memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
|
|
19094
19344
|
);
|
|
@@ -19108,7 +19358,7 @@ function untrackMemory() {
|
|
|
19108
19358
|
function writeFencedBlock() {
|
|
19109
19359
|
let content = "";
|
|
19110
19360
|
try {
|
|
19111
|
-
content = (0,
|
|
19361
|
+
content = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
|
|
19112
19362
|
} catch {
|
|
19113
19363
|
}
|
|
19114
19364
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
@@ -19120,7 +19370,7 @@ function writeFencedBlock() {
|
|
|
19120
19370
|
text = text + sep5 + VERITY_GITIGNORE_BLOCK;
|
|
19121
19371
|
}
|
|
19122
19372
|
try {
|
|
19123
|
-
(0,
|
|
19373
|
+
(0, import_node_fs18.writeFileSync)(".gitignore", text);
|
|
19124
19374
|
return true;
|
|
19125
19375
|
} catch {
|
|
19126
19376
|
return false;
|
|
@@ -19129,14 +19379,14 @@ function writeFencedBlock() {
|
|
|
19129
19379
|
function fenceMemory() {
|
|
19130
19380
|
let original = null;
|
|
19131
19381
|
try {
|
|
19132
|
-
original = (0,
|
|
19382
|
+
original = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
|
|
19133
19383
|
} catch {
|
|
19134
19384
|
original = null;
|
|
19135
19385
|
}
|
|
19136
19386
|
const restore = () => {
|
|
19137
19387
|
try {
|
|
19138
|
-
if (original === null) (0,
|
|
19139
|
-
else (0,
|
|
19388
|
+
if (original === null) (0, import_node_fs18.rmSync)(".gitignore", { force: true });
|
|
19389
|
+
else (0, import_node_fs18.writeFileSync)(".gitignore", original);
|
|
19140
19390
|
} catch {
|
|
19141
19391
|
}
|
|
19142
19392
|
};
|
|
@@ -19154,7 +19404,7 @@ function fenceMemory() {
|
|
|
19154
19404
|
}
|
|
19155
19405
|
function memoryOptOut() {
|
|
19156
19406
|
try {
|
|
19157
|
-
return (0,
|
|
19407
|
+
return (0, import_node_fs18.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
|
|
19158
19408
|
} catch {
|
|
19159
19409
|
return false;
|
|
19160
19410
|
}
|
|
@@ -19162,13 +19412,13 @@ function memoryOptOut() {
|
|
|
19162
19412
|
function keepMemoryTracked() {
|
|
19163
19413
|
let content = "";
|
|
19164
19414
|
try {
|
|
19165
|
-
content = (0,
|
|
19415
|
+
content = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
|
|
19166
19416
|
} catch {
|
|
19167
19417
|
}
|
|
19168
19418
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
19169
19419
|
try {
|
|
19170
19420
|
const sep5 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
19171
|
-
(0,
|
|
19421
|
+
(0, import_node_fs18.writeFileSync)(".gitignore", content + sep5 + MEMORY_OPT_OUT_STANZA);
|
|
19172
19422
|
} catch {
|
|
19173
19423
|
return "failed";
|
|
19174
19424
|
}
|
|
@@ -19203,26 +19453,26 @@ function untrackVerityState() {
|
|
|
19203
19453
|
}
|
|
19204
19454
|
|
|
19205
19455
|
// src/lib/safe-path.ts
|
|
19206
|
-
var
|
|
19207
|
-
var
|
|
19456
|
+
var import_node_fs19 = require("node:fs");
|
|
19457
|
+
var import_node_path17 = require("node:path");
|
|
19208
19458
|
function resolveInside(baseDir, candidate) {
|
|
19209
19459
|
if (typeof candidate !== "string" || candidate.length === 0) return null;
|
|
19210
|
-
if ((0,
|
|
19211
|
-
const baseAbs = (0,
|
|
19212
|
-
const full = (0,
|
|
19213
|
-
const baseSep = baseAbs.endsWith(
|
|
19460
|
+
if ((0, import_node_path17.isAbsolute)(candidate)) return null;
|
|
19461
|
+
const baseAbs = (0, import_node_path17.resolve)(baseDir);
|
|
19462
|
+
const full = (0, import_node_path17.resolve)(baseAbs, candidate);
|
|
19463
|
+
const baseSep = baseAbs.endsWith(import_node_path17.sep) ? baseAbs : baseAbs + import_node_path17.sep;
|
|
19214
19464
|
if (full !== baseAbs && !full.startsWith(baseSep)) return null;
|
|
19215
19465
|
try {
|
|
19216
|
-
if ((0,
|
|
19217
|
-
const realBase = (0,
|
|
19218
|
-
const realBaseSep = realBase.endsWith(
|
|
19466
|
+
if ((0, import_node_fs19.existsSync)(baseAbs)) {
|
|
19467
|
+
const realBase = (0, import_node_fs19.realpathSync)(baseAbs);
|
|
19468
|
+
const realBaseSep = realBase.endsWith(import_node_path17.sep) ? realBase : realBase + import_node_path17.sep;
|
|
19219
19469
|
let probe = full;
|
|
19220
|
-
while (!(0,
|
|
19221
|
-
const parent = (0,
|
|
19470
|
+
while (!(0, import_node_fs19.existsSync)(probe)) {
|
|
19471
|
+
const parent = (0, import_node_path17.dirname)(probe);
|
|
19222
19472
|
if (parent === probe) break;
|
|
19223
19473
|
probe = parent;
|
|
19224
19474
|
}
|
|
19225
|
-
const realProbe = (0,
|
|
19475
|
+
const realProbe = (0, import_node_fs19.realpathSync)(probe);
|
|
19226
19476
|
if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
|
|
19227
19477
|
}
|
|
19228
19478
|
} catch {
|
|
@@ -19230,37 +19480,37 @@ function resolveInside(baseDir, candidate) {
|
|
|
19230
19480
|
}
|
|
19231
19481
|
return full;
|
|
19232
19482
|
}
|
|
19233
|
-
var O_NOFOLLOW2 = typeof
|
|
19483
|
+
var O_NOFOLLOW2 = typeof import_node_fs19.constants.O_NOFOLLOW === "number" ? import_node_fs19.constants.O_NOFOLLOW : 0;
|
|
19234
19484
|
function readFileInside(baseDir, candidate, maxBytes) {
|
|
19235
19485
|
const full = resolveInside(baseDir, candidate);
|
|
19236
19486
|
if (!full) return null;
|
|
19237
19487
|
let realParent;
|
|
19238
19488
|
let realBase;
|
|
19239
19489
|
try {
|
|
19240
|
-
realParent = (0,
|
|
19241
|
-
realBase = (0,
|
|
19490
|
+
realParent = (0, import_node_fs19.realpathSync)((0, import_node_path17.dirname)(full));
|
|
19491
|
+
realBase = (0, import_node_fs19.realpathSync)((0, import_node_path17.resolve)(baseDir));
|
|
19242
19492
|
} catch {
|
|
19243
19493
|
return null;
|
|
19244
19494
|
}
|
|
19245
|
-
const realBaseSep = realBase.endsWith(
|
|
19495
|
+
const realBaseSep = realBase.endsWith(import_node_path17.sep) ? realBase : realBase + import_node_path17.sep;
|
|
19246
19496
|
if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
|
|
19247
|
-
const target = (0,
|
|
19497
|
+
const target = (0, import_node_path17.join)(realParent, (0, import_node_path17.basename)(full));
|
|
19248
19498
|
let fd = null;
|
|
19249
19499
|
try {
|
|
19250
|
-
fd = (0,
|
|
19251
|
-
const st = (0,
|
|
19500
|
+
fd = (0, import_node_fs19.openSync)(target, import_node_fs19.constants.O_RDONLY | O_NOFOLLOW2);
|
|
19501
|
+
const st = (0, import_node_fs19.fstatSync)(fd);
|
|
19252
19502
|
if (!st.isFile()) return null;
|
|
19253
19503
|
const cap2 = Math.min(maxBytes, st.size);
|
|
19254
19504
|
if (cap2 <= 0) return "";
|
|
19255
19505
|
const buf = Buffer.alloc(cap2);
|
|
19256
|
-
const bytesRead = (0,
|
|
19506
|
+
const bytesRead = (0, import_node_fs19.readSync)(fd, buf, 0, cap2, 0);
|
|
19257
19507
|
return buf.subarray(0, bytesRead).toString("utf-8");
|
|
19258
19508
|
} catch {
|
|
19259
19509
|
return null;
|
|
19260
19510
|
} finally {
|
|
19261
19511
|
if (fd !== null) {
|
|
19262
19512
|
try {
|
|
19263
|
-
(0,
|
|
19513
|
+
(0, import_node_fs19.closeSync)(fd);
|
|
19264
19514
|
} catch {
|
|
19265
19515
|
}
|
|
19266
19516
|
}
|
|
@@ -19343,32 +19593,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
|
|
|
19343
19593
|
async function ensureMemoryDir() {
|
|
19344
19594
|
await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
|
|
19345
19595
|
for (const domain of DOMAINS2) {
|
|
19346
|
-
await (0, import_promises9.mkdir)((0,
|
|
19596
|
+
await (0, import_promises9.mkdir)((0, import_node_path18.join)(memoryDir2(), domain), { recursive: true });
|
|
19347
19597
|
}
|
|
19348
|
-
if (!(0,
|
|
19349
|
-
await (0, import_promises9.writeFile)((0,
|
|
19598
|
+
if (!(0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "SCHEMA.md"))) {
|
|
19599
|
+
await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
|
|
19350
19600
|
}
|
|
19351
|
-
if (!(0,
|
|
19352
|
-
await (0, import_promises9.writeFile)((0,
|
|
19601
|
+
if (!(0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "index.md"))) {
|
|
19602
|
+
await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
|
|
19353
19603
|
}
|
|
19354
|
-
if (!(0,
|
|
19355
|
-
await (0, import_promises9.writeFile)((0,
|
|
19604
|
+
if (!(0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "log.md"))) {
|
|
19605
|
+
await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
|
|
19356
19606
|
}
|
|
19357
19607
|
}
|
|
19358
19608
|
async function buildManifest() {
|
|
19359
|
-
if (!(0,
|
|
19609
|
+
if (!(0, import_node_fs20.existsSync)(memoryDir2())) {
|
|
19360
19610
|
return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
|
|
19361
19611
|
}
|
|
19362
19612
|
const nodes = [];
|
|
19363
19613
|
for (const domain of DOMAINS2) {
|
|
19364
|
-
const domainDir = (0,
|
|
19365
|
-
if (!(0,
|
|
19614
|
+
const domainDir = (0, import_node_path18.join)(memoryDir2(), domain);
|
|
19615
|
+
if (!(0, import_node_fs20.existsSync)(domainDir)) continue;
|
|
19366
19616
|
try {
|
|
19367
19617
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
19368
19618
|
for (const file of files) {
|
|
19369
19619
|
if (!file.endsWith(".md")) continue;
|
|
19370
19620
|
const filePath = `${domain}/${file}`;
|
|
19371
|
-
const fullPath = (0,
|
|
19621
|
+
const fullPath = (0, import_node_path18.join)(memoryDir2(), filePath);
|
|
19372
19622
|
try {
|
|
19373
19623
|
const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
19374
19624
|
const hash = (0, import_node_crypto4.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
@@ -19381,13 +19631,13 @@ async function buildManifest() {
|
|
|
19381
19631
|
}
|
|
19382
19632
|
let indexHash = null;
|
|
19383
19633
|
try {
|
|
19384
|
-
const indexContent = await (0, import_promises9.readFile)((0,
|
|
19634
|
+
const indexContent = await (0, import_promises9.readFile)((0, import_node_path18.join)(memoryDir2(), "index.md"), "utf-8");
|
|
19385
19635
|
indexHash = `sha256:${(0, import_node_crypto4.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
|
|
19386
19636
|
} catch {
|
|
19387
19637
|
}
|
|
19388
19638
|
let logLength = 0;
|
|
19389
19639
|
try {
|
|
19390
|
-
const logContent = await (0, import_promises9.readFile)((0,
|
|
19640
|
+
const logContent = await (0, import_promises9.readFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), "utf-8");
|
|
19391
19641
|
logLength = logContent.split("\n").length;
|
|
19392
19642
|
} catch {
|
|
19393
19643
|
}
|
|
@@ -19398,15 +19648,15 @@ function hashContent(content) {
|
|
|
19398
19648
|
}
|
|
19399
19649
|
async function readOnDiskNodes() {
|
|
19400
19650
|
const out2 = /* @__PURE__ */ new Map();
|
|
19401
|
-
if (!(0,
|
|
19651
|
+
if (!(0, import_node_fs20.existsSync)(memoryDir2())) return out2;
|
|
19402
19652
|
for (const domain of DOMAINS2) {
|
|
19403
|
-
const domainDir = (0,
|
|
19404
|
-
if (!(0,
|
|
19653
|
+
const domainDir = (0, import_node_path18.join)(memoryDir2(), domain);
|
|
19654
|
+
if (!(0, import_node_fs20.existsSync)(domainDir)) continue;
|
|
19405
19655
|
try {
|
|
19406
19656
|
for (const file of await (0, import_promises9.readdir)(domainDir)) {
|
|
19407
19657
|
if (!file.endsWith(".md")) continue;
|
|
19408
19658
|
try {
|
|
19409
|
-
out2.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0,
|
|
19659
|
+
out2.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path18.join)(domainDir, file), "utf-8")));
|
|
19410
19660
|
} catch {
|
|
19411
19661
|
}
|
|
19412
19662
|
}
|
|
@@ -19443,7 +19693,7 @@ async function recordSyncedNodePaths() {
|
|
|
19443
19693
|
}
|
|
19444
19694
|
}
|
|
19445
19695
|
async function writeFileAtomic(path, content) {
|
|
19446
|
-
await (0, import_promises9.mkdir)((0,
|
|
19696
|
+
await (0, import_promises9.mkdir)((0, import_node_path18.dirname)(path), { recursive: true });
|
|
19447
19697
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
19448
19698
|
await (0, import_promises9.writeFile)(tmp, content);
|
|
19449
19699
|
await (0, import_promises9.rename)(tmp, path);
|
|
@@ -19457,8 +19707,8 @@ async function computeEditedNodeUploads() {
|
|
|
19457
19707
|
const uploads = [];
|
|
19458
19708
|
for (const [path, prevHash] of prev) {
|
|
19459
19709
|
if (prevHash == null) continue;
|
|
19460
|
-
const full = (0,
|
|
19461
|
-
if (!(0,
|
|
19710
|
+
const full = (0, import_node_path18.join)(memoryDir2(), path);
|
|
19711
|
+
if (!(0, import_node_fs20.existsSync)(full)) continue;
|
|
19462
19712
|
let content;
|
|
19463
19713
|
try {
|
|
19464
19714
|
content = await (0, import_promises9.readFile)(full, "utf-8");
|
|
@@ -19502,8 +19752,8 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
19502
19752
|
const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
|
|
19503
19753
|
for (const n of notes) logLines.push(` - ${n}`);
|
|
19504
19754
|
try {
|
|
19505
|
-
const existing = (0,
|
|
19506
|
-
await (0, import_promises9.writeFile)((0,
|
|
19755
|
+
const existing = (0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
|
|
19756
|
+
await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
|
|
19507
19757
|
} catch {
|
|
19508
19758
|
}
|
|
19509
19759
|
if (opts.baseline === "written") await mergeSyncBaseline(synced);
|
|
@@ -19513,7 +19763,7 @@ async function applyMemoryWrites(writes, opts = {}) {
|
|
|
19513
19763
|
async function mergeSyncBaseline(entries) {
|
|
19514
19764
|
if (entries.size === 0) return;
|
|
19515
19765
|
try {
|
|
19516
|
-
if ((0,
|
|
19766
|
+
if ((0, import_node_fs20.existsSync)(syncStateFile())) {
|
|
19517
19767
|
try {
|
|
19518
19768
|
JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
|
|
19519
19769
|
} catch {
|
|
@@ -19541,7 +19791,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
19541
19791
|
notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
|
|
19542
19792
|
}
|
|
19543
19793
|
}
|
|
19544
|
-
if ((0,
|
|
19794
|
+
if ((0, import_node_fs20.existsSync)(fullPath)) {
|
|
19545
19795
|
let existing = "";
|
|
19546
19796
|
try {
|
|
19547
19797
|
existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
|
|
@@ -19557,7 +19807,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
|
|
|
19557
19807
|
notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
|
|
19558
19808
|
}
|
|
19559
19809
|
}
|
|
19560
|
-
await (0, import_promises9.mkdir)((0,
|
|
19810
|
+
await (0, import_promises9.mkdir)((0, import_node_path18.dirname)(fullPath), { recursive: true });
|
|
19561
19811
|
await (0, import_promises9.writeFile)(fullPath, content);
|
|
19562
19812
|
return { written: true, syncedHash: hashContent(content), notes };
|
|
19563
19813
|
}
|
|
@@ -19598,8 +19848,8 @@ async function regenerateIndex() {
|
|
|
19598
19848
|
];
|
|
19599
19849
|
let totalNodes = 0;
|
|
19600
19850
|
for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
|
|
19601
|
-
const domainDir = (0,
|
|
19602
|
-
if (!(0,
|
|
19851
|
+
const domainDir = (0, import_node_path18.join)(memoryDir2(), domain);
|
|
19852
|
+
if (!(0, import_node_fs20.existsSync)(domainDir)) continue;
|
|
19603
19853
|
try {
|
|
19604
19854
|
const files = await (0, import_promises9.readdir)(domainDir);
|
|
19605
19855
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
@@ -19609,7 +19859,7 @@ async function regenerateIndex() {
|
|
|
19609
19859
|
for (const file of mdFiles.sort()) {
|
|
19610
19860
|
const slug = file.replace(/\.md$/, "");
|
|
19611
19861
|
try {
|
|
19612
|
-
const content = await (0, import_promises9.readFile)((0,
|
|
19862
|
+
const content = await (0, import_promises9.readFile)((0, import_node_path18.join)(domainDir, file), "utf-8");
|
|
19613
19863
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
19614
19864
|
const kind = pickFrontmatter(content, "kind") ?? "-";
|
|
19615
19865
|
const confidence = pickFrontmatter(content, "confidence");
|
|
@@ -19633,7 +19883,7 @@ async function regenerateIndex() {
|
|
|
19633
19883
|
lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
|
|
19634
19884
|
}
|
|
19635
19885
|
const next = lines.join("\n") + "\n";
|
|
19636
|
-
const indexPath = (0,
|
|
19886
|
+
const indexPath = (0, import_node_path18.join)(memoryDir2(), "index.md");
|
|
19637
19887
|
let existing = null;
|
|
19638
19888
|
try {
|
|
19639
19889
|
existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
|
|
@@ -20030,9 +20280,9 @@ function hasLegacyMemoryBlock(text) {
|
|
|
20030
20280
|
return findMarker(text, LEGACY_MD_START) !== -1;
|
|
20031
20281
|
}
|
|
20032
20282
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
20033
|
-
const claudeMdPath = (0,
|
|
20283
|
+
const claudeMdPath = (0, import_node_path18.join)(cwd, "CLAUDE.md");
|
|
20034
20284
|
let existing = "";
|
|
20035
|
-
if ((0,
|
|
20285
|
+
if ((0, import_node_fs20.existsSync)(claudeMdPath)) {
|
|
20036
20286
|
existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
|
|
20037
20287
|
}
|
|
20038
20288
|
let startTag = CLAUDE_MD_START;
|
|
@@ -20173,9 +20423,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
20173
20423
|
`;
|
|
20174
20424
|
|
|
20175
20425
|
// src/lib/dossier-session.ts
|
|
20176
|
-
var
|
|
20426
|
+
var import_node_fs25 = require("node:fs");
|
|
20177
20427
|
var import_node_crypto8 = require("node:crypto");
|
|
20178
|
-
var
|
|
20428
|
+
var import_node_path21 = require("node:path");
|
|
20179
20429
|
|
|
20180
20430
|
// src/lib/pending-repeat.ts
|
|
20181
20431
|
var STOP = /* @__PURE__ */ new Set([
|
|
@@ -20280,8 +20530,8 @@ function statementAnchorKey(file, patternId) {
|
|
|
20280
20530
|
|
|
20281
20531
|
// src/lib/dossier/log.ts
|
|
20282
20532
|
var import_node_crypto5 = require("node:crypto");
|
|
20283
|
-
var
|
|
20284
|
-
var
|
|
20533
|
+
var import_node_fs21 = require("node:fs");
|
|
20534
|
+
var import_node_path19 = require("node:path");
|
|
20285
20535
|
var CRC_TABLE = (() => {
|
|
20286
20536
|
const t = new Int32Array(256);
|
|
20287
20537
|
for (let i2 = 0; i2 < 256; i2++) {
|
|
@@ -20300,13 +20550,13 @@ function crc32(s) {
|
|
|
20300
20550
|
function openDossier(identity) {
|
|
20301
20551
|
try {
|
|
20302
20552
|
const dir = dossierDir(identity);
|
|
20303
|
-
(0,
|
|
20553
|
+
(0, import_node_fs21.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
20304
20554
|
return {
|
|
20305
20555
|
dir,
|
|
20306
20556
|
identity,
|
|
20307
|
-
eventsPath: (0,
|
|
20308
|
-
foldPath: (0,
|
|
20309
|
-
rotatedDir: (0,
|
|
20557
|
+
eventsPath: (0, import_node_path19.join)(dir, "events.jsonl"),
|
|
20558
|
+
foldPath: (0, import_node_path19.join)(dir, "fold.json"),
|
|
20559
|
+
rotatedDir: (0, import_node_path19.join)(dir, "rotated")
|
|
20310
20560
|
};
|
|
20311
20561
|
} catch {
|
|
20312
20562
|
return null;
|
|
@@ -20368,7 +20618,7 @@ function appendEvent(d, ev) {
|
|
|
20368
20618
|
at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
20369
20619
|
...ev
|
|
20370
20620
|
});
|
|
20371
|
-
(0,
|
|
20621
|
+
(0, import_node_fs21.appendFileSync)(d.eventsPath, line2, { mode: 384 });
|
|
20372
20622
|
return true;
|
|
20373
20623
|
} catch {
|
|
20374
20624
|
return false;
|
|
@@ -20376,14 +20626,14 @@ function appendEvent(d, ev) {
|
|
|
20376
20626
|
}
|
|
20377
20627
|
function rotateIfNeeded2(d) {
|
|
20378
20628
|
try {
|
|
20379
|
-
if (!(0,
|
|
20380
|
-
if ((0,
|
|
20381
|
-
(0,
|
|
20382
|
-
(0,
|
|
20383
|
-
const kept = (0,
|
|
20629
|
+
if (!(0, import_node_fs21.existsSync)(d.eventsPath)) return;
|
|
20630
|
+
if ((0, import_node_fs21.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
|
|
20631
|
+
(0, import_node_fs21.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
|
|
20632
|
+
(0, import_node_fs21.renameSync)(d.eventsPath, (0, import_node_path19.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
|
|
20633
|
+
const kept = (0, import_node_fs21.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
20384
20634
|
for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
|
|
20385
20635
|
try {
|
|
20386
|
-
(0,
|
|
20636
|
+
(0, import_node_fs21.renameSync)((0, import_node_path19.join)(d.rotatedDir, stale), (0, import_node_path19.join)(d.rotatedDir, `${stale}.pruned`));
|
|
20387
20637
|
} catch {
|
|
20388
20638
|
}
|
|
20389
20639
|
}
|
|
@@ -20393,8 +20643,8 @@ function rotateIfNeeded2(d) {
|
|
|
20393
20643
|
|
|
20394
20644
|
// src/lib/dossier/fold-dossier.ts
|
|
20395
20645
|
var import_node_crypto6 = require("node:crypto");
|
|
20396
|
-
var
|
|
20397
|
-
var
|
|
20646
|
+
var import_node_fs22 = require("node:fs");
|
|
20647
|
+
var import_node_path20 = require("node:path");
|
|
20398
20648
|
var EMPTY_CAPABILITIES = () => ({
|
|
20399
20649
|
human_reachable: { value: "unknown", tier: "unknown" },
|
|
20400
20650
|
authorship_observability: { value: "unknown", tier: "unknown" },
|
|
@@ -20445,12 +20695,12 @@ function foldDossier(d, opts = {}) {
|
|
|
20445
20695
|
}
|
|
20446
20696
|
};
|
|
20447
20697
|
try {
|
|
20448
|
-
if ((0,
|
|
20449
|
-
const files = (0,
|
|
20698
|
+
if ((0, import_node_fs22.existsSync)(d.rotatedDir)) {
|
|
20699
|
+
const files = (0, import_node_fs22.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
20450
20700
|
state.meta.rotations = files.length;
|
|
20451
20701
|
for (const f of files) {
|
|
20452
20702
|
try {
|
|
20453
|
-
ingest((0,
|
|
20703
|
+
ingest((0, import_node_fs22.readFileSync)((0, import_node_path20.join)(d.rotatedDir, f), "utf8"));
|
|
20454
20704
|
} catch {
|
|
20455
20705
|
state.meta.dropped_lines++;
|
|
20456
20706
|
}
|
|
@@ -20459,9 +20709,9 @@ function foldDossier(d, opts = {}) {
|
|
|
20459
20709
|
} catch {
|
|
20460
20710
|
}
|
|
20461
20711
|
try {
|
|
20462
|
-
if ((0,
|
|
20463
|
-
state.meta.upto_offset = (0,
|
|
20464
|
-
ingest((0,
|
|
20712
|
+
if ((0, import_node_fs22.existsSync)(d.eventsPath)) {
|
|
20713
|
+
state.meta.upto_offset = (0, import_node_fs22.statSync)(d.eventsPath).size;
|
|
20714
|
+
ingest((0, import_node_fs22.readFileSync)(d.eventsPath, "utf8"));
|
|
20465
20715
|
}
|
|
20466
20716
|
} catch {
|
|
20467
20717
|
}
|
|
@@ -20732,7 +20982,7 @@ function applyBounds(state, input) {
|
|
|
20732
20982
|
}
|
|
20733
20983
|
|
|
20734
20984
|
// src/lib/dossier/cache.ts
|
|
20735
|
-
var
|
|
20985
|
+
var import_node_fs23 = require("node:fs");
|
|
20736
20986
|
function compactState(s) {
|
|
20737
20987
|
const ms = (iso) => Date.parse(iso) || 0;
|
|
20738
20988
|
return {
|
|
@@ -20861,20 +21111,20 @@ function encodeState(s) {
|
|
|
20861
21111
|
function writeFoldCache(d, state) {
|
|
20862
21112
|
try {
|
|
20863
21113
|
const tmp = `${d.foldPath}.${process.pid}.tmp`;
|
|
20864
|
-
(0,
|
|
20865
|
-
(0,
|
|
21114
|
+
(0, import_node_fs23.writeFileSync)(tmp, encodeState(state), { mode: 384 });
|
|
21115
|
+
(0, import_node_fs23.renameSync)(tmp, d.foldPath);
|
|
20866
21116
|
} catch {
|
|
20867
21117
|
}
|
|
20868
21118
|
}
|
|
20869
21119
|
function readFoldCache(d) {
|
|
20870
21120
|
try {
|
|
20871
|
-
if (!(0,
|
|
20872
|
-
const raw = JSON.parse((0,
|
|
21121
|
+
if (!(0, import_node_fs23.existsSync)(d.foldPath)) return null;
|
|
21122
|
+
const raw = JSON.parse((0, import_node_fs23.readFileSync)(d.foldPath, "utf8"));
|
|
20873
21123
|
if (raw?.v !== 1) return null;
|
|
20874
21124
|
const cached2 = expandState(raw);
|
|
20875
21125
|
if (!cached2?.meta) return null;
|
|
20876
|
-
const size = (0,
|
|
20877
|
-
const rotations = (0,
|
|
21126
|
+
const size = (0, import_node_fs23.existsSync)(d.eventsPath) ? (0, import_node_fs23.statSync)(d.eventsPath).size : 0;
|
|
21127
|
+
const rotations = (0, import_node_fs23.existsSync)(d.rotatedDir) ? (0, import_node_fs23.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
|
|
20878
21128
|
if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
|
|
20879
21129
|
return cached2;
|
|
20880
21130
|
} catch {
|
|
@@ -20925,13 +21175,13 @@ function assessContinuity(i2) {
|
|
|
20925
21175
|
|
|
20926
21176
|
// src/lib/dossier/reanchor.ts
|
|
20927
21177
|
var import_node_crypto7 = require("node:crypto");
|
|
20928
|
-
var
|
|
21178
|
+
var import_node_fs24 = require("node:fs");
|
|
20929
21179
|
function lineSha(text) {
|
|
20930
21180
|
return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
20931
21181
|
}
|
|
20932
21182
|
function fileHash(path) {
|
|
20933
21183
|
try {
|
|
20934
|
-
return (0, import_node_crypto7.createHash)("sha256").update((0,
|
|
21184
|
+
return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs24.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
20935
21185
|
} catch {
|
|
20936
21186
|
return null;
|
|
20937
21187
|
}
|
|
@@ -21303,20 +21553,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
|
|
|
21303
21553
|
let sessions = 0;
|
|
21304
21554
|
try {
|
|
21305
21555
|
const dir = treeDir(identity);
|
|
21306
|
-
if (!(0,
|
|
21307
|
-
for (const entry of (0,
|
|
21556
|
+
if (!(0, import_node_fs25.existsSync)(dir)) return { paths: [], sessions: 0 };
|
|
21557
|
+
for (const entry of (0, import_node_fs25.readdirSync)(dir, { withFileTypes: true })) {
|
|
21308
21558
|
if (!entry.isDirectory()) continue;
|
|
21309
21559
|
if (entry.name === identity.sessionKey) continue;
|
|
21310
|
-
const log = (0,
|
|
21560
|
+
const log = (0, import_node_path21.join)(dir, entry.name, "events.jsonl");
|
|
21311
21561
|
try {
|
|
21312
|
-
if (!(0,
|
|
21313
|
-
if (now - (0,
|
|
21562
|
+
if (!(0, import_node_fs25.existsSync)(log)) continue;
|
|
21563
|
+
if (now - (0, import_node_fs25.statSync)(log).mtimeMs > windowMs) continue;
|
|
21314
21564
|
const sib = {
|
|
21315
|
-
dir: (0,
|
|
21565
|
+
dir: (0, import_node_path21.join)(dir, entry.name),
|
|
21316
21566
|
identity,
|
|
21317
21567
|
eventsPath: log,
|
|
21318
|
-
foldPath: (0,
|
|
21319
|
-
rotatedDir: (0,
|
|
21568
|
+
foldPath: (0, import_node_path21.join)(dir, entry.name, "fold.json"),
|
|
21569
|
+
rotatedDir: (0, import_node_path21.join)(dir, entry.name, "rotated")
|
|
21320
21570
|
};
|
|
21321
21571
|
const state = readFoldCache(sib) ?? foldDossier(sib);
|
|
21322
21572
|
sessions++;
|
|
@@ -21344,25 +21594,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
21344
21594
|
let removed = 0;
|
|
21345
21595
|
try {
|
|
21346
21596
|
const mine = dossierDir(identity);
|
|
21347
|
-
const userDir = (0,
|
|
21348
|
-
if (!(0,
|
|
21597
|
+
const userDir = (0, import_node_path21.dirname)((0, import_node_path21.dirname)(mine));
|
|
21598
|
+
if (!(0, import_node_fs25.existsSync)(userDir)) return 0;
|
|
21349
21599
|
const cutoff = Date.now() - maxAgeMs;
|
|
21350
|
-
for (const tree of (0,
|
|
21600
|
+
for (const tree of (0, import_node_fs25.readdirSync)(userDir, { withFileTypes: true })) {
|
|
21351
21601
|
if (!tree.isDirectory()) continue;
|
|
21352
|
-
const treePath = (0,
|
|
21602
|
+
const treePath = (0, import_node_path21.join)(userDir, tree.name);
|
|
21353
21603
|
let live = 0;
|
|
21354
|
-
for (const entry of (0,
|
|
21604
|
+
for (const entry of (0, import_node_fs25.readdirSync)(treePath, { withFileTypes: true })) {
|
|
21355
21605
|
if (!entry.isDirectory()) continue;
|
|
21356
|
-
const dir = (0,
|
|
21606
|
+
const dir = (0, import_node_path21.join)(treePath, entry.name);
|
|
21357
21607
|
if (dir === mine) {
|
|
21358
21608
|
live++;
|
|
21359
21609
|
continue;
|
|
21360
21610
|
}
|
|
21361
21611
|
try {
|
|
21362
|
-
const log = (0,
|
|
21363
|
-
const at = (0,
|
|
21612
|
+
const log = (0, import_node_path21.join)(dir, "events.jsonl");
|
|
21613
|
+
const at = (0, import_node_fs25.existsSync)(log) ? (0, import_node_fs25.statSync)(log).mtimeMs : (0, import_node_fs25.statSync)(dir).mtimeMs;
|
|
21364
21614
|
if (at < cutoff) {
|
|
21365
|
-
(0,
|
|
21615
|
+
(0, import_node_fs25.rmSync)(dir, { recursive: true, force: true });
|
|
21366
21616
|
removed++;
|
|
21367
21617
|
} else {
|
|
21368
21618
|
live++;
|
|
@@ -21372,7 +21622,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
|
21372
21622
|
}
|
|
21373
21623
|
if (live === 0) {
|
|
21374
21624
|
try {
|
|
21375
|
-
(0,
|
|
21625
|
+
(0, import_node_fs25.rmSync)(treePath, { recursive: false, force: false });
|
|
21376
21626
|
} catch {
|
|
21377
21627
|
}
|
|
21378
21628
|
}
|
|
@@ -21389,8 +21639,8 @@ function sessionDossier(token, sessionId) {
|
|
|
21389
21639
|
}
|
|
21390
21640
|
function hasActiveGoal(d) {
|
|
21391
21641
|
try {
|
|
21392
|
-
if (!(0,
|
|
21393
|
-
return (0,
|
|
21642
|
+
if (!(0, import_node_fs25.existsSync)(d.eventsPath)) return false;
|
|
21643
|
+
return (0, import_node_fs25.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
|
|
21394
21644
|
} catch {
|
|
21395
21645
|
return false;
|
|
21396
21646
|
}
|
|
@@ -21414,7 +21664,7 @@ function recordTurn(d, t) {
|
|
|
21414
21664
|
for (const a of t.authored) {
|
|
21415
21665
|
const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
|
|
21416
21666
|
const prior = t.known?.authored?.get(a.p);
|
|
21417
|
-
const hash = fileHash((0,
|
|
21667
|
+
const hash = fileHash((0, import_node_path21.join)(root, a.p));
|
|
21418
21668
|
const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
|
|
21419
21669
|
const adds = Math.max(0, a.a - (prior?.adds ?? 0));
|
|
21420
21670
|
const dels = Math.max(0, a.d - (prior?.dels ?? 0));
|
|
@@ -21447,7 +21697,7 @@ function recordTurn(d, t) {
|
|
|
21447
21697
|
}
|
|
21448
21698
|
const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
|
|
21449
21699
|
for (const u of t.unobserved) {
|
|
21450
|
-
const hash = fileHash((0,
|
|
21700
|
+
const hash = fileHash((0, import_node_path21.join)(root, u.p));
|
|
21451
21701
|
if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
|
|
21452
21702
|
appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
|
|
21453
21703
|
}
|
|
@@ -21482,8 +21732,8 @@ function recordVerdict(d, v) {
|
|
|
21482
21732
|
if (!sent.has(f.file)) continue;
|
|
21483
21733
|
if (!lines.has(f.file)) {
|
|
21484
21734
|
try {
|
|
21485
|
-
const abs = (0,
|
|
21486
|
-
lines.set(f.file, (0,
|
|
21735
|
+
const abs = (0, import_node_path21.join)(root, f.file);
|
|
21736
|
+
lines.set(f.file, (0, import_node_fs25.existsSync)(abs) ? (0, import_node_fs25.readFileSync)(abs, "utf8").split("\n") : null);
|
|
21487
21737
|
} catch {
|
|
21488
21738
|
lines.set(f.file, null);
|
|
21489
21739
|
}
|
|
@@ -21583,8 +21833,8 @@ function recallMemory(d, identity, opts) {
|
|
|
21583
21833
|
budgetBytes: opts.budgetBytes,
|
|
21584
21834
|
readFileLines: (file) => {
|
|
21585
21835
|
try {
|
|
21586
|
-
const abs = (0,
|
|
21587
|
-
return (0,
|
|
21836
|
+
const abs = (0, import_node_path21.join)(root, file);
|
|
21837
|
+
return (0, import_node_fs25.existsSync)(abs) ? (0, import_node_fs25.readFileSync)(abs, "utf8").split("\n") : null;
|
|
21588
21838
|
} catch {
|
|
21589
21839
|
return null;
|
|
21590
21840
|
}
|
|
@@ -21752,21 +22002,21 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
21752
22002
|
}
|
|
21753
22003
|
|
|
21754
22004
|
// src/commands/lifecycle.ts
|
|
21755
|
-
var
|
|
21756
|
-
var
|
|
22005
|
+
var import_node_fs28 = require("node:fs");
|
|
22006
|
+
var import_node_path25 = require("node:path");
|
|
21757
22007
|
|
|
21758
22008
|
// src/lib/baseline.ts
|
|
21759
|
-
var
|
|
21760
|
-
var
|
|
22009
|
+
var import_node_fs27 = require("node:fs");
|
|
22010
|
+
var import_node_path24 = require("node:path");
|
|
21761
22011
|
var import_node_crypto10 = require("node:crypto");
|
|
21762
22012
|
|
|
21763
22013
|
// src/lib/snapshot.ts
|
|
21764
|
-
var
|
|
21765
|
-
var
|
|
22014
|
+
var import_node_fs26 = require("node:fs");
|
|
22015
|
+
var import_node_path23 = require("node:path");
|
|
21766
22016
|
var import_node_child_process7 = require("node:child_process");
|
|
21767
22017
|
|
|
21768
22018
|
// src/lib/files.ts
|
|
21769
|
-
var
|
|
22019
|
+
var import_node_path22 = require("node:path");
|
|
21770
22020
|
var LANG_MAP = {
|
|
21771
22021
|
// Analyzable (static analysis + Gemini)
|
|
21772
22022
|
ts: "typescript",
|
|
@@ -21834,7 +22084,7 @@ var LANG_MAP = {
|
|
|
21834
22084
|
mk: "make"
|
|
21835
22085
|
};
|
|
21836
22086
|
function detectLanguage(filepath) {
|
|
21837
|
-
const ext = (0,
|
|
22087
|
+
const ext = (0, import_node_path22.extname)(filepath).slice(1);
|
|
21838
22088
|
return LANG_MAP[ext] ?? ext;
|
|
21839
22089
|
}
|
|
21840
22090
|
function sortByMtime(files) {
|
|
@@ -21925,16 +22175,16 @@ function collectCodeDelta(files, opts) {
|
|
|
21925
22175
|
|
|
21926
22176
|
// src/lib/snapshot.ts
|
|
21927
22177
|
function generateSnapshotDiffs(files) {
|
|
21928
|
-
if (!(0,
|
|
22178
|
+
if (!(0, import_node_fs26.existsSync)(SNAPSHOT_DIR)) {
|
|
21929
22179
|
return { diffs: [], has_snapshots: false };
|
|
21930
22180
|
}
|
|
21931
22181
|
const diffs = [];
|
|
21932
22182
|
for (const file of files) {
|
|
21933
22183
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
21934
|
-
const snapshotPath = (0,
|
|
22184
|
+
const snapshotPath = (0, import_node_path23.join)(SNAPSHOT_DIR, file.path);
|
|
21935
22185
|
const language = file.language ?? detectLanguage(file.path);
|
|
21936
|
-
if ((0,
|
|
21937
|
-
const oldContent = (0,
|
|
22186
|
+
if ((0, import_node_fs26.existsSync)(snapshotPath)) {
|
|
22187
|
+
const oldContent = (0, import_node_fs26.readFileSync)(snapshotPath, "utf-8");
|
|
21938
22188
|
if (oldContent === file.content) continue;
|
|
21939
22189
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
21940
22190
|
if (diff) {
|
|
@@ -21959,20 +22209,20 @@ function saveSnapshots(files) {
|
|
|
21959
22209
|
const snapshotPaths = /* @__PURE__ */ new Set();
|
|
21960
22210
|
for (const file of files) {
|
|
21961
22211
|
if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
|
|
21962
|
-
const snapshotPath = (0,
|
|
22212
|
+
const snapshotPath = (0, import_node_path23.join)(SNAPSHOT_DIR, file.path);
|
|
21963
22213
|
snapshotPaths.add(snapshotPath);
|
|
21964
|
-
(0,
|
|
21965
|
-
(0,
|
|
22214
|
+
(0, import_node_fs26.mkdirSync)((0, import_node_path23.dirname)(snapshotPath), { recursive: true });
|
|
22215
|
+
(0, import_node_fs26.writeFileSync)(snapshotPath, file.content);
|
|
21966
22216
|
}
|
|
21967
22217
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
21968
22218
|
}
|
|
21969
22219
|
function computeDiff(oldContent, newContent, filePath) {
|
|
21970
|
-
const tmpOld = (0,
|
|
21971
|
-
const tmpNew = (0,
|
|
22220
|
+
const tmpOld = (0, import_node_path23.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
22221
|
+
const tmpNew = (0, import_node_path23.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
21972
22222
|
try {
|
|
21973
|
-
(0,
|
|
21974
|
-
(0,
|
|
21975
|
-
(0,
|
|
22223
|
+
(0, import_node_fs26.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
22224
|
+
(0, import_node_fs26.writeFileSync)(tmpOld, oldContent);
|
|
22225
|
+
(0, import_node_fs26.writeFileSync)(tmpNew, newContent);
|
|
21976
22226
|
const result = (0, import_node_child_process7.execSync)(
|
|
21977
22227
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
21978
22228
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -21986,32 +22236,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
21986
22236
|
return null;
|
|
21987
22237
|
} finally {
|
|
21988
22238
|
try {
|
|
21989
|
-
(0,
|
|
22239
|
+
(0, import_node_fs26.unlinkSync)(tmpOld);
|
|
21990
22240
|
} catch {
|
|
21991
22241
|
}
|
|
21992
22242
|
try {
|
|
21993
|
-
(0,
|
|
22243
|
+
(0, import_node_fs26.unlinkSync)(tmpNew);
|
|
21994
22244
|
} catch {
|
|
21995
22245
|
}
|
|
21996
22246
|
}
|
|
21997
22247
|
}
|
|
21998
22248
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
21999
|
-
if (!(0,
|
|
22249
|
+
if (!(0, import_node_fs26.existsSync)(dir)) return;
|
|
22000
22250
|
try {
|
|
22001
|
-
const entries = (0,
|
|
22251
|
+
const entries = (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true });
|
|
22002
22252
|
for (const entry of entries) {
|
|
22003
22253
|
if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
|
|
22004
|
-
const fullPath = (0,
|
|
22254
|
+
const fullPath = (0, import_node_path23.join)(dir, entry.name);
|
|
22005
22255
|
if (entry.isDirectory()) {
|
|
22006
22256
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
22007
22257
|
try {
|
|
22008
|
-
const remaining = (0,
|
|
22009
|
-
if (remaining.length === 0) (0,
|
|
22258
|
+
const remaining = (0, import_node_fs26.readdirSync)(fullPath);
|
|
22259
|
+
if (remaining.length === 0) (0, import_node_fs26.rmdirSync)(fullPath);
|
|
22010
22260
|
} catch {
|
|
22011
22261
|
}
|
|
22012
22262
|
} else if (!keepSet.has(fullPath)) {
|
|
22013
22263
|
try {
|
|
22014
|
-
(0,
|
|
22264
|
+
(0, import_node_fs26.unlinkSync)(fullPath);
|
|
22015
22265
|
} catch {
|
|
22016
22266
|
}
|
|
22017
22267
|
}
|
|
@@ -22030,20 +22280,20 @@ function sessionKey(sessionId) {
|
|
|
22030
22280
|
return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
22031
22281
|
}
|
|
22032
22282
|
function sessionDir(key) {
|
|
22033
|
-
return (0,
|
|
22283
|
+
return (0, import_node_path24.join)(projectPath(BASELINE_DIR), key);
|
|
22034
22284
|
}
|
|
22035
22285
|
function manifestPath(dir) {
|
|
22036
|
-
return (0,
|
|
22286
|
+
return (0, import_node_path24.join)(dir, "manifest.json");
|
|
22037
22287
|
}
|
|
22038
22288
|
function mirrorPath(dir, repoRelPath) {
|
|
22039
|
-
return (0,
|
|
22289
|
+
return (0, import_node_path24.join)(dir, "files", repoRelPath);
|
|
22040
22290
|
}
|
|
22041
22291
|
var CARRY_FILE = `${BASELINE_DIR}/.carry`;
|
|
22042
22292
|
var CARRY_WINDOW_MS = 12e4;
|
|
22043
22293
|
function writeCarry(sessionId, headSha) {
|
|
22044
22294
|
try {
|
|
22045
|
-
(0,
|
|
22046
|
-
(0,
|
|
22295
|
+
(0, import_node_fs27.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
|
|
22296
|
+
(0, import_node_fs27.writeFileSync)(
|
|
22047
22297
|
projectPath(CARRY_FILE),
|
|
22048
22298
|
JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
|
|
22049
22299
|
);
|
|
@@ -22053,10 +22303,10 @@ function writeCarry(sessionId, headSha) {
|
|
|
22053
22303
|
function claimCarry(newKey) {
|
|
22054
22304
|
const carryPath = projectPath(CARRY_FILE);
|
|
22055
22305
|
try {
|
|
22056
|
-
if (!(0,
|
|
22057
|
-
const carry = JSON.parse((0,
|
|
22306
|
+
if (!(0, import_node_fs27.existsSync)(carryPath)) return null;
|
|
22307
|
+
const carry = JSON.parse((0, import_node_fs27.readFileSync)(carryPath, "utf-8"));
|
|
22058
22308
|
try {
|
|
22059
|
-
(0,
|
|
22309
|
+
(0, import_node_fs27.rmSync)(carryPath, { force: true });
|
|
22060
22310
|
} catch {
|
|
22061
22311
|
}
|
|
22062
22312
|
if (!carry?.from_key || typeof carry.ts !== "number") return null;
|
|
@@ -22067,11 +22317,11 @@ function claimCarry(newKey) {
|
|
|
22067
22317
|
if (!prior) return null;
|
|
22068
22318
|
const toDir = sessionDir(newKey);
|
|
22069
22319
|
try {
|
|
22070
|
-
(0,
|
|
22320
|
+
(0, import_node_fs27.rmSync)(toDir, { recursive: true, force: true });
|
|
22071
22321
|
} catch {
|
|
22072
22322
|
}
|
|
22073
|
-
(0,
|
|
22074
|
-
(0,
|
|
22323
|
+
(0, import_node_fs27.renameSync)(fromDir, toDir);
|
|
22324
|
+
(0, import_node_fs27.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
|
|
22075
22325
|
return readManifest(toDir);
|
|
22076
22326
|
} catch {
|
|
22077
22327
|
return null;
|
|
@@ -22095,21 +22345,21 @@ function captureBaseline(opts = {}) {
|
|
|
22095
22345
|
const head_sha = getCurrentCommit();
|
|
22096
22346
|
const dirty = getDirtyFiles();
|
|
22097
22347
|
try {
|
|
22098
|
-
(0,
|
|
22348
|
+
(0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
|
|
22099
22349
|
} catch {
|
|
22100
22350
|
}
|
|
22101
|
-
const filesDir = (0,
|
|
22351
|
+
const filesDir = (0, import_node_path24.join)(dir, "files");
|
|
22102
22352
|
const mirrored = [];
|
|
22103
22353
|
try {
|
|
22104
|
-
(0,
|
|
22354
|
+
(0, import_node_fs27.mkdirSync)(filesDir, { recursive: true });
|
|
22105
22355
|
for (const p of dirty) {
|
|
22106
22356
|
if (p.includes("..")) continue;
|
|
22107
22357
|
const content = safeReadForMirror(projectPath(p));
|
|
22108
22358
|
if (content === null) continue;
|
|
22109
22359
|
const dest = mirrorPath(dir, p);
|
|
22110
22360
|
try {
|
|
22111
|
-
(0,
|
|
22112
|
-
(0,
|
|
22361
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path24.dirname)(dest), { recursive: true });
|
|
22362
|
+
(0, import_node_fs27.writeFileSync)(dest, content);
|
|
22113
22363
|
mirrored.push(p);
|
|
22114
22364
|
} catch {
|
|
22115
22365
|
}
|
|
@@ -22124,8 +22374,8 @@ function captureBaseline(opts = {}) {
|
|
|
22124
22374
|
version: BASELINE_VERSION
|
|
22125
22375
|
};
|
|
22126
22376
|
try {
|
|
22127
|
-
(0,
|
|
22128
|
-
(0,
|
|
22377
|
+
(0, import_node_fs27.mkdirSync)(dir, { recursive: true });
|
|
22378
|
+
(0, import_node_fs27.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
|
|
22129
22379
|
} catch {
|
|
22130
22380
|
}
|
|
22131
22381
|
pruneOldBaselines();
|
|
@@ -22136,9 +22386,9 @@ function readBaseline(sessionId) {
|
|
|
22136
22386
|
}
|
|
22137
22387
|
function readManifest(dir) {
|
|
22138
22388
|
const mp = manifestPath(dir);
|
|
22139
|
-
if (!(0,
|
|
22389
|
+
if (!(0, import_node_fs27.existsSync)(mp)) return null;
|
|
22140
22390
|
try {
|
|
22141
|
-
const parsed = JSON.parse((0,
|
|
22391
|
+
const parsed = JSON.parse((0, import_node_fs27.readFileSync)(mp, "utf-8"));
|
|
22142
22392
|
if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
|
|
22143
22393
|
return null;
|
|
22144
22394
|
}
|
|
@@ -22169,9 +22419,9 @@ function preImage(repoRelPath, baseline) {
|
|
|
22169
22419
|
function resolvePreImage(repoRelPath, baseline) {
|
|
22170
22420
|
if (baseline.dirty_paths.includes(repoRelPath)) {
|
|
22171
22421
|
const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
|
|
22172
|
-
if ((0,
|
|
22422
|
+
if ((0, import_node_fs27.existsSync)(mp)) {
|
|
22173
22423
|
try {
|
|
22174
|
-
return { content: (0,
|
|
22424
|
+
return { content: (0, import_node_fs27.readFileSync)(mp, "utf-8"), existed: true };
|
|
22175
22425
|
} catch {
|
|
22176
22426
|
}
|
|
22177
22427
|
}
|
|
@@ -22216,8 +22466,8 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
22216
22466
|
const content = safeReadForMirror(projectPath(p));
|
|
22217
22467
|
if (content === null) continue;
|
|
22218
22468
|
const dest = mirrorPath(dir, p);
|
|
22219
|
-
(0,
|
|
22220
|
-
(0,
|
|
22469
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path24.dirname)(dest), { recursive: true });
|
|
22470
|
+
(0, import_node_fs27.writeFileSync)(dest, content);
|
|
22221
22471
|
dirty.add(p);
|
|
22222
22472
|
adopted++;
|
|
22223
22473
|
} catch {
|
|
@@ -22226,7 +22476,7 @@ function absorbIntoBaseline(paths, sessionId) {
|
|
|
22226
22476
|
if (adopted === 0) return 0;
|
|
22227
22477
|
try {
|
|
22228
22478
|
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
22229
|
-
(0,
|
|
22479
|
+
(0, import_node_fs27.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
22230
22480
|
preImageCache.delete(baseline);
|
|
22231
22481
|
} catch {
|
|
22232
22482
|
return 0;
|
|
@@ -22237,7 +22487,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
22237
22487
|
const pre = preImage(repoRelPath, baseline);
|
|
22238
22488
|
let current;
|
|
22239
22489
|
try {
|
|
22240
|
-
current = (0,
|
|
22490
|
+
current = (0, import_node_fs27.readFileSync)(projectPath(repoRelPath), "utf-8");
|
|
22241
22491
|
} catch {
|
|
22242
22492
|
return pre.existed;
|
|
22243
22493
|
}
|
|
@@ -22246,8 +22496,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
|
|
|
22246
22496
|
}
|
|
22247
22497
|
function safeReadForMirror(absPath) {
|
|
22248
22498
|
try {
|
|
22249
|
-
if ((0,
|
|
22250
|
-
const buf = (0,
|
|
22499
|
+
if ((0, import_node_fs27.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
|
|
22500
|
+
const buf = (0, import_node_fs27.readFileSync)(absPath);
|
|
22251
22501
|
if (buf.includes(0)) return null;
|
|
22252
22502
|
return buf.toString("utf-8");
|
|
22253
22503
|
} catch {
|
|
@@ -22258,18 +22508,18 @@ function pruneOldBaselines() {
|
|
|
22258
22508
|
const root = projectPath(BASELINE_DIR);
|
|
22259
22509
|
let entries;
|
|
22260
22510
|
try {
|
|
22261
|
-
entries = (0,
|
|
22511
|
+
entries = (0, import_node_fs27.readdirSync)(root);
|
|
22262
22512
|
} catch {
|
|
22263
22513
|
return;
|
|
22264
22514
|
}
|
|
22265
22515
|
const now = Date.now();
|
|
22266
22516
|
for (const name2 of entries) {
|
|
22267
|
-
const dir = (0,
|
|
22517
|
+
const dir = (0, import_node_path24.join)(root, name2);
|
|
22268
22518
|
const manifest = readManifest(dir);
|
|
22269
22519
|
if (!manifest) {
|
|
22270
22520
|
try {
|
|
22271
|
-
if (now - (0,
|
|
22272
|
-
(0,
|
|
22521
|
+
if (now - (0, import_node_fs27.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
|
|
22522
|
+
(0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
|
|
22273
22523
|
}
|
|
22274
22524
|
} catch {
|
|
22275
22525
|
}
|
|
@@ -22277,7 +22527,7 @@ function pruneOldBaselines() {
|
|
|
22277
22527
|
}
|
|
22278
22528
|
if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
|
|
22279
22529
|
try {
|
|
22280
|
-
(0,
|
|
22530
|
+
(0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
|
|
22281
22531
|
} catch {
|
|
22282
22532
|
}
|
|
22283
22533
|
}
|
|
@@ -22452,8 +22702,8 @@ function buildCompactionContext(session) {
|
|
|
22452
22702
|
commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
|
|
22453
22703
|
readFileLines: (file) => {
|
|
22454
22704
|
try {
|
|
22455
|
-
const abs = (0,
|
|
22456
|
-
return (0,
|
|
22705
|
+
const abs = (0, import_node_path25.join)(root, file);
|
|
22706
|
+
return (0, import_node_fs28.existsSync)(abs) ? (0, import_node_fs28.readFileSync)(abs, "utf8").split("\n") : null;
|
|
22457
22707
|
} catch {
|
|
22458
22708
|
return null;
|
|
22459
22709
|
}
|
|
@@ -22510,24 +22760,24 @@ async function readHookStdin() {
|
|
|
22510
22760
|
|
|
22511
22761
|
// src/commands/standard.ts
|
|
22512
22762
|
var import_promises13 = require("node:fs/promises");
|
|
22513
|
-
var
|
|
22763
|
+
var import_node_fs35 = require("node:fs");
|
|
22514
22764
|
var import_yaml3 = __toESM2(require_dist());
|
|
22515
22765
|
|
|
22516
22766
|
// src/lib/synthesize.ts
|
|
22517
22767
|
var import_node_child_process9 = require("node:child_process");
|
|
22518
|
-
var
|
|
22768
|
+
var import_node_fs31 = require("node:fs");
|
|
22519
22769
|
var import_promises10 = require("node:fs/promises");
|
|
22520
|
-
var
|
|
22770
|
+
var import_node_path28 = require("node:path");
|
|
22521
22771
|
var import_yaml = __toESM2(require_dist());
|
|
22522
22772
|
|
|
22523
22773
|
// src/lib/data-dir.ts
|
|
22524
|
-
var
|
|
22525
|
-
var
|
|
22774
|
+
var import_node_fs29 = require("node:fs");
|
|
22775
|
+
var import_node_path26 = require("node:path");
|
|
22526
22776
|
function resolveDataDir() {
|
|
22527
22777
|
const candidates2 = [
|
|
22528
|
-
(0,
|
|
22778
|
+
(0, import_node_path26.join)(__dirname, "..", "data"),
|
|
22529
22779
|
// installed: node_modules/@codacy/verity-cli/data
|
|
22530
|
-
(0,
|
|
22780
|
+
(0, import_node_path26.join)(__dirname, "..", "..", "data"),
|
|
22531
22781
|
// edge case: nested resolution
|
|
22532
22782
|
// THE COMMITTED SOURCE, for a source checkout that has not been built.
|
|
22533
22783
|
// cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
|
|
@@ -22536,14 +22786,14 @@ function resolveDataDir() {
|
|
|
22536
22786
|
// without this the synthesizer throws "Could not find Verity skill data"
|
|
22537
22787
|
// for every test and every `verity` run from source. Resolved from this
|
|
22538
22788
|
// module's own location, never the cwd: see the warning below.
|
|
22539
|
-
(0,
|
|
22789
|
+
(0, import_node_path26.join)(__dirname, "..", "..", "client"),
|
|
22540
22790
|
// bundled: cli/bin/ → ../../client
|
|
22541
|
-
(0,
|
|
22791
|
+
(0, import_node_path26.join)(__dirname, "..", "..", "..", "client"),
|
|
22542
22792
|
// tsx: cli/src/lib/ → ../../../client
|
|
22543
22793
|
...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
|
|
22544
22794
|
];
|
|
22545
22795
|
for (const candidate of candidates2) {
|
|
22546
|
-
if ((0,
|
|
22796
|
+
if ((0, import_node_fs29.existsSync)((0, import_node_path26.join)(candidate, "skills"))) {
|
|
22547
22797
|
return candidate;
|
|
22548
22798
|
}
|
|
22549
22799
|
}
|
|
@@ -22552,13 +22802,13 @@ function resolveDataDir() {
|
|
|
22552
22802
|
);
|
|
22553
22803
|
}
|
|
22554
22804
|
function setupDataPath(file) {
|
|
22555
|
-
return (0,
|
|
22805
|
+
return (0, import_node_path26.join)(resolveDataDir(), "skills", "verity-setup", file);
|
|
22556
22806
|
}
|
|
22557
22807
|
|
|
22558
22808
|
// src/lib/detect.ts
|
|
22559
22809
|
var import_node_child_process8 = require("node:child_process");
|
|
22560
|
-
var
|
|
22561
|
-
var
|
|
22810
|
+
var import_node_fs30 = require("node:fs");
|
|
22811
|
+
var import_node_path27 = require("node:path");
|
|
22562
22812
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
22563
22813
|
"typescript",
|
|
22564
22814
|
"javascript",
|
|
@@ -22615,25 +22865,25 @@ function walk(root) {
|
|
|
22615
22865
|
if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
|
|
22616
22866
|
let entries;
|
|
22617
22867
|
try {
|
|
22618
|
-
entries = (0,
|
|
22868
|
+
entries = (0, import_node_fs30.readdirSync)(dir, { withFileTypes: true });
|
|
22619
22869
|
} catch {
|
|
22620
22870
|
return;
|
|
22621
22871
|
}
|
|
22622
22872
|
for (const entry of entries) {
|
|
22623
22873
|
if (found.length >= WALK_MAX_FILES) return;
|
|
22624
22874
|
if (IGNORED_SEGMENTS.includes(entry.name)) continue;
|
|
22625
|
-
const full = (0,
|
|
22875
|
+
const full = (0, import_node_path27.join)(dir, entry.name);
|
|
22626
22876
|
if (entry.isDirectory()) visit(full, depth + 1);
|
|
22627
|
-
else if (entry.isFile()) found.push((0,
|
|
22877
|
+
else if (entry.isFile()) found.push((0, import_node_path27.relative)(root, full));
|
|
22628
22878
|
}
|
|
22629
22879
|
};
|
|
22630
22880
|
visit(root, 0);
|
|
22631
22881
|
return found;
|
|
22632
22882
|
}
|
|
22633
22883
|
function languageOf(path) {
|
|
22634
|
-
const name2 = (0,
|
|
22884
|
+
const name2 = (0, import_node_path27.basename)(path);
|
|
22635
22885
|
if (/^Dockerfile(\..+)?$/i.test(name2)) return "dockerfile";
|
|
22636
|
-
if (!(0,
|
|
22886
|
+
if (!(0, import_node_path27.extname)(name2)) return null;
|
|
22637
22887
|
const lang = detectLanguage(path);
|
|
22638
22888
|
return lang || null;
|
|
22639
22889
|
}
|
|
@@ -22690,7 +22940,7 @@ var TOOL_CONFIG_MARKERS = [
|
|
|
22690
22940
|
];
|
|
22691
22941
|
function readJson2(path) {
|
|
22692
22942
|
try {
|
|
22693
|
-
return JSON.parse((0,
|
|
22943
|
+
return JSON.parse((0, import_node_fs30.readFileSync)(path, "utf-8"));
|
|
22694
22944
|
} catch {
|
|
22695
22945
|
return null;
|
|
22696
22946
|
}
|
|
@@ -22715,17 +22965,17 @@ function declaredDependencies(root, files) {
|
|
|
22715
22965
|
if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
|
|
22716
22966
|
}
|
|
22717
22967
|
};
|
|
22718
|
-
readPackageJson((0,
|
|
22719
|
-
const nested = files.filter((f) => f.includes("/") && (0,
|
|
22720
|
-
for (const rel of nested) readPackageJson((0,
|
|
22968
|
+
readPackageJson((0, import_node_path27.join)(root, "package.json"));
|
|
22969
|
+
const nested = files.filter((f) => f.includes("/") && (0, import_node_path27.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
|
|
22970
|
+
for (const rel of nested) readPackageJson((0, import_node_path27.join)(root, rel));
|
|
22721
22971
|
const pythonManifests = [
|
|
22722
|
-
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0,
|
|
22723
|
-
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0,
|
|
22972
|
+
...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path27.join)(root, f)),
|
|
22973
|
+
...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path27.join)(root, f))
|
|
22724
22974
|
];
|
|
22725
22975
|
for (const path of pythonManifests) {
|
|
22726
|
-
if (!(0,
|
|
22976
|
+
if (!(0, import_node_fs30.existsSync)(path)) continue;
|
|
22727
22977
|
try {
|
|
22728
|
-
const text = (0,
|
|
22978
|
+
const text = (0, import_node_fs30.readFileSync)(path, "utf-8");
|
|
22729
22979
|
for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
22730
22980
|
for (const line2 of text.split("\n")) {
|
|
22731
22981
|
if (!/dependencies\s*=/.test(line2)) continue;
|
|
@@ -22735,13 +22985,13 @@ function declaredDependencies(root, files) {
|
|
|
22735
22985
|
}
|
|
22736
22986
|
}
|
|
22737
22987
|
const goMods = [
|
|
22738
|
-
(0,
|
|
22739
|
-
...files.filter((f) => f.includes("/") && (0,
|
|
22988
|
+
(0, import_node_path27.join)(root, "go.mod"),
|
|
22989
|
+
...files.filter((f) => f.includes("/") && (0, import_node_path27.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path27.join)(root, f))
|
|
22740
22990
|
];
|
|
22741
22991
|
for (const path of goMods) {
|
|
22742
|
-
if (!(0,
|
|
22992
|
+
if (!(0, import_node_fs30.existsSync)(path)) continue;
|
|
22743
22993
|
try {
|
|
22744
|
-
const text = (0,
|
|
22994
|
+
const text = (0, import_node_fs30.readFileSync)(path, "utf-8");
|
|
22745
22995
|
for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
22746
22996
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
22747
22997
|
}
|
|
@@ -22749,10 +22999,10 @@ function declaredDependencies(root, files) {
|
|
|
22749
22999
|
}
|
|
22750
23000
|
}
|
|
22751
23001
|
for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
|
|
22752
|
-
const path = (0,
|
|
22753
|
-
if (!(0,
|
|
23002
|
+
const path = (0, import_node_path27.join)(root, file);
|
|
23003
|
+
if (!(0, import_node_fs30.existsSync)(path)) continue;
|
|
22754
23004
|
try {
|
|
22755
|
-
const text = (0,
|
|
23005
|
+
const text = (0, import_node_fs30.readFileSync)(path, "utf-8");
|
|
22756
23006
|
for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
22757
23007
|
} catch {
|
|
22758
23008
|
}
|
|
@@ -22760,7 +23010,7 @@ function declaredDependencies(root, files) {
|
|
|
22760
23010
|
return names2;
|
|
22761
23011
|
}
|
|
22762
23012
|
function detectBuildSystem(root, files) {
|
|
22763
|
-
const has = (f) => (0,
|
|
23013
|
+
const has = (f) => (0, import_node_fs30.existsSync)((0, import_node_path27.join)(root, f)) || files.some((p) => (0, import_node_path27.basename)(p) === f);
|
|
22764
23014
|
if (has("pnpm-lock.yaml")) return "pnpm";
|
|
22765
23015
|
if (has("yarn.lock")) return "yarn";
|
|
22766
23016
|
if (has("bun.lock") || has("bun.lockb")) return "bun";
|
|
@@ -22777,8 +23027,8 @@ function detectBuildSystem(root, files) {
|
|
|
22777
23027
|
}
|
|
22778
23028
|
function detectArchitecture(root, files) {
|
|
22779
23029
|
const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
|
|
22780
|
-
if (workspaceMarkers.some((m) => (0,
|
|
22781
|
-
const pkg = readJson2((0,
|
|
23030
|
+
if (workspaceMarkers.some((m) => (0, import_node_fs30.existsSync)((0, import_node_path27.join)(root, m)))) return "monorepo";
|
|
23031
|
+
const pkg = readJson2((0, import_node_path27.join)(root, "package.json"));
|
|
22782
23032
|
if (pkg && "workspaces" in pkg) return "monorepo";
|
|
22783
23033
|
const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
|
|
22784
23034
|
const nested = manifests.filter((f) => f.includes("/"));
|
|
@@ -22800,10 +23050,10 @@ function measureAvgFileLength(root, files, languages) {
|
|
|
22800
23050
|
let total = 0;
|
|
22801
23051
|
let counted = 0;
|
|
22802
23052
|
for (let i2 = 0; i2 < candidates2.length; i2 += stride) {
|
|
22803
|
-
const path = (0,
|
|
23053
|
+
const path = (0, import_node_path27.join)(root, candidates2[i2]);
|
|
22804
23054
|
try {
|
|
22805
|
-
if ((0,
|
|
22806
|
-
total += (0,
|
|
23055
|
+
if ((0, import_node_fs30.statSync)(path).size > 2 * 1024 * 1024) continue;
|
|
23056
|
+
total += (0, import_node_fs30.readFileSync)(path, "utf-8").split("\n").length;
|
|
22807
23057
|
counted++;
|
|
22808
23058
|
} catch {
|
|
22809
23059
|
}
|
|
@@ -22833,14 +23083,14 @@ function detectProject(root = repoRoot()) {
|
|
|
22833
23083
|
const existingToolConfigs = [];
|
|
22834
23084
|
for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
|
|
22835
23085
|
for (const marker of markers) {
|
|
22836
|
-
if ((0,
|
|
23086
|
+
if ((0, import_node_fs30.existsSync)((0, import_node_path27.join)(root, marker))) {
|
|
22837
23087
|
existingToolConfigs.push({ tool, path: `./${marker}` });
|
|
22838
23088
|
break;
|
|
22839
23089
|
}
|
|
22840
23090
|
}
|
|
22841
23091
|
}
|
|
22842
23092
|
return {
|
|
22843
|
-
projectName: (0,
|
|
23093
|
+
projectName: (0, import_node_path27.basename)(root),
|
|
22844
23094
|
languages,
|
|
22845
23095
|
languageCounts,
|
|
22846
23096
|
frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
|
|
@@ -22938,8 +23188,8 @@ ${closingNote(input.origin)}
|
|
|
22938
23188
|
|
|
22939
23189
|
// src/lib/synthesize.ts
|
|
22940
23190
|
function loadCatalog() {
|
|
22941
|
-
const catalog = (0, import_yaml.parse)((0,
|
|
22942
|
-
const template = (0, import_yaml.parse)((0,
|
|
23191
|
+
const catalog = (0, import_yaml.parse)((0, import_node_fs31.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
|
|
23192
|
+
const template = (0, import_yaml.parse)((0, import_node_fs31.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
|
|
22943
23193
|
return { catalog, template };
|
|
22944
23194
|
}
|
|
22945
23195
|
function selectTools(languages, intensity, catalog) {
|
|
@@ -23217,7 +23467,7 @@ function validatePatternIds() {
|
|
|
23217
23467
|
}
|
|
23218
23468
|
async function runSynthesis(opts) {
|
|
23219
23469
|
const standardPath = projectPath(STANDARD_FILE);
|
|
23220
|
-
if ((0,
|
|
23470
|
+
if ((0, import_node_fs31.existsSync)(standardPath) && !opts.force) {
|
|
23221
23471
|
return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
|
|
23222
23472
|
}
|
|
23223
23473
|
const detected = opts.detected ?? detectProject();
|
|
@@ -23286,7 +23536,7 @@ async function correctVerityMdVersion(opts) {
|
|
|
23286
23536
|
}
|
|
23287
23537
|
async function writeFileTo(relative6, body2) {
|
|
23288
23538
|
const target = projectPath(relative6);
|
|
23289
|
-
await (0, import_promises10.mkdir)((0,
|
|
23539
|
+
await (0, import_promises10.mkdir)((0, import_node_path28.dirname)(target), { recursive: true });
|
|
23290
23540
|
await (0, import_promises10.writeFile)(target, body2);
|
|
23291
23541
|
}
|
|
23292
23542
|
async function deriveConfigForStandard(standard) {
|
|
@@ -23345,11 +23595,11 @@ ${validation.detail}`);
|
|
|
23345
23595
|
|
|
23346
23596
|
// src/lib/setup-state.ts
|
|
23347
23597
|
var import_promises11 = require("node:fs/promises");
|
|
23348
|
-
var
|
|
23598
|
+
var import_node_fs32 = require("node:fs");
|
|
23349
23599
|
var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
|
|
23350
23600
|
async function readSetupState() {
|
|
23351
23601
|
const path = projectPath(SETUP_STATE_FILE);
|
|
23352
|
-
if (!(0,
|
|
23602
|
+
if (!(0, import_node_fs32.existsSync)(path)) return null;
|
|
23353
23603
|
try {
|
|
23354
23604
|
const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
|
|
23355
23605
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
@@ -23365,12 +23615,12 @@ async function writeSetupState(patch) {
|
|
|
23365
23615
|
}
|
|
23366
23616
|
|
|
23367
23617
|
// src/lib/push-setup.ts
|
|
23368
|
-
var
|
|
23618
|
+
var import_node_fs34 = require("node:fs");
|
|
23369
23619
|
var import_promises12 = require("node:fs/promises");
|
|
23370
23620
|
var import_yaml2 = __toESM2(require_dist());
|
|
23371
23621
|
|
|
23372
23622
|
// src/lib/verityignore.ts
|
|
23373
|
-
var
|
|
23623
|
+
var import_node_fs33 = require("node:fs");
|
|
23374
23624
|
var EMPTY = { rules: [], securityOverlap: [], problems: [] };
|
|
23375
23625
|
var SECURITY_PROBES = [
|
|
23376
23626
|
".env",
|
|
@@ -23463,9 +23713,9 @@ function isIgnored3(ig, path) {
|
|
|
23463
23713
|
}
|
|
23464
23714
|
function loadVerityIgnore() {
|
|
23465
23715
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
23466
|
-
if (!(0,
|
|
23716
|
+
if (!(0, import_node_fs33.existsSync)(file)) return EMPTY;
|
|
23467
23717
|
try {
|
|
23468
|
-
return parseVerityIgnore((0,
|
|
23718
|
+
return parseVerityIgnore((0, import_node_fs33.readFileSync)(file, "utf-8"));
|
|
23469
23719
|
} catch {
|
|
23470
23720
|
return EMPTY;
|
|
23471
23721
|
}
|
|
@@ -23503,9 +23753,9 @@ function buildStandardUpload(standard, ignoreRaw) {
|
|
|
23503
23753
|
}
|
|
23504
23754
|
function readVerityIgnoreRaw() {
|
|
23505
23755
|
const file = projectPath(VERITYIGNORE_FILE);
|
|
23506
|
-
if (!(0,
|
|
23756
|
+
if (!(0, import_node_fs33.existsSync)(file)) return null;
|
|
23507
23757
|
try {
|
|
23508
|
-
return (0,
|
|
23758
|
+
return (0, import_node_fs33.readFileSync)(file, "utf-8");
|
|
23509
23759
|
} catch {
|
|
23510
23760
|
return null;
|
|
23511
23761
|
}
|
|
@@ -23533,7 +23783,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
23533
23783
|
}
|
|
23534
23784
|
let standardVersion = null;
|
|
23535
23785
|
const standardPath = projectPath(STANDARD_FILE);
|
|
23536
|
-
if (pushStandard && (0,
|
|
23786
|
+
if (pushStandard && (0, import_node_fs34.existsSync)(standardPath)) {
|
|
23537
23787
|
try {
|
|
23538
23788
|
const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
|
|
23539
23789
|
const upload = buildStandardUpload(content, readVerityIgnoreRaw());
|
|
@@ -23558,7 +23808,7 @@ async function pushStandardAndConfig(globals, what = {}) {
|
|
|
23558
23808
|
}
|
|
23559
23809
|
let configPushed = false;
|
|
23560
23810
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
23561
|
-
if (pushConfig && (0,
|
|
23811
|
+
if (pushConfig && (0, import_node_fs34.existsSync)(configPath)) {
|
|
23562
23812
|
try {
|
|
23563
23813
|
const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
|
|
23564
23814
|
const result = await apiRequest({
|
|
@@ -23590,7 +23840,7 @@ function registerStandardCommands(program2) {
|
|
|
23590
23840
|
const state = await readSetupState();
|
|
23591
23841
|
if (opts.configOnly) {
|
|
23592
23842
|
const standardPath = projectPath(STANDARD_FILE);
|
|
23593
|
-
if (!(0,
|
|
23843
|
+
if (!(0, import_node_fs35.existsSync)(standardPath)) {
|
|
23594
23844
|
printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
|
|
23595
23845
|
process.exit(1);
|
|
23596
23846
|
}
|
|
@@ -23936,10 +24186,10 @@ function formatRunDetail(run4) {
|
|
|
23936
24186
|
}
|
|
23937
24187
|
|
|
23938
24188
|
// src/lib/ignore-declaration.ts
|
|
23939
|
-
var
|
|
24189
|
+
var import_node_fs37 = require("node:fs");
|
|
23940
24190
|
|
|
23941
24191
|
// src/lib/debounce.ts
|
|
23942
|
-
var
|
|
24192
|
+
var import_node_fs36 = require("node:fs");
|
|
23943
24193
|
var import_node_crypto11 = require("node:crypto");
|
|
23944
24194
|
function scopedFile(base, sessionId) {
|
|
23945
24195
|
if (!sessionId) return base;
|
|
@@ -23947,9 +24197,9 @@ function scopedFile(base, sessionId) {
|
|
|
23947
24197
|
}
|
|
23948
24198
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
23949
24199
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
23950
|
-
if (!(0,
|
|
24200
|
+
if (!(0, import_node_fs36.existsSync)(file)) return null;
|
|
23951
24201
|
try {
|
|
23952
|
-
const lastTs = parseInt((0,
|
|
24202
|
+
const lastTs = parseInt((0, import_node_fs36.readFileSync)(file, "utf-8").trim(), 10);
|
|
23953
24203
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
23954
24204
|
const elapsed = nowTs - lastTs;
|
|
23955
24205
|
if (elapsed < debounceSeconds) {
|
|
@@ -23962,10 +24212,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
|
23962
24212
|
function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
23963
24213
|
if (bypassForRecentCommits) return null;
|
|
23964
24214
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
23965
|
-
if (!(0,
|
|
24215
|
+
if (!(0, import_node_fs36.existsSync)(file)) return null;
|
|
23966
24216
|
let debounceTime;
|
|
23967
24217
|
try {
|
|
23968
|
-
debounceTime = (0,
|
|
24218
|
+
debounceTime = (0, import_node_fs36.statSync)(file).mtimeMs;
|
|
23969
24219
|
} catch {
|
|
23970
24220
|
return null;
|
|
23971
24221
|
}
|
|
@@ -23973,7 +24223,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
23973
24223
|
const resolved = resolveFile(f);
|
|
23974
24224
|
if (!resolved) continue;
|
|
23975
24225
|
try {
|
|
23976
|
-
const stat3 = (0,
|
|
24226
|
+
const stat3 = (0, import_node_fs36.statSync)(resolved);
|
|
23977
24227
|
if (stat3.mtimeMs > debounceTime) {
|
|
23978
24228
|
return null;
|
|
23979
24229
|
}
|
|
@@ -23989,8 +24239,8 @@ function computeContentHash(files) {
|
|
|
23989
24239
|
for (const f of sorted) {
|
|
23990
24240
|
const resolved = resolveFile(f) ?? f;
|
|
23991
24241
|
try {
|
|
23992
|
-
if ((0,
|
|
23993
|
-
hash.update((0,
|
|
24242
|
+
if ((0, import_node_fs36.existsSync)(resolved)) {
|
|
24243
|
+
hash.update((0, import_node_fs36.readFileSync)(resolved));
|
|
23994
24244
|
}
|
|
23995
24245
|
} catch {
|
|
23996
24246
|
}
|
|
@@ -24000,9 +24250,9 @@ function computeContentHash(files) {
|
|
|
24000
24250
|
function checkContentHash(files, sessionId) {
|
|
24001
24251
|
const hash = computeContentHash(files);
|
|
24002
24252
|
const file = scopedFile(HASH_FILE, sessionId);
|
|
24003
|
-
if ((0,
|
|
24253
|
+
if ((0, import_node_fs36.existsSync)(file)) {
|
|
24004
24254
|
try {
|
|
24005
|
-
const storedHash = (0,
|
|
24255
|
+
const storedHash = (0, import_node_fs36.readFileSync)(file, "utf-8").trim();
|
|
24006
24256
|
if (hash === storedHash) {
|
|
24007
24257
|
return { skip: "No source changes since last analysis", hash };
|
|
24008
24258
|
}
|
|
@@ -24012,24 +24262,24 @@ function checkContentHash(files, sessionId) {
|
|
|
24012
24262
|
return { skip: null, hash };
|
|
24013
24263
|
}
|
|
24014
24264
|
function recordAnalysisStart(sessionId) {
|
|
24015
|
-
(0,
|
|
24016
|
-
(0,
|
|
24265
|
+
(0, import_node_fs36.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
24266
|
+
(0, import_node_fs36.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
|
|
24017
24267
|
}
|
|
24018
24268
|
function recordPassHash(hash, sessionId) {
|
|
24019
|
-
(0,
|
|
24269
|
+
(0, import_node_fs36.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
|
|
24020
24270
|
}
|
|
24021
24271
|
function narrowToRecent(files, sessionId) {
|
|
24022
24272
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
24023
|
-
if (!(0,
|
|
24273
|
+
if (!(0, import_node_fs36.existsSync)(file)) return files;
|
|
24024
24274
|
let debounceTime;
|
|
24025
24275
|
try {
|
|
24026
|
-
debounceTime = (0,
|
|
24276
|
+
debounceTime = (0, import_node_fs36.statSync)(file).mtimeMs;
|
|
24027
24277
|
} catch {
|
|
24028
24278
|
return files;
|
|
24029
24279
|
}
|
|
24030
24280
|
const recent = files.filter((f) => {
|
|
24031
24281
|
try {
|
|
24032
|
-
return (0,
|
|
24282
|
+
return (0, import_node_fs36.existsSync)(f) && (0, import_node_fs36.statSync)(f).mtimeMs > debounceTime;
|
|
24033
24283
|
} catch {
|
|
24034
24284
|
return false;
|
|
24035
24285
|
}
|
|
@@ -24042,9 +24292,9 @@ function readIteration(currentCommit, _contentHash) {
|
|
|
24042
24292
|
var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
|
|
24043
24293
|
function readBlockState(currentCommit, opts) {
|
|
24044
24294
|
if (opts?.newUserPrompt) return NO_BLOCKS;
|
|
24045
|
-
if (!(0,
|
|
24295
|
+
if (!(0, import_node_fs36.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
|
|
24046
24296
|
try {
|
|
24047
|
-
const stored = (0,
|
|
24297
|
+
const stored = (0, import_node_fs36.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
24048
24298
|
const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
|
|
24049
24299
|
if (!parsed) return NO_BLOCKS;
|
|
24050
24300
|
if (parsed.commit !== currentCommit) return NO_BLOCKS;
|
|
@@ -24090,8 +24340,8 @@ function isSameProblem(previous, current) {
|
|
|
24090
24340
|
return current.split(",").some((k) => prev.has(k));
|
|
24091
24341
|
}
|
|
24092
24342
|
function writeBlockState(commit, state) {
|
|
24093
|
-
(0,
|
|
24094
|
-
(0,
|
|
24343
|
+
(0, import_node_fs36.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
24344
|
+
(0, import_node_fs36.writeFileSync)(
|
|
24095
24345
|
ITERATION_FILE,
|
|
24096
24346
|
JSON.stringify({
|
|
24097
24347
|
v: 2,
|
|
@@ -24196,9 +24446,9 @@ function resolveIgnoreState(keys) {
|
|
|
24196
24446
|
}
|
|
24197
24447
|
function readIgnoreState(sessionId) {
|
|
24198
24448
|
const file = stateFile(sessionId);
|
|
24199
|
-
if (!(0,
|
|
24449
|
+
if (!(0, import_node_fs37.existsSync)(file)) return null;
|
|
24200
24450
|
try {
|
|
24201
|
-
const o = JSON.parse((0,
|
|
24451
|
+
const o = JSON.parse((0, import_node_fs37.readFileSync)(file, "utf-8")) ?? {};
|
|
24202
24452
|
const spent = typeof o.spent === "number" ? o.spent : 0;
|
|
24203
24453
|
const raw = o.active;
|
|
24204
24454
|
let active = null;
|
|
@@ -24222,8 +24472,8 @@ function readIgnoreState(sessionId) {
|
|
|
24222
24472
|
}
|
|
24223
24473
|
function writeIgnoreState(state, sessionId) {
|
|
24224
24474
|
try {
|
|
24225
|
-
(0,
|
|
24226
|
-
(0,
|
|
24475
|
+
(0, import_node_fs37.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
24476
|
+
(0, import_node_fs37.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
|
|
24227
24477
|
} catch {
|
|
24228
24478
|
}
|
|
24229
24479
|
}
|
|
@@ -24606,7 +24856,7 @@ function createRun(opts, globals) {
|
|
|
24606
24856
|
}
|
|
24607
24857
|
|
|
24608
24858
|
// src/commands/analyze/index.ts
|
|
24609
|
-
var
|
|
24859
|
+
var import_node_fs51 = require("node:fs");
|
|
24610
24860
|
|
|
24611
24861
|
// src/lib/repo-context.ts
|
|
24612
24862
|
var import_node_child_process11 = require("node:child_process");
|
|
@@ -25645,10 +25895,10 @@ function installRunEvidence(run4) {
|
|
|
25645
25895
|
}
|
|
25646
25896
|
|
|
25647
25897
|
// src/lib/git-frame.ts
|
|
25648
|
-
var
|
|
25898
|
+
var import_node_fs38 = require("node:fs");
|
|
25649
25899
|
var import_node_os6 = require("node:os");
|
|
25650
|
-
var import_node_path28 = require("node:path");
|
|
25651
25900
|
var import_node_path29 = require("node:path");
|
|
25901
|
+
var import_node_path30 = require("node:path");
|
|
25652
25902
|
var VALUE_TOKEN = `(?:'[^']*'|"[^"]*"|\\S+)`;
|
|
25653
25903
|
var GIT_GLOBAL_OPTS = `(?:\\s+(?:-[Cc]\\s+${VALUE_TOKEN}|--?[\\w-]+(?:=\\S+)?))*`;
|
|
25654
25904
|
var COMMIT_HEAD = `git${GIT_GLOBAL_OPTS}\\s+commit(?![\\w-])`;
|
|
@@ -25735,8 +25985,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
25735
25985
|
if (SHELL_DYNAMIC.test(raw) || raw === "-") {
|
|
25736
25986
|
return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
|
|
25737
25987
|
}
|
|
25738
|
-
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0,
|
|
25739
|
-
dir = (0,
|
|
25988
|
+
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path30.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
|
|
25989
|
+
dir = (0, import_node_path29.isAbsolute)(expanded) ? expanded : (0, import_node_path29.resolve)(dir, expanded);
|
|
25740
25990
|
}
|
|
25741
25991
|
const seg = segments[segmentIndex];
|
|
25742
25992
|
const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
|
|
@@ -25754,8 +26004,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
25754
26004
|
if (SHELL_DYNAMIC.test(raw)) {
|
|
25755
26005
|
return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
|
|
25756
26006
|
}
|
|
25757
|
-
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0,
|
|
25758
|
-
dir = (0,
|
|
26007
|
+
const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path30.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
|
|
26008
|
+
dir = (0, import_node_path29.isAbsolute)(expanded) ? expanded : (0, import_node_path29.resolve)(dir, expanded);
|
|
25759
26009
|
}
|
|
25760
26010
|
}
|
|
25761
26011
|
return { dir, named, unresolvable: null };
|
|
@@ -25815,14 +26065,14 @@ function gitAt(dir, args2) {
|
|
|
25815
26065
|
}
|
|
25816
26066
|
function realpathOr2(p) {
|
|
25817
26067
|
try {
|
|
25818
|
-
return
|
|
26068
|
+
return import_node_fs38.realpathSync.native(p);
|
|
25819
26069
|
} catch {
|
|
25820
|
-
return (0,
|
|
26070
|
+
return (0, import_node_path29.resolve)(p);
|
|
25821
26071
|
}
|
|
25822
26072
|
}
|
|
25823
26073
|
function resolveFrame(input) {
|
|
25824
26074
|
const found = findMomentSegment(input.command, input.on);
|
|
25825
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
26075
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs38.existsSync)(input.hookCwd);
|
|
25826
26076
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
25827
26077
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
25828
26078
|
const refuse = (refusal) => ({
|
|
@@ -25845,7 +26095,7 @@ function resolveFrame(input) {
|
|
|
25845
26095
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
25846
26096
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
25847
26097
|
if (targetDir !== baseDir) {
|
|
25848
|
-
if (!(0,
|
|
26098
|
+
if (!(0, import_node_fs38.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
25849
26099
|
dir = targetDir;
|
|
25850
26100
|
}
|
|
25851
26101
|
}
|
|
@@ -25856,7 +26106,7 @@ function resolveFrame(input) {
|
|
|
25856
26106
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
25857
26107
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
25858
26108
|
const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
|
|
25859
|
-
const commonDir = commonRaw ? realpathOr2((0,
|
|
26109
|
+
const commonDir = commonRaw ? realpathOr2((0, import_node_path29.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path29.resolve)(dir, commonRaw)) : null;
|
|
25860
26110
|
const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
25861
26111
|
return {
|
|
25862
26112
|
moment: found?.moment ?? null,
|
|
@@ -26031,8 +26281,8 @@ function stagedRange(frame, command) {
|
|
|
26031
26281
|
if (plan.kind === "unpredictable") {
|
|
26032
26282
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
|
|
26033
26283
|
}
|
|
26034
|
-
const mergeHead = frame.gitDir ? (0,
|
|
26035
|
-
if (mergeHead && (0,
|
|
26284
|
+
const mergeHead = frame.gitDir ? (0, import_node_path30.join)(frame.gitDir, "MERGE_HEAD") : null;
|
|
26285
|
+
if (mergeHead && (0, import_node_fs38.existsSync)(mergeHead)) {
|
|
26036
26286
|
const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
|
|
26037
26287
|
const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
|
|
26038
26288
|
const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
|
|
@@ -26166,7 +26416,7 @@ function truthy(v) {
|
|
|
26166
26416
|
}
|
|
26167
26417
|
|
|
26168
26418
|
// src/lib/transcript.ts
|
|
26169
|
-
var
|
|
26419
|
+
var import_node_fs39 = require("node:fs");
|
|
26170
26420
|
var MAX_READ_BYTES = 256 * 1024;
|
|
26171
26421
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
26172
26422
|
var MAX_FILES_LIST = 20;
|
|
@@ -26193,7 +26443,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
26193
26443
|
function readTurnLines(transcriptPath) {
|
|
26194
26444
|
let size;
|
|
26195
26445
|
try {
|
|
26196
|
-
size = (0,
|
|
26446
|
+
size = (0, import_node_fs39.statSync)(transcriptPath).size;
|
|
26197
26447
|
} catch {
|
|
26198
26448
|
return null;
|
|
26199
26449
|
}
|
|
@@ -26201,7 +26451,7 @@ function readTurnLines(transcriptPath) {
|
|
|
26201
26451
|
let raw;
|
|
26202
26452
|
let windowed = false;
|
|
26203
26453
|
if (size <= SMALL_FILE_BYTES) {
|
|
26204
|
-
raw = (0,
|
|
26454
|
+
raw = (0, import_node_fs39.readFileSync)(transcriptPath, "utf-8");
|
|
26205
26455
|
} else {
|
|
26206
26456
|
windowed = true;
|
|
26207
26457
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -26771,7 +27021,7 @@ function channelSilence(input) {
|
|
|
26771
27021
|
// src/lib/cli-version.ts
|
|
26772
27022
|
function cliVersion() {
|
|
26773
27023
|
try {
|
|
26774
|
-
return true ? "0.33.3-experimental.
|
|
27024
|
+
return true ? "0.33.3-experimental.5a3f573" : "dev";
|
|
26775
27025
|
} catch {
|
|
26776
27026
|
return "dev";
|
|
26777
27027
|
}
|
|
@@ -26812,7 +27062,7 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
26812
27062
|
|
|
26813
27063
|
// src/lib/static-analysis.ts
|
|
26814
27064
|
var import_node_child_process12 = require("node:child_process");
|
|
26815
|
-
var
|
|
27065
|
+
var import_node_fs40 = require("node:fs");
|
|
26816
27066
|
var SEVERITY_ORDER = {
|
|
26817
27067
|
Error: 0,
|
|
26818
27068
|
Critical: 0,
|
|
@@ -26868,7 +27118,7 @@ function runCodacyAnalysis(files) {
|
|
|
26868
27118
|
if (files.length === 0) return empty;
|
|
26869
27119
|
const existingFiles = files.filter((f) => {
|
|
26870
27120
|
try {
|
|
26871
|
-
return (0,
|
|
27121
|
+
return (0, import_node_fs40.existsSync)(f);
|
|
26872
27122
|
} catch {
|
|
26873
27123
|
return false;
|
|
26874
27124
|
}
|
|
@@ -27137,8 +27387,8 @@ async function scope(run4) {
|
|
|
27137
27387
|
}
|
|
27138
27388
|
|
|
27139
27389
|
// src/lib/specs.ts
|
|
27140
|
-
var
|
|
27141
|
-
var
|
|
27390
|
+
var import_node_fs41 = require("node:fs");
|
|
27391
|
+
var import_node_path31 = require("node:path");
|
|
27142
27392
|
var SPEC_CANDIDATES = [
|
|
27143
27393
|
"CLAUDE.md",
|
|
27144
27394
|
"AGENTS.md",
|
|
@@ -27160,7 +27410,7 @@ var UNCONSULTED_TOTAL_BYTES = 30720;
|
|
|
27160
27410
|
function readSpecFiles(specsOpt, root) {
|
|
27161
27411
|
const out2 = [];
|
|
27162
27412
|
for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
|
|
27163
|
-
const candidate = (0,
|
|
27413
|
+
const candidate = (0, import_node_path31.isAbsolute)(raw) ? (0, import_node_path31.relative)(root, raw) : raw;
|
|
27164
27414
|
const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
|
|
27165
27415
|
if (content === null) continue;
|
|
27166
27416
|
out2.push({ path: raw, content });
|
|
@@ -27179,7 +27429,7 @@ function discoverSpecs(consulted = []) {
|
|
|
27179
27429
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
27180
27430
|
if (totalBytes >= totalCap) return false;
|
|
27181
27431
|
if (seen.has(specPath)) return true;
|
|
27182
|
-
if (!(0,
|
|
27432
|
+
if (!(0, import_node_fs41.existsSync)(specPath)) return true;
|
|
27183
27433
|
seen.add(specPath);
|
|
27184
27434
|
const remaining = totalCap - totalBytes;
|
|
27185
27435
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
@@ -27202,7 +27452,7 @@ function discoverSpecs(consulted = []) {
|
|
|
27202
27452
|
if (!addSpec(candidate)) break;
|
|
27203
27453
|
}
|
|
27204
27454
|
for (const dir of ["spec", "docs"]) {
|
|
27205
|
-
if (!(0,
|
|
27455
|
+
if (!(0, import_node_fs41.existsSync)(dir)) continue;
|
|
27206
27456
|
try {
|
|
27207
27457
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
27208
27458
|
for (const mdFile of mdFiles) {
|
|
@@ -27217,9 +27467,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
27217
27467
|
if (depth >= maxDepth) return [];
|
|
27218
27468
|
const result = [];
|
|
27219
27469
|
try {
|
|
27220
|
-
const entries = (0,
|
|
27470
|
+
const entries = (0, import_node_fs41.readdirSync)(dir, { withFileTypes: true });
|
|
27221
27471
|
for (const entry of entries) {
|
|
27222
|
-
const fullPath = (0,
|
|
27472
|
+
const fullPath = (0, import_node_path31.join)(dir, entry.name);
|
|
27223
27473
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
27224
27474
|
result.push(fullPath);
|
|
27225
27475
|
} else if (entry.isDirectory() && depth < maxDepth - 1) {
|
|
@@ -27232,25 +27482,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
27232
27482
|
}
|
|
27233
27483
|
function discoverPlans() {
|
|
27234
27484
|
const home = process.env.HOME ?? "";
|
|
27235
|
-
const homePlansDir = (0,
|
|
27485
|
+
const homePlansDir = (0, import_node_path31.join)(home, ".claude", "plans");
|
|
27236
27486
|
const sources = [];
|
|
27237
27487
|
if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
|
|
27238
|
-
sources.push({ root: process.cwd(), prefix: (0,
|
|
27488
|
+
sources.push({ root: process.cwd(), prefix: (0, import_node_path31.join)(".claude", "plans") });
|
|
27239
27489
|
}
|
|
27240
|
-
if (home && (0,
|
|
27490
|
+
if (home && (0, import_node_fs41.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
|
|
27241
27491
|
const candidates2 = [];
|
|
27242
27492
|
const seen = /* @__PURE__ */ new Set();
|
|
27243
27493
|
for (const source2 of sources) {
|
|
27244
27494
|
let names2;
|
|
27245
27495
|
try {
|
|
27246
|
-
names2 = (0,
|
|
27496
|
+
names2 = (0, import_node_fs41.readdirSync)(source2.prefix ? (0, import_node_path31.join)(source2.root, source2.prefix) : source2.root);
|
|
27247
27497
|
} catch {
|
|
27248
27498
|
continue;
|
|
27249
27499
|
}
|
|
27250
27500
|
for (const f of names2) {
|
|
27251
27501
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
27252
27502
|
seen.add(f);
|
|
27253
|
-
const relPath = source2.prefix ? (0,
|
|
27503
|
+
const relPath = source2.prefix ? (0, import_node_path31.join)(source2.prefix, f) : f;
|
|
27254
27504
|
const stat3 = statRegularInRoot(source2.root, relPath);
|
|
27255
27505
|
if (!stat3.ok) continue;
|
|
27256
27506
|
candidates2.push({ name: f, root: source2.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
|
|
@@ -27268,9 +27518,9 @@ function discoverPlans() {
|
|
|
27268
27518
|
function isRealDirectoryChain(root, parts2) {
|
|
27269
27519
|
let current = root;
|
|
27270
27520
|
for (const part of parts2) {
|
|
27271
|
-
current = (0,
|
|
27521
|
+
current = (0, import_node_path31.join)(current, part);
|
|
27272
27522
|
try {
|
|
27273
|
-
if (!(0,
|
|
27523
|
+
if (!(0, import_node_fs41.lstatSync)(current).isDirectory()) return false;
|
|
27274
27524
|
} catch {
|
|
27275
27525
|
return false;
|
|
27276
27526
|
}
|
|
@@ -27285,7 +27535,7 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
27285
27535
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
27286
27536
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
27287
27537
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
27288
|
-
if (!(0,
|
|
27538
|
+
if (!(0, import_node_fs41.existsSync)(path)) continue;
|
|
27289
27539
|
const opened = openRegularInRoot(process.cwd(), path);
|
|
27290
27540
|
if (!opened.ok) continue;
|
|
27291
27541
|
if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
|
|
@@ -27471,8 +27721,8 @@ async function mode(run4) {
|
|
|
27471
27721
|
}
|
|
27472
27722
|
|
|
27473
27723
|
// src/lib/fold.ts
|
|
27474
|
-
var
|
|
27475
|
-
var
|
|
27724
|
+
var import_node_fs42 = require("node:fs");
|
|
27725
|
+
var import_node_path32 = require("node:path");
|
|
27476
27726
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
27477
27727
|
"user",
|
|
27478
27728
|
"assistant",
|
|
@@ -27609,7 +27859,7 @@ function candidateRoots(repoRoot2) {
|
|
|
27609
27859
|
const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
27610
27860
|
const out2 = [norm];
|
|
27611
27861
|
try {
|
|
27612
|
-
const real =
|
|
27862
|
+
const real = import_node_fs42.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
27613
27863
|
if (real !== norm) out2.push(real);
|
|
27614
27864
|
} catch {
|
|
27615
27865
|
}
|
|
@@ -27697,31 +27947,31 @@ function fold(transcriptPath, opts = {}) {
|
|
|
27697
27947
|
}
|
|
27698
27948
|
};
|
|
27699
27949
|
try {
|
|
27700
|
-
if (!(0,
|
|
27701
|
-
ingest((0,
|
|
27950
|
+
if (!(0, import_node_fs42.existsSync)(transcriptPath)) return result;
|
|
27951
|
+
ingest((0, import_node_fs42.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
27702
27952
|
result.coverage.complete = true;
|
|
27703
27953
|
} catch {
|
|
27704
27954
|
return result;
|
|
27705
27955
|
}
|
|
27706
27956
|
try {
|
|
27707
|
-
const sidecarDir = (0,
|
|
27708
|
-
(0,
|
|
27709
|
-
(0,
|
|
27957
|
+
const sidecarDir = (0, import_node_path32.join)(
|
|
27958
|
+
(0, import_node_path32.dirname)(transcriptPath),
|
|
27959
|
+
(0, import_node_path32.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
27710
27960
|
"subagents"
|
|
27711
27961
|
);
|
|
27712
|
-
if ((0,
|
|
27962
|
+
if ((0, import_node_fs42.existsSync)(sidecarDir)) {
|
|
27713
27963
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
27714
27964
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
27715
27965
|
const found = [];
|
|
27716
27966
|
const walk2 = (d, depth) => {
|
|
27717
27967
|
if (depth > 4) return;
|
|
27718
|
-
for (const e of (0,
|
|
27719
|
-
const p = (0,
|
|
27968
|
+
for (const e of (0, import_node_fs42.readdirSync)(d, { withFileTypes: true })) {
|
|
27969
|
+
const p = (0, import_node_path32.join)(d, e.name);
|
|
27720
27970
|
if (e.isDirectory()) {
|
|
27721
27971
|
walk2(p, depth + 1);
|
|
27722
27972
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
27723
27973
|
try {
|
|
27724
|
-
const st = (0,
|
|
27974
|
+
const st = (0, import_node_fs42.statSync)(p);
|
|
27725
27975
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
27726
27976
|
} catch {
|
|
27727
27977
|
result.coverage.malformed++;
|
|
@@ -27738,7 +27988,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
27738
27988
|
continue;
|
|
27739
27989
|
}
|
|
27740
27990
|
try {
|
|
27741
|
-
ingest((0,
|
|
27991
|
+
ingest((0, import_node_fs42.readFileSync)(f.path, "utf8"), "subagent");
|
|
27742
27992
|
bytes += f.size;
|
|
27743
27993
|
result.coverage.subagentFiles++;
|
|
27744
27994
|
} catch {
|
|
@@ -27773,7 +28023,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
27773
28023
|
}
|
|
27774
28024
|
function classifyUnobserved(path) {
|
|
27775
28025
|
try {
|
|
27776
|
-
const st = (0,
|
|
28026
|
+
const st = (0, import_node_fs42.statSync)(path);
|
|
27777
28027
|
if (!st.isFile()) return "unreadable";
|
|
27778
28028
|
} catch {
|
|
27779
28029
|
return "unreadable";
|
|
@@ -28088,20 +28338,20 @@ async function evidence(run4) {
|
|
|
28088
28338
|
}
|
|
28089
28339
|
|
|
28090
28340
|
// src/lib/cache-cleanup.ts
|
|
28091
|
-
var
|
|
28092
|
-
var
|
|
28341
|
+
var import_node_fs43 = require("node:fs");
|
|
28342
|
+
var import_node_path33 = require("node:path");
|
|
28093
28343
|
var CACHE_TTL_DAYS = 7;
|
|
28094
28344
|
function pruneStaleCache() {
|
|
28095
28345
|
try {
|
|
28096
28346
|
const dir = projectPath(CACHE_DIR);
|
|
28097
28347
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
28098
|
-
for (const entry of (0,
|
|
28348
|
+
for (const entry of (0, import_node_fs43.readdirSync)(dir)) {
|
|
28099
28349
|
if (!entry.startsWith("pending-")) continue;
|
|
28100
|
-
const path = (0,
|
|
28350
|
+
const path = (0, import_node_path33.join)(dir, entry);
|
|
28101
28351
|
try {
|
|
28102
|
-
const stat3 = (0,
|
|
28352
|
+
const stat3 = (0, import_node_fs43.statSync)(path);
|
|
28103
28353
|
if (stat3.mtimeMs < cutoff) {
|
|
28104
|
-
(0,
|
|
28354
|
+
(0, import_node_fs43.unlinkSync)(path);
|
|
28105
28355
|
logEvent("cache_entry_pruned", {
|
|
28106
28356
|
path: entry,
|
|
28107
28357
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -28115,7 +28365,7 @@ function pruneStaleCache() {
|
|
|
28115
28365
|
}
|
|
28116
28366
|
|
|
28117
28367
|
// src/lib/context-files.ts
|
|
28118
|
-
var
|
|
28368
|
+
var import_node_fs44 = require("node:fs");
|
|
28119
28369
|
var import_node_os7 = require("node:os");
|
|
28120
28370
|
var MAX_CONTEXT_FILES = 10;
|
|
28121
28371
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
@@ -28173,7 +28423,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
28173
28423
|
continue;
|
|
28174
28424
|
}
|
|
28175
28425
|
try {
|
|
28176
|
-
const content = (0,
|
|
28426
|
+
const content = (0, import_node_fs44.readFileSync)(safePath, "utf8");
|
|
28177
28427
|
const bytes = Buffer.byteLength(content);
|
|
28178
28428
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
28179
28429
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -28331,8 +28581,8 @@ function languageOf2(path) {
|
|
|
28331
28581
|
}
|
|
28332
28582
|
|
|
28333
28583
|
// src/lib/code/runtime.ts
|
|
28334
|
-
var
|
|
28335
|
-
var
|
|
28584
|
+
var import_node_fs45 = require("node:fs");
|
|
28585
|
+
var import_node_path34 = require("node:path");
|
|
28336
28586
|
var import_web_tree_sitter2 = __toESM2(require_web_tree_sitter2());
|
|
28337
28587
|
|
|
28338
28588
|
// src/lib/code/grammars.json
|
|
@@ -28392,18 +28642,18 @@ var grammars_default = {
|
|
|
28392
28642
|
var MAX_PARSE_BYTES = 512 * 1024;
|
|
28393
28643
|
function grammarCandidates(file, pkg, env = process.env) {
|
|
28394
28644
|
return [
|
|
28395
|
-
...env.VERITY_GRAMMAR_DIR ? [(0,
|
|
28396
|
-
(0,
|
|
28645
|
+
...env.VERITY_GRAMMAR_DIR ? [(0, import_node_path34.join)(env.VERITY_GRAMMAR_DIR, file)] : [],
|
|
28646
|
+
(0, import_node_path34.join)(__dirname, "..", "data", "grammars", file),
|
|
28397
28647
|
// bundled: cli/bin/ → cli/data/grammars/
|
|
28398
|
-
(0,
|
|
28648
|
+
(0, import_node_path34.join)(__dirname, "..", "..", "..", "data", "grammars", file),
|
|
28399
28649
|
// tsx: cli/src/lib/code/ → cli/data/grammars/
|
|
28400
|
-
(0,
|
|
28650
|
+
(0, import_node_path34.join)(__dirname, "..", "..", "..", "node_modules", pkg, file)
|
|
28401
28651
|
// tsx, before a build: the pinned devDependency
|
|
28402
28652
|
];
|
|
28403
28653
|
}
|
|
28404
28654
|
function locateGrammar(id, env = process.env) {
|
|
28405
28655
|
const g = grammars_default[id];
|
|
28406
|
-
return grammarCandidates(g.file, g.package, env).find((p) => (0,
|
|
28656
|
+
return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs45.existsSync)(p)) ?? null;
|
|
28407
28657
|
}
|
|
28408
28658
|
var loading = null;
|
|
28409
28659
|
function loadRuntime(env = process.env) {
|
|
@@ -29530,7 +29780,7 @@ var MAX_CALLERS = 30;
|
|
|
29530
29780
|
var MAX_READ_BYTES4 = 512 * 1024;
|
|
29531
29781
|
var IDENT = /^[A-Za-z_$][\w$]*$/;
|
|
29532
29782
|
var TEST_OR_TOOLING = /(^|\/)(tests?|__tests__|spec|specs|fixtures?|e2e|testdata|experiments|scripts)\/|\.(test|spec)\.[cm]?[jt]sx?$|_test\.(py|go)$|(^|\/)test_[^/]+\.py$/;
|
|
29533
|
-
var
|
|
29783
|
+
var dirname17 = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "";
|
|
29534
29784
|
function joinPath(dir, rel) {
|
|
29535
29785
|
const out2 = dir ? dir.split("/") : [];
|
|
29536
29786
|
for (const part of rel.split("/")) {
|
|
@@ -29655,7 +29905,7 @@ function parseJsonc(text) {
|
|
|
29655
29905
|
return JSON.parse(out2.replace(/,(\s*[}\]])/g, "$1"));
|
|
29656
29906
|
}
|
|
29657
29907
|
function tsconfigFor(source2, fromPath, cache) {
|
|
29658
|
-
for (let dir =
|
|
29908
|
+
for (let dir = dirname17(fromPath); ; dir = dirname17(dir)) {
|
|
29659
29909
|
const file = dir ? `${dir}/tsconfig.json` : "tsconfig.json";
|
|
29660
29910
|
if (!cache.has(file)) {
|
|
29661
29911
|
const read2 = source2.read(file, 256 * 1024);
|
|
@@ -29679,7 +29929,7 @@ function tsconfigFor(source2, fromPath, cache) {
|
|
|
29679
29929
|
function tsCandidates(spec, fromPath, cfg) {
|
|
29680
29930
|
const bases = [];
|
|
29681
29931
|
if (spec.startsWith(".")) {
|
|
29682
|
-
const b = joinPath(
|
|
29932
|
+
const b = joinPath(dirname17(fromPath), spec);
|
|
29683
29933
|
if (b !== null) bases.push(b);
|
|
29684
29934
|
} else if (cfg) {
|
|
29685
29935
|
const root = cfg.baseUrl !== null ? joinPath(cfg.dir, cfg.baseUrl) : cfg.dir;
|
|
@@ -29711,8 +29961,8 @@ function pyCandidates(spec, fromPath) {
|
|
|
29711
29961
|
const mod = spec.slice(dots).replace(/\./g, "/");
|
|
29712
29962
|
const out2 = [];
|
|
29713
29963
|
if (dots > 0) {
|
|
29714
|
-
let dir =
|
|
29715
|
-
for (let i2 = 1; i2 < dots; i2++) dir =
|
|
29964
|
+
let dir = dirname17(fromPath);
|
|
29965
|
+
for (let i2 = 1; i2 < dots; i2++) dir = dirname17(dir);
|
|
29716
29966
|
const b = mod ? joinPath(dir, mod) : dir;
|
|
29717
29967
|
if (b !== null) out2.push(`${b}.py`, `${b}/__init__.py`);
|
|
29718
29968
|
} else {
|
|
@@ -29739,7 +29989,7 @@ function moduleFiles(source2, spec, fromPath, lang, cache = /* @__PURE__ */ new
|
|
|
29739
29989
|
const module2 = mod.ok ? /^\s*module\s+(\S+)/m.exec(mod.content)?.[1] : void 0;
|
|
29740
29990
|
if (!module2 || !(spec === module2 || spec.startsWith(`${module2}/`))) return [];
|
|
29741
29991
|
const dir = spec.slice(module2.length + 1);
|
|
29742
|
-
return source2.list(dir || void 0).filter((p) =>
|
|
29992
|
+
return source2.list(dir || void 0).filter((p) => dirname17(p) === dir && p.endsWith(".go") && !p.endsWith("_test.go"));
|
|
29743
29993
|
}
|
|
29744
29994
|
if (lang === "java") {
|
|
29745
29995
|
const suffix = `${spec.replace(/\./g, "/")}.java`;
|
|
@@ -29790,7 +30040,7 @@ function definitionOf(input) {
|
|
|
29790
30040
|
if (type?.startsWith(RESULT_OF)) {
|
|
29791
30041
|
const [fnName, idx] = type.slice(RESULT_OF.length).split("#");
|
|
29792
30042
|
type = null;
|
|
29793
|
-
const others = lang === "go" ? source2.list(
|
|
30043
|
+
const others = lang === "go" ? source2.list(dirname17(path) || void 0).filter((p) => dirname17(p) === dirname17(path) && p.endsWith(".go") && p !== path) : (() => {
|
|
29794
30044
|
const imp = importOf(content, lang, fnName, null);
|
|
29795
30045
|
return imp ? moduleFiles(source2, imp.spec, path, lang, tsCache) : [];
|
|
29796
30046
|
})();
|
|
@@ -29837,7 +30087,7 @@ function definitionOf(input) {
|
|
|
29837
30087
|
}
|
|
29838
30088
|
}
|
|
29839
30089
|
if (out2.length === 0 && lang === "go" && !receiver) {
|
|
29840
|
-
for (const f of source2.list(
|
|
30090
|
+
for (const f of source2.list(dirname17(path) || void 0).filter((p) => dirname17(p) === dirname17(path) && p.endsWith(".go") && p !== path)) {
|
|
29841
30091
|
add(functionsNamed(outlineOf2(f), name2), "package");
|
|
29842
30092
|
if (Date.now() > input.deadlineAt) break;
|
|
29843
30093
|
}
|
|
@@ -30732,8 +30982,8 @@ async function repoContext(run4) {
|
|
|
30732
30982
|
|
|
30733
30983
|
// src/lib/seed-runner.ts
|
|
30734
30984
|
var import_promises15 = require("node:fs/promises");
|
|
30735
|
-
var
|
|
30736
|
-
var
|
|
30985
|
+
var import_node_fs46 = require("node:fs");
|
|
30986
|
+
var import_node_path35 = require("node:path");
|
|
30737
30987
|
var import_yaml4 = __toESM2(require_dist());
|
|
30738
30988
|
|
|
30739
30989
|
// src/lib/seed.ts
|
|
@@ -30956,8 +31206,8 @@ function normalizeTitle(title) {
|
|
|
30956
31206
|
async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
|
|
30957
31207
|
const titles = /* @__PURE__ */ new Set();
|
|
30958
31208
|
for (const dir of NODE_DIRS) {
|
|
30959
|
-
const full = (0,
|
|
30960
|
-
if (!(0,
|
|
31209
|
+
const full = (0, import_node_path35.join)(memoryDir3, dir);
|
|
31210
|
+
if (!(0, import_node_fs46.existsSync)(full)) continue;
|
|
30961
31211
|
let files;
|
|
30962
31212
|
try {
|
|
30963
31213
|
files = await (0, import_promises15.readdir)(full);
|
|
@@ -30968,7 +31218,7 @@ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
|
|
|
30968
31218
|
if (!file.endsWith(".md")) continue;
|
|
30969
31219
|
let content;
|
|
30970
31220
|
try {
|
|
30971
|
-
content = await (0, import_promises15.readFile)((0,
|
|
31221
|
+
content = await (0, import_promises15.readFile)((0, import_node_path35.join)(full, file), "utf-8");
|
|
30972
31222
|
} catch {
|
|
30973
31223
|
continue;
|
|
30974
31224
|
}
|
|
@@ -31039,7 +31289,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
31039
31289
|
return fm;
|
|
31040
31290
|
}
|
|
31041
31291
|
async function runSeed(opts) {
|
|
31042
|
-
if (!(0,
|
|
31292
|
+
if (!(0, import_node_fs46.existsSync)(STANDARD_FILE)) {
|
|
31043
31293
|
return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
31044
31294
|
}
|
|
31045
31295
|
let standardDoc;
|
|
@@ -31051,7 +31301,7 @@ async function runSeed(opts) {
|
|
|
31051
31301
|
}
|
|
31052
31302
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
31053
31303
|
let readmeContent;
|
|
31054
|
-
if ((0,
|
|
31304
|
+
if ((0, import_node_fs46.existsSync)("README.md")) {
|
|
31055
31305
|
try {
|
|
31056
31306
|
readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
|
|
31057
31307
|
} catch {
|
|
@@ -31059,7 +31309,7 @@ async function runSeed(opts) {
|
|
|
31059
31309
|
}
|
|
31060
31310
|
let claudeMdContent;
|
|
31061
31311
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
31062
|
-
if ((0,
|
|
31312
|
+
if ((0, import_node_fs46.existsSync)(p)) {
|
|
31063
31313
|
try {
|
|
31064
31314
|
claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
|
|
31065
31315
|
break;
|
|
@@ -31139,13 +31389,13 @@ async function runSeed(opts) {
|
|
|
31139
31389
|
continue;
|
|
31140
31390
|
}
|
|
31141
31391
|
const deduplicated = res.data.deduplicated === true;
|
|
31142
|
-
if (deduplicated && (0,
|
|
31392
|
+
if (deduplicated && (0, import_node_fs46.existsSync)(targetPath)) {
|
|
31143
31393
|
existing++;
|
|
31144
31394
|
continue;
|
|
31145
31395
|
}
|
|
31146
31396
|
const content = typeof res.data.content === "string" && res.data.content.length > 0 ? res.data.content : renderNodeMarkdown(c, nodeId, createdAt);
|
|
31147
31397
|
try {
|
|
31148
|
-
await (0, import_promises15.mkdir)((0,
|
|
31398
|
+
await (0, import_promises15.mkdir)((0, import_node_path35.dirname)(targetPath), { recursive: true });
|
|
31149
31399
|
await (0, import_promises15.writeFile)(targetPath, content);
|
|
31150
31400
|
if (deduplicated) existing++;
|
|
31151
31401
|
else {
|
|
@@ -31161,8 +31411,8 @@ async function runSeed(opts) {
|
|
|
31161
31411
|
}
|
|
31162
31412
|
|
|
31163
31413
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
31164
|
-
var
|
|
31165
|
-
var
|
|
31414
|
+
var import_node_fs47 = require("node:fs");
|
|
31415
|
+
var import_node_path36 = require("node:path");
|
|
31166
31416
|
async function memoryManifest(run4) {
|
|
31167
31417
|
const { globals } = run4;
|
|
31168
31418
|
const { serviceUrl, token } = run4;
|
|
@@ -31172,9 +31422,9 @@ async function memoryManifest(run4) {
|
|
|
31172
31422
|
let autoSeedNotice = null;
|
|
31173
31423
|
try {
|
|
31174
31424
|
await ensureMemoryDir();
|
|
31175
|
-
const seedMarker = (0,
|
|
31176
|
-
const hasStandard = (0,
|
|
31177
|
-
const alreadyTried = (0,
|
|
31425
|
+
const seedMarker = (0, import_node_path36.join)(VERITY_DIR, ".seeded");
|
|
31426
|
+
const hasStandard = (0, import_node_fs47.existsSync)(STANDARD_FILE);
|
|
31427
|
+
const alreadyTried = (0, import_node_fs47.existsSync)(seedMarker);
|
|
31178
31428
|
if (hasStandard && !alreadyTried) {
|
|
31179
31429
|
const preManifest = await buildManifest();
|
|
31180
31430
|
if (preManifest.nodes.length === 0) {
|
|
@@ -31187,7 +31437,7 @@ async function memoryManifest(run4) {
|
|
|
31187
31437
|
dryRun: false
|
|
31188
31438
|
});
|
|
31189
31439
|
if (seedResult.created > 0 || seedResult.existing > 0) {
|
|
31190
|
-
(0,
|
|
31440
|
+
(0, import_node_fs47.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
|
|
31191
31441
|
`);
|
|
31192
31442
|
if (seedResult.created > 0) {
|
|
31193
31443
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
@@ -31198,7 +31448,7 @@ async function memoryManifest(run4) {
|
|
|
31198
31448
|
failed: seedResult.failed
|
|
31199
31449
|
});
|
|
31200
31450
|
} else if (seedResult.skipped === "already_seeded") {
|
|
31201
|
-
(0,
|
|
31451
|
+
(0, import_node_fs47.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
31202
31452
|
`);
|
|
31203
31453
|
} else {
|
|
31204
31454
|
logEvent("auto_seed_noop", {
|
|
@@ -31293,7 +31543,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
|
|
|
31293
31543
|
}
|
|
31294
31544
|
|
|
31295
31545
|
// src/commands/analyze/phases/10-working-memory.ts
|
|
31296
|
-
var
|
|
31546
|
+
var import_node_path37 = require("node:path");
|
|
31297
31547
|
async function workingMemory(run4) {
|
|
31298
31548
|
const { opts } = run4;
|
|
31299
31549
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
|
|
@@ -31305,7 +31555,7 @@ async function workingMemory(run4) {
|
|
|
31305
31555
|
const priorState = foldForMarks(memorySession.d);
|
|
31306
31556
|
incrementReport = computeIncrement(
|
|
31307
31557
|
allForReview,
|
|
31308
|
-
(p) => fileHash((0,
|
|
31558
|
+
(p) => fileHash((0, import_node_path37.join)(repoRoot(), p)),
|
|
31309
31559
|
priorState.authored_all.map((a) => ({
|
|
31310
31560
|
path: a.path,
|
|
31311
31561
|
hash_at_last_verdict: a.hash_at_last_verdict
|
|
@@ -31387,7 +31637,7 @@ async function workingMemory(run4) {
|
|
|
31387
31637
|
}
|
|
31388
31638
|
|
|
31389
31639
|
// src/lib/note-budget.ts
|
|
31390
|
-
var
|
|
31640
|
+
var import_node_fs48 = require("node:fs");
|
|
31391
31641
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
31392
31642
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
31393
31643
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -31409,9 +31659,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
31409
31659
|
}
|
|
31410
31660
|
function readAdvisoryEpisode(sessionId) {
|
|
31411
31661
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
31412
|
-
if (!(0,
|
|
31662
|
+
if (!(0, import_node_fs48.existsSync)(file)) return null;
|
|
31413
31663
|
try {
|
|
31414
|
-
const o = JSON.parse((0,
|
|
31664
|
+
const o = JSON.parse((0, import_node_fs48.readFileSync)(file, "utf-8")) ?? {};
|
|
31415
31665
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
31416
31666
|
if (isNaN(delivered)) return null;
|
|
31417
31667
|
return {
|
|
@@ -31425,8 +31675,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
31425
31675
|
}
|
|
31426
31676
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
31427
31677
|
try {
|
|
31428
|
-
(0,
|
|
31429
|
-
(0,
|
|
31678
|
+
(0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
31679
|
+
(0, import_node_fs48.writeFileSync)(
|
|
31430
31680
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
31431
31681
|
JSON.stringify({ v: 1, ...episode })
|
|
31432
31682
|
);
|
|
@@ -31758,14 +32008,14 @@ async function buildRequest(run4) {
|
|
|
31758
32008
|
}
|
|
31759
32009
|
|
|
31760
32010
|
// src/lib/offline.ts
|
|
31761
|
-
var
|
|
32011
|
+
var import_node_fs49 = require("node:fs");
|
|
31762
32012
|
var import_node_crypto13 = require("node:crypto");
|
|
31763
32013
|
function cacheRequest(body2) {
|
|
31764
32014
|
try {
|
|
31765
|
-
(0,
|
|
32015
|
+
(0, import_node_fs49.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
31766
32016
|
const suffix = (0, import_node_crypto13.randomBytes)(4).toString("hex");
|
|
31767
32017
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
31768
|
-
(0,
|
|
32018
|
+
(0, import_node_fs49.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
|
|
31769
32019
|
} catch {
|
|
31770
32020
|
}
|
|
31771
32021
|
}
|
|
@@ -31884,8 +32134,8 @@ async function transmit(run4) {
|
|
|
31884
32134
|
}
|
|
31885
32135
|
|
|
31886
32136
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
31887
|
-
var
|
|
31888
|
-
var
|
|
32137
|
+
var import_node_fs50 = require("node:fs");
|
|
32138
|
+
var import_node_path38 = require("node:path");
|
|
31889
32139
|
async function reconcile(run4) {
|
|
31890
32140
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory: memory2, memorySession, response, reviewable, securityFiles, turnId } = run4;
|
|
31891
32141
|
const sentPaths = codeDelta.files.map((f) => f.path);
|
|
@@ -31914,7 +32164,7 @@ async function reconcile(run4) {
|
|
|
31914
32164
|
const st = foldDossier(memorySession.d);
|
|
31915
32165
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line2) => {
|
|
31916
32166
|
try {
|
|
31917
|
-
const src = (0,
|
|
32167
|
+
const src = (0, import_node_fs50.readFileSync)((0, import_node_path38.join)(repoRoot(), file), "utf8").split("\n");
|
|
31918
32168
|
const at = src[line2 - 1];
|
|
31919
32169
|
return at === void 0 ? null : lineSha(at);
|
|
31920
32170
|
} catch {
|
|
@@ -32736,7 +32986,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
32736
32986
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
32737
32987
|
async function runAnalyze(opts, globals) {
|
|
32738
32988
|
if (!verityConfigured()) {
|
|
32739
|
-
(0,
|
|
32989
|
+
(0, import_node_fs51.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
32740
32990
|
process.exit(0);
|
|
32741
32991
|
}
|
|
32742
32992
|
const run4 = createRun(opts, globals);
|
|
@@ -32757,11 +33007,11 @@ async function runAnalyze(opts, globals) {
|
|
|
32757
33007
|
}
|
|
32758
33008
|
|
|
32759
33009
|
// src/commands/baseline.ts
|
|
32760
|
-
var
|
|
33010
|
+
var import_node_fs53 = require("node:fs");
|
|
32761
33011
|
|
|
32762
33012
|
// src/lib/project-skills.ts
|
|
32763
|
-
var
|
|
32764
|
-
var
|
|
33013
|
+
var import_node_fs52 = require("node:fs");
|
|
33014
|
+
var import_node_path39 = require("node:path");
|
|
32765
33015
|
var PROJECT_SKILL_NAMES = [
|
|
32766
33016
|
"verity-setup",
|
|
32767
33017
|
"verity-analyze",
|
|
@@ -32787,14 +33037,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
32787
33037
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
32788
33038
|
function staleProjectSkills() {
|
|
32789
33039
|
const root = projectPath(".claude/skills");
|
|
32790
|
-
if (!(0,
|
|
32791
|
-
return ALL.filter((name2) => (0,
|
|
33040
|
+
if (!(0, import_node_fs52.existsSync)(root)) return [];
|
|
33041
|
+
return ALL.filter((name2) => (0, import_node_fs52.existsSync)((0, import_node_path39.join)(root, name2)));
|
|
32792
33042
|
}
|
|
32793
33043
|
function removeProjectSkills() {
|
|
32794
33044
|
const root = projectPath(".claude/skills");
|
|
32795
33045
|
const removed = [];
|
|
32796
33046
|
for (const name2 of staleProjectSkills()) {
|
|
32797
|
-
(0,
|
|
33047
|
+
(0, import_node_fs52.rmSync)((0, import_node_path39.join)(root, name2), { recursive: true, force: true });
|
|
32798
33048
|
removed.push(name2);
|
|
32799
33049
|
}
|
|
32800
33050
|
return removed;
|
|
@@ -32859,13 +33109,13 @@ function registerBaselineCommands(program2) {
|
|
|
32859
33109
|
let memoryMsg = null;
|
|
32860
33110
|
let memoryAgentLine = null;
|
|
32861
33111
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
32862
|
-
if (realStart && !(0,
|
|
33112
|
+
if (realStart && !(0, import_node_fs53.existsSync)(memoryNotice)) {
|
|
32863
33113
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
32864
33114
|
if (trackedGraph > 0) {
|
|
32865
33115
|
memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
|
|
32866
33116
|
memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
|
|
32867
33117
|
try {
|
|
32868
|
-
(0,
|
|
33118
|
+
(0, import_node_fs53.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
32869
33119
|
} catch {
|
|
32870
33120
|
}
|
|
32871
33121
|
}
|
|
@@ -32884,7 +33134,7 @@ function registerBaselineCommands(program2) {
|
|
|
32884
33134
|
if (needsSetup) {
|
|
32885
33135
|
userMsg = stale.length > 0 ? `Verity: the plugin is installed \u2014 run /verity:init to finish setting it up here (it will also clear ${stale.length} duplicate skills).` : "Verity: the plugin is installed \u2014 run /verity:init to finish setting it up here.";
|
|
32886
33136
|
notices.push(
|
|
32887
|
-
"The Verity plugin is installed here but /verity:init has not been run for this project. Installing the plugin cannot repair a project on its own \u2014 Claude Code has no post-install hook \u2014 so tell the user to run /verity:init (they type it; it is not a skill you can invoke). It asks how they want reviews to run, then does the repair."
|
|
33137
|
+
"The Verity plugin is installed here but /verity:init has not been run for this project. Installing the plugin cannot repair a project on its own \u2014 Claude Code has no post-install hook \u2014 so tell the user to run /verity:init (they type it; it is not a skill you can invoke). It asks how they want reviews to run, about telemetry and whether to sign in \u2014 all in the session \u2014 then does the repair and the sign-in."
|
|
32888
33138
|
);
|
|
32889
33139
|
if (stale.length > 0) {
|
|
32890
33140
|
notices.push(
|
|
@@ -32966,7 +33216,7 @@ function hookSource(value) {
|
|
|
32966
33216
|
}
|
|
32967
33217
|
|
|
32968
33218
|
// src/commands/review.ts
|
|
32969
|
-
var
|
|
33219
|
+
var import_node_fs54 = require("node:fs");
|
|
32970
33220
|
function registerReviewCommand(program2) {
|
|
32971
33221
|
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) => {
|
|
32972
33222
|
const globals = program2.opts();
|
|
@@ -32983,7 +33233,7 @@ async function runReview(opts, globals) {
|
|
|
32983
33233
|
const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
|
|
32984
33234
|
const analyzable = filterAnalyzable(allFiles);
|
|
32985
33235
|
const securityFiles = filterSecurity(allFiles);
|
|
32986
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
33236
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs54.existsSync)(f) || resolveFile(f) !== null);
|
|
32987
33237
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
32988
33238
|
const codeDelta = collectCodeDelta(allFiles);
|
|
32989
33239
|
const tokenResult = await resolveToken(globals.token);
|
|
@@ -33049,8 +33299,8 @@ async function runReview(opts, globals) {
|
|
|
33049
33299
|
}
|
|
33050
33300
|
|
|
33051
33301
|
// src/commands/guard.ts
|
|
33052
|
-
var
|
|
33053
|
-
var
|
|
33302
|
+
var import_node_fs58 = require("node:fs");
|
|
33303
|
+
var import_node_path44 = require("node:path");
|
|
33054
33304
|
|
|
33055
33305
|
// src/lib/terminal-text.ts
|
|
33056
33306
|
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
|
|
@@ -33158,7 +33408,7 @@ async function runAgentReview(options) {
|
|
|
33158
33408
|
}
|
|
33159
33409
|
|
|
33160
33410
|
// src/lib/prove/auto.ts
|
|
33161
|
-
var
|
|
33411
|
+
var import_node_path43 = require("node:path");
|
|
33162
33412
|
var import_node_crypto18 = require("node:crypto");
|
|
33163
33413
|
|
|
33164
33414
|
// src/lib/prove/signals.ts
|
|
@@ -34824,18 +35074,18 @@ function renderReplay(model, property, r) {
|
|
|
34824
35074
|
// src/lib/prove/runner.ts
|
|
34825
35075
|
var import_node_child_process15 = require("node:child_process");
|
|
34826
35076
|
var import_node_os8 = require("node:os");
|
|
34827
|
-
var
|
|
35077
|
+
var import_node_fs57 = require("node:fs");
|
|
34828
35078
|
var import_node_os9 = require("node:os");
|
|
34829
|
-
var
|
|
35079
|
+
var import_node_path42 = require("node:path");
|
|
34830
35080
|
|
|
34831
35081
|
// src/lib/prove/scaffold.ts
|
|
34832
|
-
var
|
|
34833
|
-
var
|
|
35082
|
+
var import_node_fs56 = require("node:fs");
|
|
35083
|
+
var import_node_path41 = require("node:path");
|
|
34834
35084
|
|
|
34835
35085
|
// src/lib/prove/safe-write.ts
|
|
34836
|
-
var
|
|
35086
|
+
var import_node_fs55 = require("node:fs");
|
|
34837
35087
|
var import_node_crypto14 = require("node:crypto");
|
|
34838
|
-
var
|
|
35088
|
+
var import_node_path40 = require("node:path");
|
|
34839
35089
|
var SafeWriteError = class extends Error {
|
|
34840
35090
|
constructor(reason, path) {
|
|
34841
35091
|
super(`refusing to write ${path}: ${reason}`);
|
|
@@ -34844,10 +35094,10 @@ var SafeWriteError = class extends Error {
|
|
|
34844
35094
|
this.name = "SafeWriteError";
|
|
34845
35095
|
}
|
|
34846
35096
|
};
|
|
34847
|
-
var FLAGS3 =
|
|
35097
|
+
var FLAGS3 = import_node_fs55.constants;
|
|
34848
35098
|
var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
|
|
34849
35099
|
function assertPlainRelative(rel) {
|
|
34850
|
-
if (!rel || (0,
|
|
35100
|
+
if (!rel || (0, import_node_path40.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
|
|
34851
35101
|
for (const part of rel.split(/[\\/]/)) {
|
|
34852
35102
|
if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
|
|
34853
35103
|
}
|
|
@@ -34856,34 +35106,34 @@ function ensureDirsNoFollow(root, rel) {
|
|
|
34856
35106
|
const parts2 = rel.split(/[\\/]/);
|
|
34857
35107
|
let cur = root;
|
|
34858
35108
|
for (const part of parts2.slice(0, -1)) {
|
|
34859
|
-
cur = (0,
|
|
35109
|
+
cur = (0, import_node_path40.join)(cur, part);
|
|
34860
35110
|
let st;
|
|
34861
35111
|
try {
|
|
34862
|
-
st = (0,
|
|
35112
|
+
st = (0, import_node_fs55.lstatSync)(cur);
|
|
34863
35113
|
} catch {
|
|
34864
|
-
(0,
|
|
35114
|
+
(0, import_node_fs55.mkdirSync)(cur);
|
|
34865
35115
|
continue;
|
|
34866
35116
|
}
|
|
34867
35117
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
|
|
34868
35118
|
if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
|
|
34869
35119
|
}
|
|
34870
|
-
return (0,
|
|
35120
|
+
return (0, import_node_path40.join)(root, rel);
|
|
34871
35121
|
}
|
|
34872
35122
|
function insideRoot(realRoot, realPath) {
|
|
34873
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
35123
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path40.sep) ? realRoot : realRoot + import_node_path40.sep);
|
|
34874
35124
|
}
|
|
34875
35125
|
function removeQuietly(path) {
|
|
34876
35126
|
try {
|
|
34877
|
-
(0,
|
|
35127
|
+
(0, import_node_fs55.unlinkSync)(path);
|
|
34878
35128
|
} catch {
|
|
34879
35129
|
}
|
|
34880
35130
|
}
|
|
34881
35131
|
function writeFileInRootNoFollow(root, rel, content) {
|
|
34882
35132
|
assertPlainRelative(rel);
|
|
34883
35133
|
const dest = ensureDirsNoFollow(root, rel);
|
|
34884
|
-
const dir = (0,
|
|
35134
|
+
const dir = (0, import_node_path40.dirname)(dest);
|
|
34885
35135
|
try {
|
|
34886
|
-
const st = (0,
|
|
35136
|
+
const st = (0, import_node_fs55.lstatSync)(dest);
|
|
34887
35137
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
|
|
34888
35138
|
if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
|
|
34889
35139
|
} catch (err2) {
|
|
@@ -34891,41 +35141,41 @@ function writeFileInRootNoFollow(root, rel, content) {
|
|
|
34891
35141
|
}
|
|
34892
35142
|
let realRoot;
|
|
34893
35143
|
try {
|
|
34894
|
-
realRoot = (0,
|
|
35144
|
+
realRoot = (0, import_node_fs55.realpathSync)(root);
|
|
34895
35145
|
} catch {
|
|
34896
35146
|
throw new SafeWriteError("unwritable", root);
|
|
34897
35147
|
}
|
|
34898
|
-
const tmp = (0,
|
|
35148
|
+
const tmp = (0, import_node_path40.join)(dir, `.${(0, import_node_path40.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
|
|
34899
35149
|
let fd;
|
|
34900
35150
|
try {
|
|
34901
|
-
fd = (0,
|
|
35151
|
+
fd = (0, import_node_fs55.openSync)(tmp, import_node_fs55.constants.O_WRONLY | import_node_fs55.constants.O_CREAT | import_node_fs55.constants.O_EXCL | NOFOLLOW2, 420);
|
|
34902
35152
|
} catch {
|
|
34903
35153
|
throw new SafeWriteError("unwritable", tmp);
|
|
34904
35154
|
}
|
|
34905
35155
|
try {
|
|
34906
|
-
const opened = (0,
|
|
35156
|
+
const opened = (0, import_node_fs55.fstatSync)(fd, { bigint: true });
|
|
34907
35157
|
let realTmp;
|
|
34908
35158
|
try {
|
|
34909
|
-
realTmp = (0,
|
|
35159
|
+
realTmp = (0, import_node_fs55.realpathSync)(tmp);
|
|
34910
35160
|
} catch {
|
|
34911
35161
|
throw new SafeWriteError("escaped", tmp);
|
|
34912
35162
|
}
|
|
34913
|
-
const there = (0,
|
|
35163
|
+
const there = (0, import_node_fs55.lstatSync)(realTmp, { bigint: true });
|
|
34914
35164
|
if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
|
|
34915
35165
|
throw new SafeWriteError("escaped", tmp);
|
|
34916
35166
|
}
|
|
34917
35167
|
const buf = Buffer.from(content, "utf-8");
|
|
34918
35168
|
let off = 0;
|
|
34919
|
-
while (off < buf.length) off += (0,
|
|
35169
|
+
while (off < buf.length) off += (0, import_node_fs55.writeSync)(fd, buf, off, buf.length - off);
|
|
34920
35170
|
} catch (err2) {
|
|
34921
|
-
(0,
|
|
35171
|
+
(0, import_node_fs55.closeSync)(fd);
|
|
34922
35172
|
removeQuietly(tmp);
|
|
34923
35173
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
|
|
34924
35174
|
}
|
|
34925
|
-
(0,
|
|
35175
|
+
(0, import_node_fs55.closeSync)(fd);
|
|
34926
35176
|
try {
|
|
34927
|
-
if (!insideRoot(realRoot, (0,
|
|
34928
|
-
(0,
|
|
35177
|
+
if (!insideRoot(realRoot, (0, import_node_fs55.realpathSync)(dir)) || (0, import_node_fs55.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
|
|
35178
|
+
(0, import_node_fs55.renameSync)(tmp, dest);
|
|
34929
35179
|
} catch (err2) {
|
|
34930
35180
|
removeQuietly(tmp);
|
|
34931
35181
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
|
|
@@ -34939,9 +35189,9 @@ function pathHasNoLink(root, rel) {
|
|
|
34939
35189
|
}
|
|
34940
35190
|
let cur = root;
|
|
34941
35191
|
for (const part of rel.split(/[\\/]/)) {
|
|
34942
|
-
cur = cur +
|
|
35192
|
+
cur = cur + import_node_path40.sep + part;
|
|
34943
35193
|
try {
|
|
34944
|
-
if ((0,
|
|
35194
|
+
if ((0, import_node_fs55.lstatSync)(cur).isSymbolicLink()) return false;
|
|
34945
35195
|
} catch {
|
|
34946
35196
|
return true;
|
|
34947
35197
|
}
|
|
@@ -35251,20 +35501,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
|
|
|
35251
35501
|
never committed; what reaches the team is the bug report and the fix.
|
|
35252
35502
|
`;
|
|
35253
35503
|
function scaffoldProofs(root) {
|
|
35254
|
-
const proofsDir = (0,
|
|
35504
|
+
const proofsDir = (0, import_node_path41.join)(root, PROOFS_DIR);
|
|
35255
35505
|
const written = [];
|
|
35256
35506
|
const kept = [];
|
|
35257
35507
|
for (const stray of ["lakefile.lean"]) {
|
|
35258
35508
|
const rel = `${PROOFS_DIR}/${stray}`;
|
|
35259
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35509
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path41.join)(root, rel));
|
|
35260
35510
|
try {
|
|
35261
|
-
(0,
|
|
35511
|
+
(0, import_node_fs56.rmSync)((0, import_node_path41.join)(root, rel), { force: true });
|
|
35262
35512
|
} catch {
|
|
35263
35513
|
}
|
|
35264
35514
|
}
|
|
35265
35515
|
for (const f of PROOFS_TEMPLATE_FILES) {
|
|
35266
35516
|
const rel = `${PROOFS_DIR}/${f.path}`;
|
|
35267
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35517
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path41.join)(root, rel));
|
|
35268
35518
|
const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
|
|
35269
35519
|
if (current.ok && current.content === f.content) {
|
|
35270
35520
|
kept.push(rel);
|
|
@@ -35277,8 +35527,8 @@ function scaffoldProofs(root) {
|
|
|
35277
35527
|
[`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
|
|
35278
35528
|
[`${MODELS_DIR}/README.md`, MODELS_README]
|
|
35279
35529
|
]) {
|
|
35280
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35281
|
-
if (existsNoFollow((0,
|
|
35530
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path41.join)(root, rel));
|
|
35531
|
+
if (existsNoFollow((0, import_node_path41.join)(root, rel))) {
|
|
35282
35532
|
kept.push(rel);
|
|
35283
35533
|
continue;
|
|
35284
35534
|
}
|
|
@@ -35289,7 +35539,7 @@ function scaffoldProofs(root) {
|
|
|
35289
35539
|
}
|
|
35290
35540
|
function existsNoFollow(abs) {
|
|
35291
35541
|
try {
|
|
35292
|
-
(0,
|
|
35542
|
+
(0, import_node_fs56.lstatSync)(abs);
|
|
35293
35543
|
return true;
|
|
35294
35544
|
} catch {
|
|
35295
35545
|
return false;
|
|
@@ -35547,16 +35797,16 @@ function renderReport(r) {
|
|
|
35547
35797
|
|
|
35548
35798
|
// src/lib/prove/runner.ts
|
|
35549
35799
|
function verityLeanHome(env = process.env) {
|
|
35550
|
-
return env.VERITY_LEAN_HOME ?? (0,
|
|
35800
|
+
return env.VERITY_LEAN_HOME ?? (0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
|
|
35551
35801
|
}
|
|
35552
35802
|
function findToolchain(env = process.env) {
|
|
35553
|
-
const managedBin = (0,
|
|
35554
|
-
const elanBin = (0,
|
|
35555
|
-
const path = [managedBin, elanBin, env.PATH ?? ""].filter(Boolean).join(
|
|
35803
|
+
const managedBin = (0, import_node_path42.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
|
|
35804
|
+
const elanBin = (0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
|
|
35805
|
+
const path = [managedBin, elanBin, env.PATH ?? ""].filter(Boolean).join(import_node_path42.delimiter);
|
|
35556
35806
|
const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
|
|
35557
|
-
const elanHas = (0,
|
|
35807
|
+
const elanHas = (0, import_node_fs57.existsSync)((0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
|
|
35558
35808
|
const exe = process.platform === "win32" ? "lake.exe" : "lake";
|
|
35559
|
-
const candidates2 = [(0,
|
|
35809
|
+
const candidates2 = [(0, import_node_path42.join)(managedBin, exe), ...elanHas ? [(0, import_node_path42.join)(elanBin, exe)] : [], exe];
|
|
35560
35810
|
for (const candidate of candidates2) {
|
|
35561
35811
|
try {
|
|
35562
35812
|
(0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
|
|
@@ -35632,41 +35882,41 @@ function runAsync(tc, cwd, args2, timeoutMs) {
|
|
|
35632
35882
|
var DEFAULT_BUILD_TIMEOUT_MS = 10 * 6e4;
|
|
35633
35883
|
var DEFAULT_CHECK_TIMEOUT_MS = 12e4;
|
|
35634
35884
|
function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
35635
|
-
return run2(tc, (0,
|
|
35885
|
+
return run2(tc, (0, import_node_path42.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
35636
35886
|
}
|
|
35637
35887
|
function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
35638
|
-
return runAsync(tc, (0,
|
|
35888
|
+
return runAsync(tc, (0, import_node_path42.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
35639
35889
|
}
|
|
35640
35890
|
function isModelInRoot(modelsAbs, rel) {
|
|
35641
|
-
if (!rel.endsWith(".lean") || (0,
|
|
35891
|
+
if (!rel.endsWith(".lean") || (0, import_node_path42.isAbsolute)(rel) || rel.startsWith("..")) return false;
|
|
35642
35892
|
return statRegularInRoot(modelsAbs, rel).ok;
|
|
35643
35893
|
}
|
|
35644
35894
|
function resolveModelFile(root, arg) {
|
|
35645
|
-
const modelsAbs = (0,
|
|
35646
|
-
const asPath = (0,
|
|
35895
|
+
const modelsAbs = (0, import_node_path42.join)(root, MODELS_DIR);
|
|
35896
|
+
const asPath = (0, import_node_path42.relative)(modelsAbs, (0, import_node_path42.isAbsolute)(arg) ? arg : (0, import_node_path42.resolve)(root, arg));
|
|
35647
35897
|
const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
|
|
35648
35898
|
for (const rel of candidates2) {
|
|
35649
|
-
if (isModelInRoot(modelsAbs, rel)) return (0,
|
|
35899
|
+
if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path42.join)(modelsAbs, rel);
|
|
35650
35900
|
}
|
|
35651
35901
|
return null;
|
|
35652
35902
|
}
|
|
35653
35903
|
function listModelFiles(root) {
|
|
35654
|
-
const modelsAbs = (0,
|
|
35655
|
-
if (!(0,
|
|
35656
|
-
return (0,
|
|
35904
|
+
const modelsAbs = (0, import_node_path42.join)(root, MODELS_DIR);
|
|
35905
|
+
if (!(0, import_node_fs57.existsSync)(modelsAbs)) return [];
|
|
35906
|
+
return (0, import_node_fs57.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path42.join)(modelsAbs, f));
|
|
35657
35907
|
}
|
|
35658
35908
|
function trimDiagnostics(text) {
|
|
35659
35909
|
return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
|
|
35660
35910
|
}
|
|
35661
35911
|
function checkModel(tc, root, modelFile, opts = {}) {
|
|
35662
|
-
const proofsAbs = (0,
|
|
35663
|
-
const rel = (0,
|
|
35912
|
+
const proofsAbs = (0, import_node_path42.join)(root, PROOFS_DIR);
|
|
35913
|
+
const rel = (0, import_node_path42.relative)(proofsAbs, modelFile);
|
|
35664
35914
|
const res = run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35665
35915
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35666
35916
|
}
|
|
35667
35917
|
async function checkModelAsync(tc, root, modelFile, opts = {}) {
|
|
35668
|
-
const proofsAbs = (0,
|
|
35669
|
-
const rel = (0,
|
|
35918
|
+
const proofsAbs = (0, import_node_path42.join)(root, PROOFS_DIR);
|
|
35919
|
+
const rel = (0, import_node_path42.relative)(proofsAbs, modelFile);
|
|
35670
35920
|
const res = await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35671
35921
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
35672
35922
|
}
|
|
@@ -35674,10 +35924,10 @@ function toReport(res, root, modelFile, timeoutMs) {
|
|
|
35674
35924
|
const parsed = parseVerityLines(res.stdout);
|
|
35675
35925
|
const combined = `${res.stdout}
|
|
35676
35926
|
${res.stderr}`;
|
|
35677
|
-
const name2 = parsed.header?.model ?? (0,
|
|
35927
|
+
const name2 = parsed.header?.model ?? (0, import_node_path42.basename)(modelFile, ".lean");
|
|
35678
35928
|
const report = {
|
|
35679
35929
|
model: name2,
|
|
35680
|
-
file: (0,
|
|
35930
|
+
file: (0, import_node_path42.relative)(root, modelFile),
|
|
35681
35931
|
ok: res.ok,
|
|
35682
35932
|
header: parsed.header,
|
|
35683
35933
|
properties: parsed.properties,
|
|
@@ -36207,7 +36457,7 @@ async function runFormalPhase(input) {
|
|
|
36207
36457
|
modelName = gen.name;
|
|
36208
36458
|
const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
|
|
36209
36459
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
36210
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
36460
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path43.join)(root, rel);
|
|
36211
36461
|
progress.model = { name: gen.name, file: rel, rounds: round };
|
|
36212
36462
|
progress.step = "check";
|
|
36213
36463
|
report = await deps.check(root, abs);
|
|
@@ -36307,7 +36557,7 @@ async function runFormalPhase(input) {
|
|
|
36307
36557
|
return done({
|
|
36308
36558
|
status: "checked",
|
|
36309
36559
|
target,
|
|
36310
|
-
model: { name: modelName, file: (0,
|
|
36560
|
+
model: { name: modelName, file: (0, import_node_path43.relative)(root, (0, import_node_path43.join)(root, modelFile)), rounds },
|
|
36311
36561
|
properties: report.properties,
|
|
36312
36562
|
findings
|
|
36313
36563
|
});
|
|
@@ -36370,7 +36620,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
36370
36620
|
}
|
|
36371
36621
|
const rel = `${dir}/${gen.name}.lean`;
|
|
36372
36622
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
36373
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
36623
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path43.join)(root, rel);
|
|
36374
36624
|
const report = await opts.deps.check(root, abs);
|
|
36375
36625
|
const abstracts = report.header?.abstracts ?? [];
|
|
36376
36626
|
const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
|
|
@@ -36480,7 +36730,7 @@ var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
|
36480
36730
|
var WRITERS_BUDGET_MS = 1500;
|
|
36481
36731
|
var EXCERPT_MAX_LINES2 = 30;
|
|
36482
36732
|
var GUARD_BLOCK_CAP = 2;
|
|
36483
|
-
var GUARD_ITER_FILE = (0,
|
|
36733
|
+
var GUARD_ITER_FILE = (0, import_node_path44.join)(VERITY_DIR, ".guard-iteration");
|
|
36484
36734
|
function readPreToolUseStdin() {
|
|
36485
36735
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
36486
36736
|
return new Promise((resolve8) => {
|
|
@@ -36525,7 +36775,7 @@ function readPreToolUseStdin() {
|
|
|
36525
36775
|
}
|
|
36526
36776
|
function readIterMap() {
|
|
36527
36777
|
try {
|
|
36528
|
-
const raw = JSON.parse((0,
|
|
36778
|
+
const raw = JSON.parse((0, import_node_fs58.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
36529
36779
|
if (raw && typeof raw === "object") {
|
|
36530
36780
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
36531
36781
|
return { [raw.moment]: raw.count };
|
|
@@ -36545,10 +36795,10 @@ function readIter(moment) {
|
|
|
36545
36795
|
}
|
|
36546
36796
|
function writeIter(moment, count) {
|
|
36547
36797
|
try {
|
|
36548
|
-
(0,
|
|
36798
|
+
(0, import_node_fs58.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
36549
36799
|
const map = readIterMap();
|
|
36550
36800
|
map[moment] = count;
|
|
36551
|
-
(0,
|
|
36801
|
+
(0, import_node_fs58.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
36552
36802
|
} catch {
|
|
36553
36803
|
}
|
|
36554
36804
|
}
|
|
@@ -36558,10 +36808,10 @@ function resetIter(moment) {
|
|
|
36558
36808
|
if (!(moment in map)) return;
|
|
36559
36809
|
delete map[moment];
|
|
36560
36810
|
if (Object.keys(map).length === 0) {
|
|
36561
|
-
if ((0,
|
|
36811
|
+
if ((0, import_node_fs58.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs58.unlinkSync)(GUARD_ITER_FILE);
|
|
36562
36812
|
} else {
|
|
36563
|
-
(0,
|
|
36564
|
-
(0,
|
|
36813
|
+
(0, import_node_fs58.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
36814
|
+
(0, import_node_fs58.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
36565
36815
|
}
|
|
36566
36816
|
} catch {
|
|
36567
36817
|
}
|
|
@@ -36631,7 +36881,7 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
36631
36881
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
36632
36882
|
const analyzable = filterAnalyzable(files);
|
|
36633
36883
|
const securityFiles = filterSecurity(files);
|
|
36634
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
36884
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs58.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
36635
36885
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
36636
36886
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
36637
36887
|
const requestBody = {
|
|
@@ -37239,7 +37489,7 @@ function registerIgnoreCommand(program2) {
|
|
|
37239
37489
|
|
|
37240
37490
|
// src/commands/waive.ts
|
|
37241
37491
|
var import_node_crypto19 = require("node:crypto");
|
|
37242
|
-
var
|
|
37492
|
+
var import_node_fs59 = require("node:fs");
|
|
37243
37493
|
function registerWaiveCommand(program2) {
|
|
37244
37494
|
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) => {
|
|
37245
37495
|
const globals = program2.opts();
|
|
@@ -37268,7 +37518,7 @@ function registerWaiveCommand(program2) {
|
|
|
37268
37518
|
if (opts.file) {
|
|
37269
37519
|
body2.file = opts.file;
|
|
37270
37520
|
try {
|
|
37271
|
-
body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0,
|
|
37521
|
+
body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs59.readFileSync)(opts.file)).digest("hex");
|
|
37272
37522
|
} catch {
|
|
37273
37523
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
37274
37524
|
process.exit(1);
|
|
@@ -37293,10 +37543,10 @@ function registerWaiveCommand(program2) {
|
|
|
37293
37543
|
}
|
|
37294
37544
|
|
|
37295
37545
|
// src/commands/init.ts
|
|
37296
|
-
var
|
|
37546
|
+
var import_node_fs64 = require("node:fs");
|
|
37297
37547
|
var import_promises20 = require("node:fs/promises");
|
|
37298
37548
|
var import_yaml6 = __toESM2(require_dist());
|
|
37299
|
-
var
|
|
37549
|
+
var import_node_path48 = require("node:path");
|
|
37300
37550
|
var import_node_child_process19 = require("node:child_process");
|
|
37301
37551
|
|
|
37302
37552
|
// src/lib/banner.ts
|
|
@@ -37375,7 +37625,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
37375
37625
|
}
|
|
37376
37626
|
|
|
37377
37627
|
// src/commands/doctor.ts
|
|
37378
|
-
var
|
|
37628
|
+
var import_node_fs60 = require("node:fs");
|
|
37379
37629
|
|
|
37380
37630
|
// src/lib/prereqs.ts
|
|
37381
37631
|
var import_node_child_process16 = require("node:child_process");
|
|
@@ -37583,11 +37833,11 @@ async function buildReport() {
|
|
|
37583
37833
|
const hooks = wiring.status;
|
|
37584
37834
|
const provenance = cliProvenance();
|
|
37585
37835
|
const telemetry = await checkTelemetry();
|
|
37586
|
-
const hasConfig = (0,
|
|
37836
|
+
const hasConfig = (0, import_node_fs60.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
37587
37837
|
const artifacts = {
|
|
37588
|
-
standard: (0,
|
|
37838
|
+
standard: (0, import_node_fs60.existsSync)(projectPath(STANDARD_FILE)),
|
|
37589
37839
|
analysisConfig: hasConfig,
|
|
37590
|
-
verityMd: (0,
|
|
37840
|
+
verityMd: (0, import_node_fs60.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
37591
37841
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
37592
37842
|
};
|
|
37593
37843
|
const next = [];
|
|
@@ -37634,8 +37884,18 @@ async function buildReport() {
|
|
|
37634
37884
|
if (state?.telemetry === "deferred") {
|
|
37635
37885
|
next.push('Telemetry was requested but needs a token \u2014 run "verity login", then "verity telemetry install".');
|
|
37636
37886
|
}
|
|
37637
|
-
const memory2 = {
|
|
37638
|
-
|
|
37887
|
+
const memory2 = {
|
|
37888
|
+
posture: memoryPosture(),
|
|
37889
|
+
trackedFiles: committedMemoryFiles().length,
|
|
37890
|
+
optedOut: memoryOptOut()
|
|
37891
|
+
};
|
|
37892
|
+
const trackedState = { files: committedVerityState().length };
|
|
37893
|
+
if (trackedState.files > 0) {
|
|
37894
|
+
next.push(
|
|
37895
|
+
`${trackedState.files} machine-local Verity state file(s) under .verity/ are tracked in git (they can include copies of flagged secrets). Run "verity init --untrack-state" to untrack them (the files stay on disk).`
|
|
37896
|
+
);
|
|
37897
|
+
}
|
|
37898
|
+
if (memory2.trackedFiles > 0 && !memory2.optedOut) {
|
|
37639
37899
|
next.push(
|
|
37640
37900
|
`${memory2.trackedFiles} knowledge-graph file(s) under .verity/memory/ are tracked in git, so Verity's generated notes appear in every diff and pull request. Run "verity memory untrack" to stop that (the files stay on disk), or "verity memory track" if this project commits them on purpose.`
|
|
37641
37901
|
);
|
|
@@ -37674,6 +37934,7 @@ async function buildReport() {
|
|
|
37674
37934
|
telemetry: { enabled: telemetry.enabled, endpoint: telemetry.endpoint },
|
|
37675
37935
|
artifacts,
|
|
37676
37936
|
memory: memory2,
|
|
37937
|
+
trackedState,
|
|
37677
37938
|
next
|
|
37678
37939
|
};
|
|
37679
37940
|
}
|
|
@@ -37733,8 +37994,8 @@ function registerDoctorCommand(program2) {
|
|
|
37733
37994
|
}
|
|
37734
37995
|
|
|
37735
37996
|
// src/commands/migrate.ts
|
|
37736
|
-
var
|
|
37737
|
-
var
|
|
37997
|
+
var import_node_fs61 = require("node:fs");
|
|
37998
|
+
var import_node_path45 = require("node:path");
|
|
37738
37999
|
var import_node_child_process17 = require("node:child_process");
|
|
37739
38000
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
37740
38001
|
function defaultNpmRemover(pkg) {
|
|
@@ -37771,12 +38032,12 @@ async function runMigration(opts = {}) {
|
|
|
37771
38032
|
return { actions, migrated: actions.length > 0 };
|
|
37772
38033
|
}
|
|
37773
38034
|
function migrateProjectDir(root, actions) {
|
|
37774
|
-
const gateDir = (0,
|
|
37775
|
-
const verityDir = (0,
|
|
37776
|
-
if ((0,
|
|
38035
|
+
const gateDir = (0, import_node_path45.join)(root, ".gate");
|
|
38036
|
+
const verityDir = (0, import_node_path45.join)(root, ".verity");
|
|
38037
|
+
if ((0, import_node_fs61.existsSync)(gateDir) && !(0, import_node_fs61.existsSync)(verityDir)) {
|
|
37777
38038
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
37778
38039
|
}
|
|
37779
|
-
if ((0,
|
|
38040
|
+
if ((0, import_node_fs61.existsSync)(gateDir) && (0, import_node_fs61.existsSync)(verityDir)) {
|
|
37780
38041
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
37781
38042
|
}
|
|
37782
38043
|
return false;
|
|
@@ -37797,13 +38058,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
37797
38058
|
}
|
|
37798
38059
|
}
|
|
37799
38060
|
if (moved) {
|
|
37800
|
-
if ((0,
|
|
38061
|
+
if ((0, import_node_fs61.existsSync)(gateDir)) {
|
|
37801
38062
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
37802
38063
|
if (carried > 0) {
|
|
37803
38064
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
37804
38065
|
}
|
|
37805
38066
|
try {
|
|
37806
|
-
(0,
|
|
38067
|
+
(0, import_node_fs61.rmSync)(gateDir, { recursive: true, force: true });
|
|
37807
38068
|
} catch {
|
|
37808
38069
|
}
|
|
37809
38070
|
}
|
|
@@ -37819,18 +38080,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
37819
38080
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
37820
38081
|
}
|
|
37821
38082
|
try {
|
|
37822
|
-
(0,
|
|
38083
|
+
(0, import_node_fs61.rmSync)(gateDir, { recursive: true, force: true });
|
|
37823
38084
|
} catch {
|
|
37824
38085
|
}
|
|
37825
38086
|
return carried > 0;
|
|
37826
38087
|
}
|
|
37827
38088
|
function migrateGlobalCredentials(home, actions) {
|
|
37828
38089
|
if (!home) return;
|
|
37829
|
-
const gateCreds = (0,
|
|
37830
|
-
const verityCreds = (0,
|
|
37831
|
-
if (!(0,
|
|
37832
|
-
if (!(0,
|
|
37833
|
-
(0,
|
|
38090
|
+
const gateCreds = (0, import_node_path45.join)(home, ".gate", "credentials");
|
|
38091
|
+
const verityCreds = (0, import_node_path45.join)(home, ".verity", "credentials");
|
|
38092
|
+
if (!(0, import_node_fs61.existsSync)(gateCreds)) return;
|
|
38093
|
+
if (!(0, import_node_fs61.existsSync)(verityCreds)) {
|
|
38094
|
+
(0, import_node_fs61.mkdirSync)((0, import_node_path45.join)(home, ".verity"), { recursive: true });
|
|
37834
38095
|
moveFile(gateCreds, verityCreds);
|
|
37835
38096
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
37836
38097
|
return;
|
|
@@ -37852,8 +38113,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
37852
38113
|
}
|
|
37853
38114
|
}
|
|
37854
38115
|
async function migrateClaudeMd(root, actions) {
|
|
37855
|
-
const claudeMd = (0,
|
|
37856
|
-
const hadLegacyBlock = (0,
|
|
38116
|
+
const claudeMd = (0, import_node_path45.join)(root, "CLAUDE.md");
|
|
38117
|
+
const hadLegacyBlock = (0, import_node_fs61.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
37857
38118
|
if (!hadLegacyBlock) return;
|
|
37858
38119
|
try {
|
|
37859
38120
|
await ensureClaudeMdPointer(root);
|
|
@@ -37863,9 +38124,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
37863
38124
|
}
|
|
37864
38125
|
}
|
|
37865
38126
|
function migrateStandardFile(root, actions) {
|
|
37866
|
-
const gateMd = (0,
|
|
37867
|
-
const verityMd = (0,
|
|
37868
|
-
if (!(0,
|
|
38127
|
+
const gateMd = (0, import_node_path45.join)(root, "GATE.md");
|
|
38128
|
+
const verityMd = (0, import_node_path45.join)(root, "VERITY.md");
|
|
38129
|
+
if (!(0, import_node_fs61.existsSync)(gateMd) || (0, import_node_fs61.existsSync)(verityMd)) return;
|
|
37869
38130
|
let moved = false;
|
|
37870
38131
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
37871
38132
|
try {
|
|
@@ -37877,12 +38138,12 @@ function migrateStandardFile(root, actions) {
|
|
|
37877
38138
|
if (!moved) moveFile(gateMd, verityMd);
|
|
37878
38139
|
const content = readFileSyncSafe(verityMd);
|
|
37879
38140
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
37880
|
-
if (refreshed !== content) (0,
|
|
38141
|
+
if (refreshed !== content) (0, import_node_fs61.writeFileSync)(verityMd, refreshed);
|
|
37881
38142
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
37882
38143
|
}
|
|
37883
38144
|
async function migrateTelemetryHeaders(root, actions) {
|
|
37884
|
-
const file = (0,
|
|
37885
|
-
if (!(0,
|
|
38145
|
+
const file = (0, import_node_path45.join)(root, ".claude", "settings.local.json");
|
|
38146
|
+
if (!(0, import_node_fs61.existsSync)(file)) return;
|
|
37886
38147
|
let settings;
|
|
37887
38148
|
try {
|
|
37888
38149
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -37930,14 +38191,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
37930
38191
|
}
|
|
37931
38192
|
if (toAppend.length > 0) {
|
|
37932
38193
|
const sep5 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
37933
|
-
(0,
|
|
38194
|
+
(0, import_node_fs61.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
|
|
37934
38195
|
}
|
|
37935
|
-
(0,
|
|
38196
|
+
(0, import_node_fs61.rmSync)(gateCreds, { force: true });
|
|
37936
38197
|
return toAppend.length;
|
|
37937
38198
|
}
|
|
37938
38199
|
function readFileSyncSafe(path) {
|
|
37939
38200
|
try {
|
|
37940
|
-
return (0,
|
|
38201
|
+
return (0, import_node_fs61.readFileSync)(path, "utf-8");
|
|
37941
38202
|
} catch {
|
|
37942
38203
|
return "";
|
|
37943
38204
|
}
|
|
@@ -37952,35 +38213,35 @@ function hasStagedChanges(root) {
|
|
|
37952
38213
|
}
|
|
37953
38214
|
function moveDir(from, to) {
|
|
37954
38215
|
try {
|
|
37955
|
-
(0,
|
|
38216
|
+
(0, import_node_fs61.renameSync)(from, to);
|
|
37956
38217
|
} catch (err2) {
|
|
37957
38218
|
if (err2.code !== "EXDEV") throw err2;
|
|
37958
|
-
(0,
|
|
37959
|
-
(0,
|
|
38219
|
+
(0, import_node_fs61.cpSync)(from, to, { recursive: true });
|
|
38220
|
+
(0, import_node_fs61.rmSync)(from, { recursive: true, force: true });
|
|
37960
38221
|
}
|
|
37961
38222
|
}
|
|
37962
38223
|
function moveFile(from, to) {
|
|
37963
38224
|
try {
|
|
37964
|
-
(0,
|
|
38225
|
+
(0, import_node_fs61.renameSync)(from, to);
|
|
37965
38226
|
} catch (err2) {
|
|
37966
38227
|
if (err2.code !== "EXDEV") throw err2;
|
|
37967
|
-
(0,
|
|
37968
|
-
(0,
|
|
38228
|
+
(0, import_node_fs61.cpSync)(from, to);
|
|
38229
|
+
(0, import_node_fs61.rmSync)(from, { force: true });
|
|
37969
38230
|
}
|
|
37970
38231
|
}
|
|
37971
38232
|
function carryLegacyContents(gateDir, verityDir) {
|
|
37972
38233
|
let copied = 0;
|
|
37973
38234
|
const walk2 = (relDir) => {
|
|
37974
|
-
const srcDir = (0,
|
|
37975
|
-
for (const entry of (0,
|
|
37976
|
-
const rel = relDir ? (0,
|
|
37977
|
-
const src = (0,
|
|
37978
|
-
const dest = (0,
|
|
37979
|
-
if ((0,
|
|
38235
|
+
const srcDir = (0, import_node_path45.join)(gateDir, relDir);
|
|
38236
|
+
for (const entry of (0, import_node_fs61.readdirSync)(srcDir)) {
|
|
38237
|
+
const rel = relDir ? (0, import_node_path45.join)(relDir, entry) : entry;
|
|
38238
|
+
const src = (0, import_node_path45.join)(gateDir, rel);
|
|
38239
|
+
const dest = (0, import_node_path45.join)(verityDir, rel);
|
|
38240
|
+
if ((0, import_node_fs61.statSync)(src).isDirectory()) {
|
|
37980
38241
|
walk2(rel);
|
|
37981
|
-
} else if (!(0,
|
|
37982
|
-
(0,
|
|
37983
|
-
(0,
|
|
38242
|
+
} else if (!(0, import_node_fs61.existsSync)(dest)) {
|
|
38243
|
+
(0, import_node_fs61.mkdirSync)((0, import_node_path45.dirname)(dest), { recursive: true });
|
|
38244
|
+
(0, import_node_fs61.cpSync)(src, dest);
|
|
37984
38245
|
copied++;
|
|
37985
38246
|
}
|
|
37986
38247
|
}
|
|
@@ -37989,22 +38250,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
37989
38250
|
return copied;
|
|
37990
38251
|
}
|
|
37991
38252
|
async function needsMigration(root = repoRoot()) {
|
|
37992
|
-
const gateDir = (0,
|
|
37993
|
-
const verityDir = (0,
|
|
37994
|
-
if ((0,
|
|
37995
|
-
if ((0,
|
|
37996
|
-
if ((0,
|
|
38253
|
+
const gateDir = (0, import_node_path45.join)(root, ".gate");
|
|
38254
|
+
const verityDir = (0, import_node_path45.join)(root, ".verity");
|
|
38255
|
+
if ((0, import_node_fs61.existsSync)(gateDir) && !(0, import_node_fs61.existsSync)(verityDir)) return true;
|
|
38256
|
+
if ((0, import_node_fs61.existsSync)(gateDir) && (0, import_node_fs61.existsSync)(verityDir)) {
|
|
38257
|
+
if ((0, import_node_fs61.existsSync)((0, import_node_path45.join)(gateDir, "credentials")) && !(0, import_node_fs61.existsSync)((0, import_node_path45.join)(verityDir, "credentials"))) {
|
|
37997
38258
|
return true;
|
|
37998
38259
|
}
|
|
37999
|
-
if ((0,
|
|
38260
|
+
if ((0, import_node_fs61.existsSync)((0, import_node_path45.join)(gateDir, "memory")) && !(0, import_node_fs61.existsSync)((0, import_node_path45.join)(verityDir, "memory"))) {
|
|
38000
38261
|
return true;
|
|
38001
38262
|
}
|
|
38002
38263
|
}
|
|
38003
|
-
const claudeMd = (0,
|
|
38004
|
-
if ((0,
|
|
38264
|
+
const claudeMd = (0, import_node_path45.join)(root, "CLAUDE.md");
|
|
38265
|
+
if ((0, import_node_fs61.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
38005
38266
|
return true;
|
|
38006
38267
|
}
|
|
38007
|
-
if ((0,
|
|
38268
|
+
if ((0, import_node_fs61.existsSync)((0, import_node_path45.join)(root, "GATE.md")) && !(0, import_node_fs61.existsSync)((0, import_node_path45.join)(root, "VERITY.md"))) {
|
|
38008
38269
|
return true;
|
|
38009
38270
|
}
|
|
38010
38271
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -38285,11 +38546,11 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
38285
38546
|
}
|
|
38286
38547
|
|
|
38287
38548
|
// src/lib/prove/lean-install.ts
|
|
38288
|
-
var
|
|
38549
|
+
var import_node_fs62 = require("node:fs");
|
|
38289
38550
|
var import_node_crypto20 = require("node:crypto");
|
|
38290
38551
|
var import_node_child_process18 = require("node:child_process");
|
|
38291
38552
|
var import_node_os10 = require("node:os");
|
|
38292
|
-
var
|
|
38553
|
+
var import_node_path46 = require("node:path");
|
|
38293
38554
|
var import_promises18 = require("node:stream/promises");
|
|
38294
38555
|
var import_node_stream = require("node:stream");
|
|
38295
38556
|
var RELEASES = "https://releases.lean-lang.org/lean4";
|
|
@@ -38309,7 +38570,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
|
|
|
38309
38570
|
function sha256File(path) {
|
|
38310
38571
|
return new Promise((resolve8, reject) => {
|
|
38311
38572
|
const hash = (0, import_node_crypto20.createHash)("sha256");
|
|
38312
|
-
(0,
|
|
38573
|
+
(0, import_node_fs62.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
|
|
38313
38574
|
});
|
|
38314
38575
|
}
|
|
38315
38576
|
async function verifyDownload(zip, asset, version = pinnedVersion()) {
|
|
@@ -38329,7 +38590,7 @@ function leanAssetName(version = pinnedVersion()) {
|
|
|
38329
38590
|
return suffix ? `lean-${v}-${suffix}.zip` : null;
|
|
38330
38591
|
}
|
|
38331
38592
|
function pinnedVersionDir(env = process.env) {
|
|
38332
|
-
return (0,
|
|
38593
|
+
return (0, import_node_path46.join)(verityLeanHome(env), pinnedVersion());
|
|
38333
38594
|
}
|
|
38334
38595
|
function lakeBinary() {
|
|
38335
38596
|
return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
|
|
@@ -38340,12 +38601,12 @@ function unzip(zip, dest) {
|
|
|
38340
38601
|
for (const [cmd, args2] of attempts) {
|
|
38341
38602
|
try {
|
|
38342
38603
|
(0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
|
|
38343
|
-
if ((0,
|
|
38604
|
+
if ((0, import_node_fs62.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
|
|
38344
38605
|
errors.push(`${cmd}: produced nothing`);
|
|
38345
38606
|
} catch (err2) {
|
|
38346
38607
|
errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
|
|
38347
38608
|
try {
|
|
38348
|
-
for (const e of (0,
|
|
38609
|
+
for (const e of (0, import_node_fs62.readdirSync)(dest)) (0, import_node_fs62.rmSync)((0, import_node_path46.join)(dest, e), { recursive: true, force: true });
|
|
38349
38610
|
} catch {
|
|
38350
38611
|
}
|
|
38351
38612
|
}
|
|
@@ -38362,7 +38623,7 @@ async function download(url, dest, onProgress) {
|
|
|
38362
38623
|
seen += chunk.length;
|
|
38363
38624
|
onProgress(seen, total);
|
|
38364
38625
|
});
|
|
38365
|
-
await (0, import_promises18.pipeline)(stream, (0,
|
|
38626
|
+
await (0, import_promises18.pipeline)(stream, (0, import_node_fs62.createWriteStream)(dest));
|
|
38366
38627
|
}
|
|
38367
38628
|
function inPlaceProgress(label2, write = (s) => process.stderr.write(s)) {
|
|
38368
38629
|
let active = false;
|
|
@@ -38400,10 +38661,10 @@ async function installLean(opts = {}) {
|
|
|
38400
38661
|
const dir = pinnedVersionDir(env);
|
|
38401
38662
|
const url = `${RELEASES}/${pinnedVersion()}/${asset}`;
|
|
38402
38663
|
const home = verityLeanHome(env);
|
|
38403
|
-
const tmp = (0,
|
|
38404
|
-
(0,
|
|
38405
|
-
(0,
|
|
38406
|
-
const zip = (0,
|
|
38664
|
+
const tmp = (0, import_node_path46.join)(home, ".tmp");
|
|
38665
|
+
(0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
|
|
38666
|
+
(0, import_node_fs62.mkdirSync)(tmp, { recursive: true });
|
|
38667
|
+
const zip = (0, import_node_path46.join)(tmp, asset);
|
|
38407
38668
|
say(`downloading ${url}`);
|
|
38408
38669
|
let lastPct = -1;
|
|
38409
38670
|
try {
|
|
@@ -38416,40 +38677,40 @@ async function installLean(opts = {}) {
|
|
|
38416
38677
|
}
|
|
38417
38678
|
});
|
|
38418
38679
|
} catch (err2) {
|
|
38419
|
-
(0,
|
|
38680
|
+
(0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
|
|
38420
38681
|
return { ok: false, error: err2.message };
|
|
38421
38682
|
}
|
|
38422
38683
|
say("verifying checksum");
|
|
38423
38684
|
const verified = await verifyDownload(zip, asset);
|
|
38424
38685
|
if (!verified.ok) {
|
|
38425
|
-
(0,
|
|
38686
|
+
(0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
|
|
38426
38687
|
return { ok: false, error: verified.error };
|
|
38427
38688
|
}
|
|
38428
38689
|
say("unpacking (this takes a minute)");
|
|
38429
|
-
const unpack = (0,
|
|
38430
|
-
(0,
|
|
38690
|
+
const unpack = (0, import_node_path46.join)(tmp, "unpack");
|
|
38691
|
+
(0, import_node_fs62.mkdirSync)(unpack);
|
|
38431
38692
|
const unpacked = unzip(zip, unpack);
|
|
38432
38693
|
if (!unpacked.ok) {
|
|
38433
|
-
(0,
|
|
38694
|
+
(0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
|
|
38434
38695
|
return { ok: false, error: `unpack failed: ${unpacked.error}` };
|
|
38435
38696
|
}
|
|
38436
|
-
const entries = (0,
|
|
38437
|
-
const top = entries.length === 1 && (0,
|
|
38438
|
-
if (!(0,
|
|
38439
|
-
(0,
|
|
38697
|
+
const entries = (0, import_node_fs62.readdirSync)(unpack);
|
|
38698
|
+
const top = entries.length === 1 && (0, import_node_fs62.statSync)((0, import_node_path46.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path46.join)(unpack, entries[0]) : unpack;
|
|
38699
|
+
if (!(0, import_node_fs62.existsSync)((0, import_node_path46.join)(top, "bin", lakeBinary()))) {
|
|
38700
|
+
(0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
|
|
38440
38701
|
return { ok: false, error: "the archive did not contain bin/lake" };
|
|
38441
38702
|
}
|
|
38442
|
-
(0,
|
|
38443
|
-
(0,
|
|
38444
|
-
(0,
|
|
38445
|
-
(0,
|
|
38703
|
+
(0, import_node_fs62.rmSync)(dir, { recursive: true, force: true });
|
|
38704
|
+
(0, import_node_fs62.mkdirSync)(home, { recursive: true });
|
|
38705
|
+
(0, import_node_fs62.renameSync)(top, dir);
|
|
38706
|
+
(0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
|
|
38446
38707
|
return { ok: true, dir };
|
|
38447
38708
|
}
|
|
38448
38709
|
|
|
38449
38710
|
// src/lib/remote-config.ts
|
|
38450
|
-
var
|
|
38711
|
+
var import_node_fs63 = require("node:fs");
|
|
38451
38712
|
var import_promises19 = require("node:fs/promises");
|
|
38452
|
-
var
|
|
38713
|
+
var import_node_path47 = require("node:path");
|
|
38453
38714
|
var import_yaml5 = __toESM2(require_dist());
|
|
38454
38715
|
var IGNORE_RIDER = "verityignore";
|
|
38455
38716
|
async function fetchRemoteSetup(opts) {
|
|
@@ -38494,7 +38755,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
38494
38755
|
written.push(STANDARD_FILE);
|
|
38495
38756
|
if (rider !== null) {
|
|
38496
38757
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
38497
|
-
if (!(0,
|
|
38758
|
+
if (!(0, import_node_fs63.existsSync)(localIgnore)) {
|
|
38498
38759
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
38499
38760
|
written.push(VERITYIGNORE_FILE);
|
|
38500
38761
|
} else {
|
|
@@ -38527,7 +38788,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
38527
38788
|
}
|
|
38528
38789
|
async function writeOut(relative6, body2) {
|
|
38529
38790
|
const target = projectPath(relative6);
|
|
38530
|
-
await (0, import_promises19.mkdir)((0,
|
|
38791
|
+
await (0, import_promises19.mkdir)((0, import_node_path47.dirname)(target), { recursive: true });
|
|
38531
38792
|
await (0, import_promises19.writeFile)(target, body2);
|
|
38532
38793
|
}
|
|
38533
38794
|
function describeRemote(found) {
|
|
@@ -38644,15 +38905,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
38644
38905
|
}
|
|
38645
38906
|
function resolveDataDir2() {
|
|
38646
38907
|
const candidates2 = [
|
|
38647
|
-
(0,
|
|
38908
|
+
(0, import_node_path48.join)(__dirname, "..", "data"),
|
|
38648
38909
|
// installed: node_modules/@codacy/verity-cli/data
|
|
38649
|
-
(0,
|
|
38910
|
+
(0, import_node_path48.join)(__dirname, "..", "..", "data"),
|
|
38650
38911
|
// edge case: nested resolution
|
|
38651
|
-
(0,
|
|
38912
|
+
(0, import_node_path48.join)(process.cwd(), "cli", "data")
|
|
38652
38913
|
// local dev: running from repo root
|
|
38653
38914
|
];
|
|
38654
38915
|
for (const candidate of candidates2) {
|
|
38655
|
-
if ((0,
|
|
38916
|
+
if ((0, import_node_fs64.existsSync)((0, import_node_path48.join)(candidate, "skills"))) {
|
|
38656
38917
|
return candidate;
|
|
38657
38918
|
}
|
|
38658
38919
|
}
|
|
@@ -38668,9 +38929,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
38668
38929
|
const list2 = (dir) => {
|
|
38669
38930
|
const out2 = [];
|
|
38670
38931
|
const walk2 = (d, prefix) => {
|
|
38671
|
-
for (const e of (0,
|
|
38932
|
+
for (const e of (0, import_node_fs64.readdirSync)(d, { withFileTypes: true })) {
|
|
38672
38933
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
38673
|
-
if (e.isDirectory()) walk2((0,
|
|
38934
|
+
if (e.isDirectory()) walk2((0, import_node_path48.join)(d, e.name), rel);
|
|
38674
38935
|
else if (e.isFile()) out2.push(rel);
|
|
38675
38936
|
}
|
|
38676
38937
|
};
|
|
@@ -38681,8 +38942,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
38681
38942
|
const shipped = list2(src);
|
|
38682
38943
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
38683
38944
|
for (const rel of shipped) {
|
|
38684
|
-
const a = await (0, import_promises20.readFile)((0,
|
|
38685
|
-
const b = await (0, import_promises20.readFile)((0,
|
|
38945
|
+
const a = await (0, import_promises20.readFile)((0, import_node_path48.join)(src, rel), "utf-8");
|
|
38946
|
+
const b = await (0, import_promises20.readFile)((0, import_node_path48.join)(dest, rel), "utf-8");
|
|
38686
38947
|
if (a !== b) return false;
|
|
38687
38948
|
}
|
|
38688
38949
|
return true;
|
|
@@ -38730,8 +38991,14 @@ async function askSetupQuestions(defaultsOnly, previous, given = {}) {
|
|
|
38730
38991
|
const momentsDefault = given.moments ?? (previous?.moments?.length ? previous.moments : await momentsFromInstalledHooks());
|
|
38731
38992
|
const askIntensity = !given.intensity;
|
|
38732
38993
|
const askMoments = !given.moments;
|
|
38994
|
+
const givenTelemetry = async () => {
|
|
38995
|
+
if (given.telemetry === void 0) return "not-asked";
|
|
38996
|
+
const enabled = (await checkTelemetry()).enabled;
|
|
38997
|
+
if (given.telemetry) return enabled ? "already-on" : "yes";
|
|
38998
|
+
return enabled ? "turn-off" : "no";
|
|
38999
|
+
};
|
|
38733
39000
|
if (defaultsOnly || !askIntensity && !askMoments) {
|
|
38734
|
-
return { intensity: intensityDefault, moments: momentsDefault, telemetry:
|
|
39001
|
+
return { intensity: intensityDefault, moments: momentsDefault, telemetry: await givenTelemetry() };
|
|
38735
39002
|
}
|
|
38736
39003
|
if (previous?.intensity || previous?.moments) {
|
|
38737
39004
|
printInfo(`Current: ${intensityDefault} \xB7 ${momentsDefault.join(", ")} \u2014 press Enter to keep either.`);
|
|
@@ -38746,6 +39013,9 @@ async function askSetupQuestions(defaultsOnly, previous, given = {}) {
|
|
|
38746
39013
|
MOMENT_CHOICES,
|
|
38747
39014
|
momentsDefault
|
|
38748
39015
|
);
|
|
39016
|
+
if (given.telemetry !== void 0) {
|
|
39017
|
+
return { intensity, moments, telemetry: await givenTelemetry() };
|
|
39018
|
+
}
|
|
38749
39019
|
const current = await checkTelemetry();
|
|
38750
39020
|
if (current.enabled) {
|
|
38751
39021
|
printInfo(`Cost & usage telemetry: already enabled \u2192 ${current.endpoint}`);
|
|
@@ -38760,6 +39030,12 @@ async function askSetupQuestions(defaultsOnly, previous, given = {}) {
|
|
|
38760
39030
|
const wants = await promptYes(" Enable cost & usage telemetry? [Y/n] ", { nonInteractive: false });
|
|
38761
39031
|
return { intensity, moments, telemetry: wants ? "yes" : "no" };
|
|
38762
39032
|
}
|
|
39033
|
+
function parseTelemetryAnswer(raw) {
|
|
39034
|
+
const v = raw.trim().toLowerCase();
|
|
39035
|
+
if (v === "on") return true;
|
|
39036
|
+
if (v === "off") return false;
|
|
39037
|
+
return null;
|
|
39038
|
+
}
|
|
38763
39039
|
function insideClaudeCode() {
|
|
38764
39040
|
return !!process.env.CLAUDECODE || !!process.env.CLAUDE_SESSION_ID;
|
|
38765
39041
|
}
|
|
@@ -38868,7 +39144,7 @@ async function synthesizeLocally(opts) {
|
|
|
38868
39144
|
async function healStaleAnalysisConfig(globals) {
|
|
38869
39145
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
38870
39146
|
const standardPath = projectPath(STANDARD_FILE);
|
|
38871
|
-
if (!(0,
|
|
39147
|
+
if (!(0, import_node_fs64.existsSync)(configPath) || !(0, import_node_fs64.existsSync)(standardPath)) return;
|
|
38872
39148
|
const validation = validatePatternIds();
|
|
38873
39149
|
if (validation.status !== "invalid") return;
|
|
38874
39150
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -38965,17 +39241,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
38965
39241
|
async function installSkills(force, step) {
|
|
38966
39242
|
step("Installing skills");
|
|
38967
39243
|
const dataDir = resolveDataDir2();
|
|
38968
|
-
const skillsSource = (0,
|
|
39244
|
+
const skillsSource = (0, import_node_path48.join)(dataDir, "skills");
|
|
38969
39245
|
const skillsDest = ".claude/skills";
|
|
38970
39246
|
let skillsInstalled = 0;
|
|
38971
39247
|
for (const skill of SKILLS) {
|
|
38972
|
-
const src = (0,
|
|
38973
|
-
const dest = (0,
|
|
38974
|
-
if (!(0,
|
|
39248
|
+
const src = (0, import_node_path48.join)(skillsSource, skill);
|
|
39249
|
+
const dest = (0, import_node_path48.join)(skillsDest, skill);
|
|
39250
|
+
if (!(0, import_node_fs64.existsSync)(src)) {
|
|
38975
39251
|
printWarn(` Skill data not found: ${skill}`);
|
|
38976
39252
|
continue;
|
|
38977
39253
|
}
|
|
38978
|
-
if ((0,
|
|
39254
|
+
if ((0, import_node_fs64.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
38979
39255
|
skillsInstalled++;
|
|
38980
39256
|
continue;
|
|
38981
39257
|
}
|
|
@@ -39037,7 +39313,7 @@ async function checkPrerequisites(step) {
|
|
|
39037
39313
|
}
|
|
39038
39314
|
return prereqs.checks.some((c) => c.id === "claude" && c.status === "ok");
|
|
39039
39315
|
}
|
|
39040
|
-
async function scaffoldProject(step, defaultsOnly, pluginMode) {
|
|
39316
|
+
async function scaffoldProject(step, defaultsOnly, pluginMode, given = {}) {
|
|
39041
39317
|
step("Knowledge base, .gitignore and CLAUDE.md");
|
|
39042
39318
|
await (0, import_promises20.mkdir)(VERITY_DIR, { recursive: true });
|
|
39043
39319
|
await ensureMemoryDir();
|
|
@@ -39062,7 +39338,7 @@ async function scaffoldProject(step, defaultsOnly, pluginMode) {
|
|
|
39062
39338
|
const trackedMemory = memoryOptOut() ? [] : committedMemoryFiles();
|
|
39063
39339
|
if (trackedMemory.length > 0) {
|
|
39064
39340
|
printWarn(` ${trackedMemory.length} knowledge-graph file(s) are tracked, so they show up in every diff.`);
|
|
39065
|
-
const fence = defaultsOnly ? false : await promptYes(" Stop tracking them (files stay on disk)? [Y/n] ", { nonInteractive: false });
|
|
39341
|
+
const fence = given.untrackMemory ? true : defaultsOnly ? false : await promptYes(" Stop tracking them (files stay on disk)? [Y/n] ", { nonInteractive: false });
|
|
39066
39342
|
if (fence) {
|
|
39067
39343
|
const result = fenceMemory();
|
|
39068
39344
|
if (!result.ok) printWarn(' Could not untrack \u2014 run "verity memory untrack" when you can');
|
|
@@ -39077,7 +39353,7 @@ async function scaffoldProject(step, defaultsOnly, pluginMode) {
|
|
|
39077
39353
|
const tracked = committedVerityState();
|
|
39078
39354
|
if (tracked.length > 0) {
|
|
39079
39355
|
printWarn(` ${tracked.length} Verity state file(s) are tracked in git (e.g. ${tracked[0]}).`);
|
|
39080
|
-
const untrack = defaultsOnly ? false : await promptYes(" Untrack them now (files stay on disk)? [Y/n] ", { nonInteractive: false });
|
|
39356
|
+
const untrack = given.untrackState ? true : defaultsOnly ? false : await promptYes(" Untrack them now (files stay on disk)? [Y/n] ", { nonInteractive: false });
|
|
39081
39357
|
if (untrack) {
|
|
39082
39358
|
const result = untrackVerityState();
|
|
39083
39359
|
if (result === "untracked") printInfo(" Untracked (staged) \u2014 commit to finish \u2713");
|
|
@@ -39155,7 +39431,10 @@ function registerInitCommand(program2) {
|
|
|
39155
39431
|
).option(
|
|
39156
39432
|
"--intensity <level>",
|
|
39157
39433
|
"Answer the analysis-intensity question without asking: lightweight | balanced | thorough"
|
|
39158
|
-
).
|
|
39434
|
+
).option(
|
|
39435
|
+
"--telemetry <on|off>",
|
|
39436
|
+
"Answer the cost & usage telemetry question without asking: on | off"
|
|
39437
|
+
).option("--untrack-memory", 'Answer yes to "stop tracking the knowledge graph in git?" without asking').option("--untrack-state", 'Answer yes to "untrack committed Verity state?" without asking').action(async (opts) => {
|
|
39159
39438
|
const force = opts.force ?? false;
|
|
39160
39439
|
const wantsHandoff = opts.setup !== false;
|
|
39161
39440
|
const wantsAdopt = opts.adopt !== false;
|
|
@@ -39163,7 +39442,7 @@ function registerInitCommand(program2) {
|
|
|
39163
39442
|
const staleMarker = clearStalePluginMarker();
|
|
39164
39443
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
39165
39444
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
39166
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
39445
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs64.existsSync)(m));
|
|
39167
39446
|
if (!isProject) {
|
|
39168
39447
|
printError("No project detected in the current directory.");
|
|
39169
39448
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -39244,16 +39523,29 @@ function registerInitCommand(program2) {
|
|
|
39244
39523
|
}
|
|
39245
39524
|
givenIntensity = match.id;
|
|
39246
39525
|
}
|
|
39526
|
+
let givenTelemetry;
|
|
39527
|
+
if (opts.telemetry != null) {
|
|
39528
|
+
const parsed = parseTelemetryAnswer(String(opts.telemetry));
|
|
39529
|
+
if (parsed === null) {
|
|
39530
|
+
printError(`--telemetry: unrecognised "${opts.telemetry}". Valid: on, off.`);
|
|
39531
|
+
process.exit(1);
|
|
39532
|
+
}
|
|
39533
|
+
givenTelemetry = parsed;
|
|
39534
|
+
}
|
|
39247
39535
|
const answers = await askSetupQuestions(defaultsOnly, previous, {
|
|
39248
39536
|
intensity: givenIntensity,
|
|
39249
|
-
moments: givenMoments
|
|
39537
|
+
moments: givenMoments,
|
|
39538
|
+
telemetry: givenTelemetry
|
|
39250
39539
|
});
|
|
39251
39540
|
const { intensity, moments } = answers;
|
|
39252
39541
|
if (defaultsOnly) {
|
|
39253
39542
|
printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
|
|
39254
39543
|
}
|
|
39255
|
-
await scaffoldProject(step, defaultsOnly, pluginMode
|
|
39256
|
-
|
|
39544
|
+
await scaffoldProject(step, defaultsOnly, pluginMode, {
|
|
39545
|
+
untrackMemory: opts.untrackMemory === true,
|
|
39546
|
+
untrackState: opts.untrackState === true
|
|
39547
|
+
});
|
|
39548
|
+
const globalVerityDir = (0, import_node_path48.join)(process.env.HOME ?? "", ".verity");
|
|
39257
39549
|
await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
|
|
39258
39550
|
console.log("");
|
|
39259
39551
|
step("Wiring Claude Code hooks");
|
|
@@ -39301,8 +39593,14 @@ function registerInitCommand(program2) {
|
|
|
39301
39593
|
printInfo(' not asked (unattended run) \u2014 enable later with "verity telemetry install"');
|
|
39302
39594
|
} else if (answers.telemetry === "no") {
|
|
39303
39595
|
printInfo(' declined \u2014 enable later with "verity telemetry install"');
|
|
39304
|
-
}
|
|
39305
|
-
|
|
39596
|
+
} else if (answers.telemetry === "already-on") {
|
|
39597
|
+
printInfo(" already enabled \u2713");
|
|
39598
|
+
} else if (answers.telemetry === "turn-off") {
|
|
39599
|
+
const removed = await uninstallTelemetry();
|
|
39600
|
+
if (removed.ok) printInfo(' turned off (--telemetry off) \u2014 re-enable with "verity telemetry install"');
|
|
39601
|
+
else printWarn(` Could not turn telemetry off: ${removed.error}`);
|
|
39602
|
+
}
|
|
39603
|
+
let telemetryChoice = answers.telemetry === "already-on" ? "enabled" : answers.telemetry === "no" || answers.telemetry === "turn-off" ? "declined" : wantsTelemetry ? "deferred" : void 0;
|
|
39306
39604
|
if (wantsTelemetry) {
|
|
39307
39605
|
const globals = program2.opts();
|
|
39308
39606
|
const token = await resolveToken(globals.token);
|
|
@@ -39322,7 +39620,7 @@ function registerInitCommand(program2) {
|
|
|
39322
39620
|
}
|
|
39323
39621
|
step("Your project's Standard");
|
|
39324
39622
|
let haveStandard = false;
|
|
39325
|
-
if ((0,
|
|
39623
|
+
if ((0, import_node_fs64.existsSync)(projectPath(STANDARD_FILE))) {
|
|
39326
39624
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
39327
39625
|
haveStandard = true;
|
|
39328
39626
|
} else {
|
|
@@ -39352,7 +39650,7 @@ function registerInitCommand(program2) {
|
|
|
39352
39650
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
39353
39651
|
init: {
|
|
39354
39652
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39355
|
-
cli_version: true ? "0.33.3-experimental.
|
|
39653
|
+
cli_version: true ? "0.33.3-experimental.5a3f573" : "dev"
|
|
39356
39654
|
}
|
|
39357
39655
|
});
|
|
39358
39656
|
} catch (err2) {
|
|
@@ -39402,8 +39700,8 @@ function registerInitCommand(program2) {
|
|
|
39402
39700
|
}
|
|
39403
39701
|
|
|
39404
39702
|
// src/commands/uninstall.ts
|
|
39405
|
-
var
|
|
39406
|
-
var
|
|
39703
|
+
var import_node_fs65 = require("node:fs");
|
|
39704
|
+
var import_node_path49 = require("node:path");
|
|
39407
39705
|
function registerUninstallCommand(program2) {
|
|
39408
39706
|
program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
|
|
39409
39707
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -39412,11 +39710,11 @@ function registerUninstallCommand(program2) {
|
|
|
39412
39710
|
const actions = [];
|
|
39413
39711
|
const skillsRoot = projectPath(".claude/skills");
|
|
39414
39712
|
for (const name2 of PROJECT_SKILL_NAMES) {
|
|
39415
|
-
const dir = (0,
|
|
39416
|
-
if ((0,
|
|
39713
|
+
const dir = (0, import_node_path49.join)(skillsRoot, name2);
|
|
39714
|
+
if ((0, import_node_fs65.existsSync)(dir)) {
|
|
39417
39715
|
actions.push({
|
|
39418
39716
|
label: `Remove .claude/skills/${name2}/`,
|
|
39419
|
-
apply: () => (0,
|
|
39717
|
+
apply: () => (0, import_node_fs65.rmSync)(dir, { recursive: true, force: true })
|
|
39420
39718
|
});
|
|
39421
39719
|
}
|
|
39422
39720
|
}
|
|
@@ -39430,24 +39728,24 @@ function registerUninstallCommand(program2) {
|
|
|
39430
39728
|
});
|
|
39431
39729
|
}
|
|
39432
39730
|
const verityDir = projectPath(VERITY_DIR);
|
|
39433
|
-
if ((0,
|
|
39731
|
+
if ((0, import_node_fs65.existsSync)(verityDir)) {
|
|
39434
39732
|
actions.push({
|
|
39435
39733
|
label: `Remove ${VERITY_DIR}/`,
|
|
39436
|
-
apply: () => (0,
|
|
39734
|
+
apply: () => (0, import_node_fs65.rmSync)(verityDir, { recursive: true, force: true })
|
|
39437
39735
|
});
|
|
39438
39736
|
}
|
|
39439
39737
|
if (!keepVerityMd) {
|
|
39440
39738
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
39441
|
-
if ((0,
|
|
39739
|
+
if ((0, import_node_fs65.existsSync)(verityMd)) {
|
|
39442
39740
|
actions.push({
|
|
39443
39741
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
39444
|
-
apply: () => (0,
|
|
39742
|
+
apply: () => (0, import_node_fs65.rmSync)(verityMd, { force: true })
|
|
39445
39743
|
});
|
|
39446
39744
|
}
|
|
39447
39745
|
}
|
|
39448
39746
|
const cleanupEmptyDir = (path) => {
|
|
39449
|
-
if ((0,
|
|
39450
|
-
(0,
|
|
39747
|
+
if ((0, import_node_fs65.existsSync)(path) && (0, import_node_fs65.statSync)(path).isDirectory() && (0, import_node_fs65.readdirSync)(path).length === 0) {
|
|
39748
|
+
(0, import_node_fs65.rmdirSync)(path);
|
|
39451
39749
|
}
|
|
39452
39750
|
};
|
|
39453
39751
|
actions.push({
|
|
@@ -39458,11 +39756,11 @@ function registerUninstallCommand(program2) {
|
|
|
39458
39756
|
}
|
|
39459
39757
|
});
|
|
39460
39758
|
const home = process.env.HOME ?? "";
|
|
39461
|
-
const globalVerityDir = (0,
|
|
39462
|
-
if (purgeGlobal && (0,
|
|
39759
|
+
const globalVerityDir = (0, import_node_path49.join)(home, ".verity");
|
|
39760
|
+
if (purgeGlobal && (0, import_node_fs65.existsSync)(globalVerityDir)) {
|
|
39463
39761
|
actions.push({
|
|
39464
39762
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
39465
|
-
apply: () => (0,
|
|
39763
|
+
apply: () => (0, import_node_fs65.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
39466
39764
|
});
|
|
39467
39765
|
}
|
|
39468
39766
|
if (actions.length === 0) {
|
|
@@ -39656,8 +39954,8 @@ function registerTaskCommands(program2) {
|
|
|
39656
39954
|
}
|
|
39657
39955
|
|
|
39658
39956
|
// src/commands/reset.ts
|
|
39659
|
-
var
|
|
39660
|
-
var
|
|
39957
|
+
var import_node_fs66 = require("node:fs");
|
|
39958
|
+
var import_node_path50 = require("node:path");
|
|
39661
39959
|
function registerResetCommand(program2) {
|
|
39662
39960
|
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) => {
|
|
39663
39961
|
const globals = program2.opts();
|
|
@@ -39694,11 +39992,11 @@ function registerResetCommand(program2) {
|
|
|
39694
39992
|
}
|
|
39695
39993
|
const cacheDir = projectPath(CACHE_DIR);
|
|
39696
39994
|
let purged = 0;
|
|
39697
|
-
if ((0,
|
|
39698
|
-
for (const entry of (0,
|
|
39995
|
+
if ((0, import_node_fs66.existsSync)(cacheDir)) {
|
|
39996
|
+
for (const entry of (0, import_node_fs66.readdirSync)(cacheDir)) {
|
|
39699
39997
|
if (entry.startsWith("pending-")) {
|
|
39700
39998
|
try {
|
|
39701
|
-
(0,
|
|
39999
|
+
(0, import_node_fs66.unlinkSync)((0, import_node_path50.join)(cacheDir, entry));
|
|
39702
40000
|
purged++;
|
|
39703
40001
|
} catch {
|
|
39704
40002
|
}
|
|
@@ -39713,19 +40011,19 @@ function registerResetCommand(program2) {
|
|
|
39713
40011
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
39714
40012
|
];
|
|
39715
40013
|
for (const file of filesToClear) {
|
|
39716
|
-
if ((0,
|
|
40014
|
+
if ((0, import_node_fs66.existsSync)(file)) {
|
|
39717
40015
|
try {
|
|
39718
|
-
(0,
|
|
40016
|
+
(0, import_node_fs66.writeFileSync)(file, "");
|
|
39719
40017
|
} catch {
|
|
39720
40018
|
}
|
|
39721
40019
|
}
|
|
39722
40020
|
}
|
|
39723
40021
|
if (opts.all) {
|
|
39724
40022
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
39725
|
-
if ((0,
|
|
39726
|
-
for (const entry of (0,
|
|
40023
|
+
if ((0, import_node_fs66.existsSync)(logsDir)) {
|
|
40024
|
+
for (const entry of (0, import_node_fs66.readdirSync)(logsDir)) {
|
|
39727
40025
|
try {
|
|
39728
|
-
(0,
|
|
40026
|
+
(0, import_node_fs66.unlinkSync)((0, import_node_path50.join)(logsDir, entry));
|
|
39729
40027
|
} catch {
|
|
39730
40028
|
}
|
|
39731
40029
|
}
|
|
@@ -39737,7 +40035,7 @@ function registerResetCommand(program2) {
|
|
|
39737
40035
|
}
|
|
39738
40036
|
|
|
39739
40037
|
// src/commands/reflect.ts
|
|
39740
|
-
var
|
|
40038
|
+
var import_node_fs67 = require("node:fs");
|
|
39741
40039
|
|
|
39742
40040
|
// src/lib/reflection-globs.ts
|
|
39743
40041
|
var MAX_GLOBS = 6;
|
|
@@ -39775,7 +40073,7 @@ async function writeNodeToDisk(args2) {
|
|
|
39775
40073
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
39776
40074
|
);
|
|
39777
40075
|
if (written === 0) return false;
|
|
39778
|
-
return (0,
|
|
40076
|
+
return (0, import_node_fs67.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
|
|
39779
40077
|
} catch {
|
|
39780
40078
|
return false;
|
|
39781
40079
|
}
|
|
@@ -40207,6 +40505,15 @@ function registerRunCommand(program2) {
|
|
|
40207
40505
|
}
|
|
40208
40506
|
|
|
40209
40507
|
// src/commands/telemetry.ts
|
|
40508
|
+
var import_node_fs68 = require("node:fs");
|
|
40509
|
+
async function recordTelemetryChoice(choice) {
|
|
40510
|
+
if (!(0, import_node_fs68.existsSync)(projectPath(SETUP_STATE_FILE))) return;
|
|
40511
|
+
try {
|
|
40512
|
+
if ((await readSetupState())?.telemetry === choice) return;
|
|
40513
|
+
await writeSetupState({ telemetry: choice });
|
|
40514
|
+
} catch {
|
|
40515
|
+
}
|
|
40516
|
+
}
|
|
40210
40517
|
function registerTelemetryCommands(program2) {
|
|
40211
40518
|
const telemetry = program2.command("telemetry").description("Manage Claude Code OpenTelemetry export to Verity (cost & usage)");
|
|
40212
40519
|
telemetry.command("install").description("Enable Claude Code telemetry export to Verity (writes .claude/settings.local.json)").action(async () => {
|
|
@@ -40232,6 +40539,7 @@ function registerTelemetryCommands(program2) {
|
|
|
40232
40539
|
printError(result.error);
|
|
40233
40540
|
process.exit(1);
|
|
40234
40541
|
}
|
|
40542
|
+
await recordTelemetryChoice("enabled");
|
|
40235
40543
|
printInfo(`Telemetry enabled \u2192 ${result.data.endpoint}`);
|
|
40236
40544
|
printInfo(` wrote ${SETTINGS_LOCAL_FILE2} (no token stored \u2014 resolved at runtime via otelHeadersHelper)`);
|
|
40237
40545
|
printInfo(" takes effect on your NEXT Claude Code session; first metrics appear within ~60s of activity");
|
|
@@ -40268,6 +40576,7 @@ function registerTelemetryCommands(program2) {
|
|
|
40268
40576
|
printError(result.error);
|
|
40269
40577
|
process.exit(1);
|
|
40270
40578
|
}
|
|
40579
|
+
await recordTelemetryChoice("declined");
|
|
40271
40580
|
printInfo(
|
|
40272
40581
|
result.data.removed > 0 ? `Telemetry disabled (${result.data.removed} keys removed from ${SETTINGS_LOCAL_FILE2})` : "Telemetry was not enabled \u2014 nothing to remove."
|
|
40273
40582
|
);
|
|
@@ -40275,8 +40584,8 @@ function registerTelemetryCommands(program2) {
|
|
|
40275
40584
|
}
|
|
40276
40585
|
|
|
40277
40586
|
// src/commands/prove.ts
|
|
40278
|
-
var
|
|
40279
|
-
var
|
|
40587
|
+
var import_node_fs69 = require("node:fs");
|
|
40588
|
+
var import_node_path51 = require("node:path");
|
|
40280
40589
|
|
|
40281
40590
|
// src/lib/prove/hint-pool.ts
|
|
40282
40591
|
var STOP2 = /* @__PURE__ */ new Set([
|
|
@@ -40412,7 +40721,7 @@ function registerProveCommand(program2) {
|
|
|
40412
40721
|
process.exit(2);
|
|
40413
40722
|
}
|
|
40414
40723
|
const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
|
|
40415
|
-
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0,
|
|
40724
|
+
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path51.relative)(root, (0, import_node_path51.resolve)(p)) || ".") });
|
|
40416
40725
|
if (opts.hint && paths.length === 0) {
|
|
40417
40726
|
const hit = hintMatches(root, opts.hint);
|
|
40418
40727
|
if (hit.files.length > 0) {
|
|
@@ -40466,7 +40775,7 @@ function registerProveCommand(program2) {
|
|
|
40466
40775
|
});
|
|
40467
40776
|
prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
|
|
40468
40777
|
const root = repoRoot();
|
|
40469
|
-
if (!(0,
|
|
40778
|
+
if (!(0, import_node_fs69.existsSync)((0, import_node_path51.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
40470
40779
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
40471
40780
|
process.exit(2);
|
|
40472
40781
|
}
|
|
@@ -40490,7 +40799,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
40490
40799
|
const reports = [];
|
|
40491
40800
|
for (const f of files) {
|
|
40492
40801
|
const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
|
|
40493
|
-
report.file = (0,
|
|
40802
|
+
report.file = (0, import_node_path51.relative)(root, f);
|
|
40494
40803
|
reports.push(report);
|
|
40495
40804
|
try {
|
|
40496
40805
|
writeResult(root, report);
|
|
@@ -40528,7 +40837,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
40528
40837
|
printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
|
|
40529
40838
|
process.exit(2);
|
|
40530
40839
|
}
|
|
40531
|
-
if (!(0,
|
|
40840
|
+
if (!(0, import_node_fs69.existsSync)((0, import_node_path51.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
40532
40841
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
40533
40842
|
process.exit(2);
|
|
40534
40843
|
}
|
|
@@ -40559,7 +40868,7 @@ ${report.error ?? ""}`);
|
|
|
40559
40868
|
printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
|
|
40560
40869
|
return;
|
|
40561
40870
|
}
|
|
40562
|
-
const modelSource = readRegularFileInRoot(root, (0,
|
|
40871
|
+
const modelSource = readRegularFileInRoot(root, (0, import_node_path51.relative)(root, file), 512 * 1024);
|
|
40563
40872
|
if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
|
|
40564
40873
|
const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
|
|
40565
40874
|
const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
|
|
@@ -40579,7 +40888,7 @@ ${report.error ?? ""}`);
|
|
|
40579
40888
|
});
|
|
40580
40889
|
prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
|
|
40581
40890
|
const root = repoRoot();
|
|
40582
|
-
let files = paths.map((p) => (0,
|
|
40891
|
+
let files = paths.map((p) => (0, import_node_path51.relative)(root, (0, import_node_path51.resolve)(p)));
|
|
40583
40892
|
if (files.length === 0) {
|
|
40584
40893
|
const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
|
|
40585
40894
|
const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
|
|
@@ -40639,7 +40948,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
40639
40948
|
let revise;
|
|
40640
40949
|
if (opts.revise) {
|
|
40641
40950
|
const existing = resolveModelFile(root, opts.revise);
|
|
40642
|
-
const src = existing ? readRegularFileInRoot(root, (0,
|
|
40951
|
+
const src = existing ? readRegularFileInRoot(root, (0, import_node_path51.relative)(root, existing), 64 * 1024) : null;
|
|
40643
40952
|
if (!src || !src.ok || !opts.note) {
|
|
40644
40953
|
printError('--revise needs an existing model under Models/ and --note "<what the replay showed>"');
|
|
40645
40954
|
process.exit(2);
|
|
@@ -40678,8 +40987,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
40678
40987
|
});
|
|
40679
40988
|
prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
|
|
40680
40989
|
const root = repoRoot();
|
|
40681
|
-
const rel0 = (0,
|
|
40682
|
-
const rel = rel0.startsWith("..") || (0,
|
|
40990
|
+
const rel0 = (0, import_node_path51.relative)(root, (0, import_node_path51.isAbsolute)(file) ? file : (0, import_node_path51.join)(root, file)).replace(/\\/g, "/");
|
|
40991
|
+
const rel = rel0.startsWith("..") || (0, import_node_path51.isAbsolute)(rel0) ? null : rel0;
|
|
40683
40992
|
if (!rel) {
|
|
40684
40993
|
printError(`${file} is not inside this repository`);
|
|
40685
40994
|
process.exit(2);
|
|
@@ -40695,8 +41004,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
40695
41004
|
});
|
|
40696
41005
|
prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
|
|
40697
41006
|
const root = repoRoot();
|
|
40698
|
-
const rel = (0,
|
|
40699
|
-
const digest = rel.startsWith("..") || (0,
|
|
41007
|
+
const rel = (0, import_node_path51.relative)(root, (0, import_node_path51.isAbsolute)(file) ? file : (0, import_node_path51.join)(root, file));
|
|
41008
|
+
const digest = rel.startsWith("..") || (0, import_node_path51.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
|
|
40700
41009
|
if (!digest) {
|
|
40701
41010
|
printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
|
|
40702
41011
|
process.exit(2);
|
|
@@ -40730,10 +41039,10 @@ function refreshScaffold(root) {
|
|
|
40730
41039
|
}
|
|
40731
41040
|
|
|
40732
41041
|
// src/commands/lean.ts
|
|
40733
|
-
var
|
|
41042
|
+
var import_node_fs70 = require("node:fs");
|
|
40734
41043
|
var import_node_child_process20 = require("node:child_process");
|
|
40735
41044
|
var import_node_os11 = require("node:os");
|
|
40736
|
-
var
|
|
41045
|
+
var import_node_path52 = require("node:path");
|
|
40737
41046
|
function registerLeanCommand(program2) {
|
|
40738
41047
|
const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
|
|
40739
41048
|
lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
|
|
@@ -40750,7 +41059,7 @@ function registerLeanCommand(program2) {
|
|
|
40750
41059
|
const managed = pinnedVersionDir();
|
|
40751
41060
|
const matches = version ? version.includes(pin) : false;
|
|
40752
41061
|
if (opts.json) {
|
|
40753
|
-
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0,
|
|
41062
|
+
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs70.existsSync)((0, import_node_path52.join)(managed, "bin")), asset: leanAssetName() });
|
|
40754
41063
|
return;
|
|
40755
41064
|
}
|
|
40756
41065
|
printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
|
|
@@ -40768,7 +41077,7 @@ function registerLeanCommand(program2) {
|
|
|
40768
41077
|
process.exit(2);
|
|
40769
41078
|
}
|
|
40770
41079
|
const dir = pinnedVersionDir();
|
|
40771
|
-
if ((0,
|
|
41080
|
+
if ((0, import_node_fs70.existsSync)((0, import_node_path52.join)(dir, "bin", "lake")) && !opts.force) {
|
|
40772
41081
|
printInfo(`already installed at ${dir}`);
|
|
40773
41082
|
return;
|
|
40774
41083
|
}
|
|
@@ -40804,18 +41113,18 @@ function registerLeanCommand(program2) {
|
|
|
40804
41113
|
});
|
|
40805
41114
|
lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
|
|
40806
41115
|
const dir = pinnedVersionDir();
|
|
40807
|
-
if (!(0,
|
|
41116
|
+
if (!(0, import_node_fs70.existsSync)(dir)) {
|
|
40808
41117
|
printInfo("nothing to remove");
|
|
40809
41118
|
return;
|
|
40810
41119
|
}
|
|
40811
|
-
(0,
|
|
41120
|
+
(0, import_node_fs70.rmSync)(dir, { recursive: true, force: true });
|
|
40812
41121
|
printInfo(`removed ${dir}`);
|
|
40813
41122
|
});
|
|
40814
41123
|
}
|
|
40815
41124
|
|
|
40816
41125
|
// src/cli.ts
|
|
40817
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.33.3-experimental.
|
|
40818
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.3-experimental.
|
|
41126
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.33.3-experimental.5a3f573").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) => {
|
|
41127
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.3-experimental.5a3f573");
|
|
40819
41128
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
40820
41129
|
try {
|
|
40821
41130
|
await foldLegacyLocalCredential();
|