@codacy/verity-cli 0.30.0-experimental.452ead4 → 0.30.0-experimental.5188287
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/verity.js +289 -235
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10342,6 +10342,10 @@ function repoRoot() {
|
|
|
10342
10342
|
}
|
|
10343
10343
|
return _repoRoot;
|
|
10344
10344
|
}
|
|
10345
|
+
function _resetRepoRoot() {
|
|
10346
|
+
_repoRoot = null;
|
|
10347
|
+
_mainRoot = void 0;
|
|
10348
|
+
}
|
|
10345
10349
|
var _mainRoot;
|
|
10346
10350
|
function mainWorktreeRoot() {
|
|
10347
10351
|
if (_mainRoot !== void 0) return _mainRoot;
|
|
@@ -10804,13 +10808,6 @@ function execGit(cmd) {
|
|
|
10804
10808
|
return "";
|
|
10805
10809
|
}
|
|
10806
10810
|
}
|
|
10807
|
-
function execGitArgs(args) {
|
|
10808
|
-
try {
|
|
10809
|
-
return (0, import_node_child_process3.execFileSync)("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
10810
|
-
} catch {
|
|
10811
|
-
return "";
|
|
10812
|
-
}
|
|
10813
|
-
}
|
|
10814
10811
|
function splitLines(s) {
|
|
10815
10812
|
return s.split("\n").filter((l) => l.length > 0);
|
|
10816
10813
|
}
|
|
@@ -10877,9 +10874,6 @@ function getChangedFiles() {
|
|
|
10877
10874
|
const filtered = Array.from(sets).filter((f) => !isVerityOwnedPath(f));
|
|
10878
10875
|
return { files: filtered, hasRecentCommitFiles };
|
|
10879
10876
|
}
|
|
10880
|
-
function getStagedFiles() {
|
|
10881
|
-
return splitLines(execGit("git diff --cached --name-only")).filter((f) => !isVerityOwnedPath(f));
|
|
10882
|
-
}
|
|
10883
10877
|
function getDirtyFiles() {
|
|
10884
10878
|
const set = /* @__PURE__ */ new Set();
|
|
10885
10879
|
for (const f of splitLines(execGit("git diff --name-only HEAD"))) set.add(f);
|
|
@@ -10900,33 +10894,6 @@ function showContentAtRef(ref, repoRelPath) {
|
|
|
10900
10894
|
return null;
|
|
10901
10895
|
}
|
|
10902
10896
|
}
|
|
10903
|
-
function getPushRangeFiles() {
|
|
10904
|
-
const diff = (range) => splitLines(execGitArgs(["diff", "--name-only", range])).filter((f) => !f.startsWith(".verity/") && !f.startsWith(".verity\\"));
|
|
10905
|
-
const resolvers = [
|
|
10906
|
-
() => execGitArgs(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{push}"]) ? "@{push}..HEAD" : null,
|
|
10907
|
-
() => execGitArgs(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"]) ? "@{upstream}..HEAD" : null,
|
|
10908
|
-
() => {
|
|
10909
|
-
const branch = execGitArgs(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
10910
|
-
return branch && branch !== "HEAD" && execGitArgs(["rev-parse", "--verify", "-q", `origin/${branch}`]) ? `origin/${branch}..HEAD` : null;
|
|
10911
|
-
}
|
|
10912
|
-
];
|
|
10913
|
-
for (const resolve4 of resolvers) {
|
|
10914
|
-
const range = resolve4();
|
|
10915
|
-
if (range) return { files: diff(range), range };
|
|
10916
|
-
}
|
|
10917
|
-
const baseline = readBaselineSha();
|
|
10918
|
-
if (baseline) {
|
|
10919
|
-
const files = diff(`${baseline}..HEAD`);
|
|
10920
|
-
if (files.length > 0) return { files, range: `${baseline}..HEAD` };
|
|
10921
|
-
}
|
|
10922
|
-
const last = diff("HEAD~1..HEAD");
|
|
10923
|
-
return { files: last, range: last.length > 0 ? "HEAD~1..HEAD" : null };
|
|
10924
|
-
}
|
|
10925
|
-
function getPushRangeMessages() {
|
|
10926
|
-
const { range } = getPushRangeFiles();
|
|
10927
|
-
if (!range) return "";
|
|
10928
|
-
return execGitArgs(["log", range, "--format=%B%x00"]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
|
|
10929
|
-
}
|
|
10930
10897
|
function filterAnalyzable(files) {
|
|
10931
10898
|
return files.filter((f) => {
|
|
10932
10899
|
const ext = (0, import_node_path3.extname)(f).slice(1);
|
|
@@ -13747,6 +13714,160 @@ var import_node_fs14 = require("node:fs");
|
|
|
13747
13714
|
var import_node_crypto7 = require("node:crypto");
|
|
13748
13715
|
var import_node_path13 = require("node:path");
|
|
13749
13716
|
|
|
13717
|
+
// src/lib/analysis-mode.ts
|
|
13718
|
+
var DEBUG_PHRASES = [
|
|
13719
|
+
"not working",
|
|
13720
|
+
"doesn't work",
|
|
13721
|
+
"doesn't work",
|
|
13722
|
+
"does not work",
|
|
13723
|
+
"isn't working",
|
|
13724
|
+
"is not working",
|
|
13725
|
+
"can't figure out",
|
|
13726
|
+
"stack trace"
|
|
13727
|
+
];
|
|
13728
|
+
var DEBUG_WORDS = [
|
|
13729
|
+
"fix",
|
|
13730
|
+
"bug",
|
|
13731
|
+
"broken",
|
|
13732
|
+
"crash",
|
|
13733
|
+
"crashing",
|
|
13734
|
+
"failing",
|
|
13735
|
+
"debug",
|
|
13736
|
+
"debugging",
|
|
13737
|
+
"investigate",
|
|
13738
|
+
"troubleshoot",
|
|
13739
|
+
"regression",
|
|
13740
|
+
"wrong"
|
|
13741
|
+
];
|
|
13742
|
+
var DEBUG_PATTERN = new RegExp(
|
|
13743
|
+
[
|
|
13744
|
+
...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
|
|
13745
|
+
...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
|
|
13746
|
+
].join("|"),
|
|
13747
|
+
"i"
|
|
13748
|
+
);
|
|
13749
|
+
var FALSE_POSITIVE_PATTERNS = [
|
|
13750
|
+
/\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
|
|
13751
|
+
/\berror\s+handling\b/i,
|
|
13752
|
+
/\berror\s+boundar(?:y|ies)\b/i,
|
|
13753
|
+
/\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
|
|
13754
|
+
/\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
|
|
13755
|
+
];
|
|
13756
|
+
function hasDebugIntent(prompt) {
|
|
13757
|
+
if (!DEBUG_PATTERN.test(prompt)) return false;
|
|
13758
|
+
for (const fp of FALSE_POSITIVE_PATTERNS) {
|
|
13759
|
+
if (fp.test(prompt)) return false;
|
|
13760
|
+
}
|
|
13761
|
+
return true;
|
|
13762
|
+
}
|
|
13763
|
+
var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
|
|
13764
|
+
var CODE_AUTHORING_PATTERN = /\b(add|create|implement|build|write|fix|update|change|refactor|modify|remove|delete|move|rename)\b.*\b(function|component|feature|endpoint|test|file|module|class|type|interface|hook|page|route|style|migration|code|bug|error|issue)\b/i;
|
|
13765
|
+
function isGitOnlyPrompt(prompt) {
|
|
13766
|
+
if (!GIT_ONLY_PATTERN.test(prompt)) return false;
|
|
13767
|
+
if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
|
|
13768
|
+
return true;
|
|
13769
|
+
}
|
|
13770
|
+
function reconcileAnalysisMode(predictedMode, signals) {
|
|
13771
|
+
const mode2 = resolveAnalysisMode(predictedMode, signals);
|
|
13772
|
+
if (mode2 !== "skip") return mode2;
|
|
13773
|
+
const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
|
|
13774
|
+
if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
|
|
13775
|
+
return mode2;
|
|
13776
|
+
}
|
|
13777
|
+
function resolveAnalysisMode(predictedMode, signals) {
|
|
13778
|
+
if (!predictedMode || !isValidMode(predictedMode)) {
|
|
13779
|
+
return detectAnalysisMode(
|
|
13780
|
+
signals.noFilesChanged,
|
|
13781
|
+
signals.assistantResponse,
|
|
13782
|
+
signals.conversationPrompts,
|
|
13783
|
+
signals.actionSummary,
|
|
13784
|
+
signals.sessionAuthoredCode
|
|
13785
|
+
);
|
|
13786
|
+
}
|
|
13787
|
+
const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
|
|
13788
|
+
const agentInvestigated = didAgentInvestigate(signals.actionSummary);
|
|
13789
|
+
switch (predictedMode) {
|
|
13790
|
+
case "skip":
|
|
13791
|
+
if (agentAuthoredCode) return "standard";
|
|
13792
|
+
return "skip";
|
|
13793
|
+
case "plan":
|
|
13794
|
+
if (agentAuthoredCode) return "standard";
|
|
13795
|
+
return "plan";
|
|
13796
|
+
case "debug":
|
|
13797
|
+
return "debug";
|
|
13798
|
+
case "standard":
|
|
13799
|
+
if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
|
|
13800
|
+
return agentInvestigated ? "plan" : "skip";
|
|
13801
|
+
}
|
|
13802
|
+
return "standard";
|
|
13803
|
+
}
|
|
13804
|
+
}
|
|
13805
|
+
function didAgentInvestigate(summary) {
|
|
13806
|
+
if (!summary) return false;
|
|
13807
|
+
return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
|
|
13808
|
+
}
|
|
13809
|
+
function isValidMode(mode2) {
|
|
13810
|
+
return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
|
|
13811
|
+
}
|
|
13812
|
+
function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
|
|
13813
|
+
const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
|
|
13814
|
+
if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
|
|
13815
|
+
if (!agentAuthoredCode) return "skip";
|
|
13816
|
+
}
|
|
13817
|
+
if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
|
|
13818
|
+
return "plan";
|
|
13819
|
+
}
|
|
13820
|
+
if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
|
|
13821
|
+
return didAgentInvestigate(actionSummary) ? "plan" : "skip";
|
|
13822
|
+
}
|
|
13823
|
+
for (const prompt of conversationPrompts) {
|
|
13824
|
+
if (hasDebugIntent(prompt)) {
|
|
13825
|
+
return "debug";
|
|
13826
|
+
}
|
|
13827
|
+
}
|
|
13828
|
+
return "standard";
|
|
13829
|
+
}
|
|
13830
|
+
var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
|
|
13831
|
+
var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
|
|
13832
|
+
var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
|
|
13833
|
+
var CHAIN_RE = /&&|\||;|\$\(|\x60/;
|
|
13834
|
+
function isNonAuthoringCommand(cmd) {
|
|
13835
|
+
if (typeof cmd !== "string" || cmd.trim().length === 0) return false;
|
|
13836
|
+
if (FILE_MUTATE_RE.test(cmd)) return false;
|
|
13837
|
+
if (CHAIN_RE.test(cmd)) return false;
|
|
13838
|
+
return GIT_PLUMBING_RE.test(cmd) || READ_ONLY_RE.test(cmd);
|
|
13839
|
+
}
|
|
13840
|
+
function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
|
|
13841
|
+
if (!actionSummary) return sessionAuthoredCode;
|
|
13842
|
+
if ((actionSummary.subagents ?? 0) > 0) return true;
|
|
13843
|
+
if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
|
|
13844
|
+
const commands = actionSummary.commands ?? [];
|
|
13845
|
+
if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
|
|
13846
|
+
if (sessionAuthoredCode) {
|
|
13847
|
+
const allSafe = commands.length > 0 && commands.every(isNonAuthoringCommand);
|
|
13848
|
+
if (!allSafe) return true;
|
|
13849
|
+
}
|
|
13850
|
+
return false;
|
|
13851
|
+
}
|
|
13852
|
+
function scopeToAuthored(files, actionSummary) {
|
|
13853
|
+
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
13854
|
+
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
13855
|
+
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
13856
|
+
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
13857
|
+
}
|
|
13858
|
+
function narrowToAgentAuthored(files, actionSummary) {
|
|
13859
|
+
if (!actionSummary) return files;
|
|
13860
|
+
const touched = [
|
|
13861
|
+
...actionSummary.files_edited,
|
|
13862
|
+
...actionSummary.files_created
|
|
13863
|
+
];
|
|
13864
|
+
if (touched.length === 0) return files;
|
|
13865
|
+
return files.filter((f) => {
|
|
13866
|
+
const suffix = "/" + f;
|
|
13867
|
+
return touched.some((t) => t === f || t.endsWith(suffix));
|
|
13868
|
+
});
|
|
13869
|
+
}
|
|
13870
|
+
|
|
13750
13871
|
// src/lib/skip-detection.ts
|
|
13751
13872
|
function isBareAckPrompt(prompt) {
|
|
13752
13873
|
if (typeof prompt !== "string") return false;
|
|
@@ -13810,6 +13931,15 @@ function shouldSkipForBareAck(input) {
|
|
|
13810
13931
|
if (input.turnAuthoredCode) return false;
|
|
13811
13932
|
return input.canSeeTurnAuthorship;
|
|
13812
13933
|
}
|
|
13934
|
+
function isCommandOnlyTurn(input) {
|
|
13935
|
+
if (!input.authorshipIsObservable) return false;
|
|
13936
|
+
if (input.userCommandsTruncated) return false;
|
|
13937
|
+
const commands = input.userCommands ?? [];
|
|
13938
|
+
if (commands.length === 0) return false;
|
|
13939
|
+
if (input.agentAuthoredFiles > 0) return false;
|
|
13940
|
+
if (input.agentToolCalls > 0) return false;
|
|
13941
|
+
return commands.every(isNonAuthoringCommand);
|
|
13942
|
+
}
|
|
13813
13943
|
|
|
13814
13944
|
// src/lib/pending-repeat.ts
|
|
13815
13945
|
var STOP = /* @__PURE__ */ new Set([
|
|
@@ -16949,6 +17079,10 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
|
|
|
16949
17079
|
dir = (0, import_node_path18.isAbsolute)(expanded) ? expanded : (0, import_node_path18.resolve)(dir, expanded);
|
|
16950
17080
|
}
|
|
16951
17081
|
const seg = segments[segmentIndex];
|
|
17082
|
+
const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
|
|
17083
|
+
if (overrideMatch) {
|
|
17084
|
+
return { dir: null, named: true, unresolvable: `git-dir/work-tree/index override in command: ${overrideMatch[0].trim()}` };
|
|
17085
|
+
}
|
|
16952
17086
|
const gitMatch = seg.match(new RegExp(`(?:^|[\\s;&|(])(?:[^\\s;&|()'"]*\\/)?git(${GIT_GLOBAL_OPTS})\\s`));
|
|
16953
17087
|
if (gitMatch) {
|
|
16954
17088
|
const optsRegion = gitMatch[1] ?? "";
|
|
@@ -17040,14 +17174,22 @@ function resolveFrame(input) {
|
|
|
17040
17174
|
});
|
|
17041
17175
|
let dir = baseDir;
|
|
17042
17176
|
if (found) {
|
|
17043
|
-
const
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
if (
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17177
|
+
const segments = splitSegments(input.command);
|
|
17178
|
+
const kindRes = found.moment === "pre-commit" ? [COMMIT_RE] : [PUSH_RE, GH_PR_RE];
|
|
17179
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
17180
|
+
for (let i = 0; i < segments.length; i++) {
|
|
17181
|
+
if (/--dry-run\b/.test(segments[i])) continue;
|
|
17182
|
+
if (!kindRes.some((re) => re.test(segments[i]))) continue;
|
|
17183
|
+
const target = extractCommandTarget(input.command, i, baseDir);
|
|
17184
|
+
if (target.named) anchor = "command-target";
|
|
17185
|
+
if (target.unresolvable) return refuse(`target:${target.unresolvable}`);
|
|
17186
|
+
dirs.add(target.dir ?? baseDir);
|
|
17187
|
+
}
|
|
17188
|
+
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
17189
|
+
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
17190
|
+
if (targetDir !== baseDir) {
|
|
17191
|
+
if (!(0, import_node_fs20.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
17192
|
+
dir = targetDir;
|
|
17051
17193
|
}
|
|
17052
17194
|
}
|
|
17053
17195
|
const toplevel = gitAt(dir, ["rev-parse", "--show-toplevel"]);
|
|
@@ -17148,6 +17290,10 @@ function rangeFiles(frame, range) {
|
|
|
17148
17290
|
}
|
|
17149
17291
|
return out.split("\n").filter((l) => l.length > 0).filter((f) => !isVerityOwnedPath(f));
|
|
17150
17292
|
}
|
|
17293
|
+
function rangeMessages(frame, range) {
|
|
17294
|
+
if (range.kind === "staged" || range.kind === "nothing" || !range.base) return "";
|
|
17295
|
+
return frameGit(frame, ["log", `${range.base}..${range.head === "INDEX" ? "HEAD" : range.head}`, "--format=%B%x00"]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
|
|
17296
|
+
}
|
|
17151
17297
|
function frameTelemetry(frame, range, divergence) {
|
|
17152
17298
|
const t = {
|
|
17153
17299
|
anchor: frame.anchor,
|
|
@@ -17204,6 +17350,8 @@ var MAX_COMMAND_CHARS = 80;
|
|
|
17204
17350
|
var MAX_TOOL_BLOCKS = 200;
|
|
17205
17351
|
var MAX_SUMMARY_BYTES = 4096;
|
|
17206
17352
|
var HOME = process.env.HOME ?? "";
|
|
17353
|
+
var BASH_INPUT_RE = /^\s*<bash-input>([\s\S]*?)<\/bash-input>/;
|
|
17354
|
+
var BASH_ECHO_RE = /^\s*<bash-(?:stdout|stderr)>/;
|
|
17207
17355
|
async function extractActionSummary(transcriptPath) {
|
|
17208
17356
|
try {
|
|
17209
17357
|
const read = readTurnLines(transcriptPath);
|
|
@@ -17267,7 +17415,7 @@ function isRealUserMessage(parsed) {
|
|
|
17267
17415
|
const message = parsed.message;
|
|
17268
17416
|
if (!message) return false;
|
|
17269
17417
|
const content = message.content;
|
|
17270
|
-
if (typeof content === "string") return
|
|
17418
|
+
if (typeof content === "string") return !BASH_ECHO_RE.test(content);
|
|
17271
17419
|
if (Array.isArray(content)) {
|
|
17272
17420
|
return content.some((b) => {
|
|
17273
17421
|
if (typeof b !== "object" || b === null) return false;
|
|
@@ -17282,6 +17430,8 @@ function buildSummary(lines) {
|
|
|
17282
17430
|
const filesEdited = /* @__PURE__ */ new Set();
|
|
17283
17431
|
const filesCreated = /* @__PURE__ */ new Set();
|
|
17284
17432
|
const commands = [];
|
|
17433
|
+
const userCommands = [];
|
|
17434
|
+
let userCommandsTruncated = false;
|
|
17285
17435
|
let searches = 0;
|
|
17286
17436
|
let subagents = 0;
|
|
17287
17437
|
let webFetches = 0;
|
|
@@ -17299,6 +17449,17 @@ function buildSummary(lines) {
|
|
|
17299
17449
|
if (entry.type === "user" && !firstTimestamp) {
|
|
17300
17450
|
firstTimestamp = entry.timestamp ?? null;
|
|
17301
17451
|
}
|
|
17452
|
+
if (entry.type === "user") {
|
|
17453
|
+
const typed = userTypedCommands(entry);
|
|
17454
|
+
if (typed.truncated) userCommandsTruncated = true;
|
|
17455
|
+
for (const cmd of typed.commands) {
|
|
17456
|
+
if (userCommands.length >= MAX_COMMANDS) {
|
|
17457
|
+
userCommandsTruncated = true;
|
|
17458
|
+
break;
|
|
17459
|
+
}
|
|
17460
|
+
userCommands.push(cmd);
|
|
17461
|
+
}
|
|
17462
|
+
}
|
|
17302
17463
|
if (entry.type !== "assistant") continue;
|
|
17303
17464
|
turnMessages++;
|
|
17304
17465
|
lastTimestamp = entry.timestamp ?? lastTimestamp;
|
|
@@ -17376,6 +17537,8 @@ function buildSummary(lines) {
|
|
|
17376
17537
|
],
|
|
17377
17538
|
searches,
|
|
17378
17539
|
commands,
|
|
17540
|
+
user_commands: userCommands,
|
|
17541
|
+
...userCommandsTruncated ? { user_commands_truncated: true } : {},
|
|
17379
17542
|
subagents,
|
|
17380
17543
|
web_fetches: webFetches,
|
|
17381
17544
|
total_tool_calls: totalToolCalls,
|
|
@@ -17384,6 +17547,8 @@ function buildSummary(lines) {
|
|
|
17384
17547
|
};
|
|
17385
17548
|
if (JSON.stringify(summary).length > MAX_SUMMARY_BYTES) {
|
|
17386
17549
|
summary.commands = [];
|
|
17550
|
+
summary.user_commands = [];
|
|
17551
|
+
summary.user_commands_truncated = true;
|
|
17387
17552
|
if (JSON.stringify(summary).length > MAX_SUMMARY_BYTES) {
|
|
17388
17553
|
summary.files_read = summary.files_read.slice(0, 10);
|
|
17389
17554
|
summary.files_edited = summary.files_edited.slice(0, 10);
|
|
@@ -17401,6 +17566,22 @@ function addPath(set, rawPath) {
|
|
|
17401
17566
|
if (p.length > 200) p = p.slice(0, 200);
|
|
17402
17567
|
set.add(p);
|
|
17403
17568
|
}
|
|
17569
|
+
function userTypedCommands(entry) {
|
|
17570
|
+
const none = { commands: [], truncated: false };
|
|
17571
|
+
const message = entry.message;
|
|
17572
|
+
const content = message?.content;
|
|
17573
|
+
if (typeof content !== "string") return none;
|
|
17574
|
+
const m = BASH_INPUT_RE.exec(content);
|
|
17575
|
+
if (!m) return none;
|
|
17576
|
+
const commands = [];
|
|
17577
|
+
let truncated = false;
|
|
17578
|
+
for (const line of m[1].split("\n")) {
|
|
17579
|
+
if (line.length > MAX_COMMAND_CHARS) truncated = true;
|
|
17580
|
+
const cmd = sanitizeCommand(line);
|
|
17581
|
+
if (cmd) commands.push(cmd);
|
|
17582
|
+
}
|
|
17583
|
+
return { commands, truncated };
|
|
17584
|
+
}
|
|
17404
17585
|
function sanitizeCommand(rawCmd) {
|
|
17405
17586
|
if (typeof rawCmd !== "string" || !rawCmd) return null;
|
|
17406
17587
|
let cmd = rawCmd.split("\n")[0];
|
|
@@ -17635,7 +17816,7 @@ function truncateToCap(text) {
|
|
|
17635
17816
|
function buildHookOutput(gateDecision, systemMessage, agentContext) {
|
|
17636
17817
|
return {
|
|
17637
17818
|
gate_decision: gateDecision,
|
|
17638
|
-
systemMessage,
|
|
17819
|
+
...systemMessage === null ? {} : { systemMessage },
|
|
17639
17820
|
...agentContext ? {
|
|
17640
17821
|
hookSpecificOutput: {
|
|
17641
17822
|
hookEventName: "Stop",
|
|
@@ -17656,7 +17837,7 @@ function channelSilence(input) {
|
|
|
17656
17837
|
// src/lib/cli-version.ts
|
|
17657
17838
|
function cliVersion() {
|
|
17658
17839
|
try {
|
|
17659
|
-
return true ? "0.30.0-experimental.
|
|
17840
|
+
return true ? "0.30.0-experimental.5188287" : "dev";
|
|
17660
17841
|
} catch {
|
|
17661
17842
|
return "dev";
|
|
17662
17843
|
}
|
|
@@ -17942,6 +18123,7 @@ async function passAndExit(run, reason, skip, kindOverride) {
|
|
|
17942
18123
|
"verity-command",
|
|
17943
18124
|
"bare-acknowledgment",
|
|
17944
18125
|
"reflection-prompt",
|
|
18126
|
+
"command-only-turn",
|
|
17945
18127
|
"skip-mode",
|
|
17946
18128
|
"zero-increment",
|
|
17947
18129
|
"debounce",
|
|
@@ -17960,10 +18142,12 @@ async function passAndExit(run, reason, skip, kindOverride) {
|
|
|
17960
18142
|
}
|
|
17961
18143
|
const AGENT_SILENT_SKIPS = /* @__PURE__ */ new Set([]);
|
|
17962
18144
|
const agentNote = AGENT_SILENT_SKIPS.has(skip) ? null : note;
|
|
18145
|
+
const HUMAN_SILENT_SKIPS = /* @__PURE__ */ new Set(["command-only-turn"]);
|
|
18146
|
+
const humanNote = HUMAN_SILENT_SKIPS.has(skip) ? null : `Verity: ${reason}`;
|
|
17963
18147
|
printJsonCompact(
|
|
17964
18148
|
buildHookOutput(
|
|
17965
18149
|
verdict,
|
|
17966
|
-
|
|
18150
|
+
humanNote,
|
|
17967
18151
|
// `additionalContext` is the agent's ONLY input. Writing only
|
|
17968
18152
|
// `systemMessage` — the human's field — tells the agent nothing at all,
|
|
17969
18153
|
// which is what sixteen of the nineteen terminating paths used to do.
|
|
@@ -18113,6 +18297,15 @@ function discoverPlans() {
|
|
|
18113
18297
|
// src/commands/analyze/phases/03-intent-inputs.ts
|
|
18114
18298
|
async function intentInputs(run) {
|
|
18115
18299
|
const { actionSummary, allForReview, assistantResponse, baseline, baselineSessionId } = run;
|
|
18300
|
+
if (isCommandOnlyTurn({
|
|
18301
|
+
userCommands: actionSummary?.user_commands,
|
|
18302
|
+
userCommandsTruncated: actionSummary?.user_commands_truncated,
|
|
18303
|
+
agentAuthoredFiles: (actionSummary?.files_edited.length ?? 0) + (actionSummary?.files_created.length ?? 0),
|
|
18304
|
+
agentToolCalls: actionSummary?.total_tool_calls ?? 0,
|
|
18305
|
+
authorshipIsObservable: !!actionSummary && actionSummary.transcript_windowed !== "orphaned"
|
|
18306
|
+
})) {
|
|
18307
|
+
await passAndExit(run, "User command only \u2014 skipping analysis", "command-only-turn");
|
|
18308
|
+
}
|
|
18116
18309
|
const conversation = await readAndClearConversationBuffer(baselineSessionId);
|
|
18117
18310
|
const specs = discoverSpecs(actionSummary?.files_read ?? []);
|
|
18118
18311
|
const plans = discoverPlans();
|
|
@@ -18153,156 +18346,6 @@ async function connect(run) {
|
|
|
18153
18346
|
Object.assign(run, { urlResult, serviceUrl: urlResult.data, token: tokenResult.data.token });
|
|
18154
18347
|
}
|
|
18155
18348
|
|
|
18156
|
-
// src/lib/analysis-mode.ts
|
|
18157
|
-
var DEBUG_PHRASES = [
|
|
18158
|
-
"not working",
|
|
18159
|
-
"doesn't work",
|
|
18160
|
-
"doesn't work",
|
|
18161
|
-
"does not work",
|
|
18162
|
-
"isn't working",
|
|
18163
|
-
"is not working",
|
|
18164
|
-
"can't figure out",
|
|
18165
|
-
"stack trace"
|
|
18166
|
-
];
|
|
18167
|
-
var DEBUG_WORDS = [
|
|
18168
|
-
"fix",
|
|
18169
|
-
"bug",
|
|
18170
|
-
"broken",
|
|
18171
|
-
"crash",
|
|
18172
|
-
"crashing",
|
|
18173
|
-
"failing",
|
|
18174
|
-
"debug",
|
|
18175
|
-
"debugging",
|
|
18176
|
-
"investigate",
|
|
18177
|
-
"troubleshoot",
|
|
18178
|
-
"regression",
|
|
18179
|
-
"wrong"
|
|
18180
|
-
];
|
|
18181
|
-
var DEBUG_PATTERN = new RegExp(
|
|
18182
|
-
[
|
|
18183
|
-
...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
|
|
18184
|
-
...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
|
|
18185
|
-
].join("|"),
|
|
18186
|
-
"i"
|
|
18187
|
-
);
|
|
18188
|
-
var FALSE_POSITIVE_PATTERNS = [
|
|
18189
|
-
/\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
|
|
18190
|
-
/\berror\s+handling\b/i,
|
|
18191
|
-
/\berror\s+boundar(?:y|ies)\b/i,
|
|
18192
|
-
/\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
|
|
18193
|
-
/\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
|
|
18194
|
-
];
|
|
18195
|
-
function hasDebugIntent(prompt) {
|
|
18196
|
-
if (!DEBUG_PATTERN.test(prompt)) return false;
|
|
18197
|
-
for (const fp of FALSE_POSITIVE_PATTERNS) {
|
|
18198
|
-
if (fp.test(prompt)) return false;
|
|
18199
|
-
}
|
|
18200
|
-
return true;
|
|
18201
|
-
}
|
|
18202
|
-
var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
|
|
18203
|
-
var CODE_AUTHORING_PATTERN = /\b(add|create|implement|build|write|fix|update|change|refactor|modify|remove|delete|move|rename)\b.*\b(function|component|feature|endpoint|test|file|module|class|type|interface|hook|page|route|style|migration|code|bug|error|issue)\b/i;
|
|
18204
|
-
function isGitOnlyPrompt(prompt) {
|
|
18205
|
-
if (!GIT_ONLY_PATTERN.test(prompt)) return false;
|
|
18206
|
-
if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
|
|
18207
|
-
return true;
|
|
18208
|
-
}
|
|
18209
|
-
function reconcileAnalysisMode(predictedMode, signals) {
|
|
18210
|
-
const mode2 = resolveAnalysisMode(predictedMode, signals);
|
|
18211
|
-
if (mode2 !== "skip") return mode2;
|
|
18212
|
-
const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
|
|
18213
|
-
if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
|
|
18214
|
-
return mode2;
|
|
18215
|
-
}
|
|
18216
|
-
function resolveAnalysisMode(predictedMode, signals) {
|
|
18217
|
-
if (!predictedMode || !isValidMode(predictedMode)) {
|
|
18218
|
-
return detectAnalysisMode(
|
|
18219
|
-
signals.noFilesChanged,
|
|
18220
|
-
signals.assistantResponse,
|
|
18221
|
-
signals.conversationPrompts,
|
|
18222
|
-
signals.actionSummary,
|
|
18223
|
-
signals.sessionAuthoredCode
|
|
18224
|
-
);
|
|
18225
|
-
}
|
|
18226
|
-
const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
|
|
18227
|
-
const agentInvestigated = didAgentInvestigate(signals.actionSummary);
|
|
18228
|
-
switch (predictedMode) {
|
|
18229
|
-
case "skip":
|
|
18230
|
-
if (agentAuthoredCode) return "standard";
|
|
18231
|
-
return "skip";
|
|
18232
|
-
case "plan":
|
|
18233
|
-
if (agentAuthoredCode) return "standard";
|
|
18234
|
-
return "plan";
|
|
18235
|
-
case "debug":
|
|
18236
|
-
return "debug";
|
|
18237
|
-
case "standard":
|
|
18238
|
-
if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
|
|
18239
|
-
return agentInvestigated ? "plan" : "skip";
|
|
18240
|
-
}
|
|
18241
|
-
return "standard";
|
|
18242
|
-
}
|
|
18243
|
-
}
|
|
18244
|
-
function didAgentInvestigate(summary) {
|
|
18245
|
-
if (!summary) return false;
|
|
18246
|
-
return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
|
|
18247
|
-
}
|
|
18248
|
-
function isValidMode(mode2) {
|
|
18249
|
-
return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
|
|
18250
|
-
}
|
|
18251
|
-
function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
|
|
18252
|
-
const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
|
|
18253
|
-
if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
|
|
18254
|
-
if (!agentAuthoredCode) return "skip";
|
|
18255
|
-
}
|
|
18256
|
-
if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
|
|
18257
|
-
return "plan";
|
|
18258
|
-
}
|
|
18259
|
-
if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
|
|
18260
|
-
return didAgentInvestigate(actionSummary) ? "plan" : "skip";
|
|
18261
|
-
}
|
|
18262
|
-
for (const prompt of conversationPrompts) {
|
|
18263
|
-
if (hasDebugIntent(prompt)) {
|
|
18264
|
-
return "debug";
|
|
18265
|
-
}
|
|
18266
|
-
}
|
|
18267
|
-
return "standard";
|
|
18268
|
-
}
|
|
18269
|
-
var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
|
|
18270
|
-
var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
|
|
18271
|
-
var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
|
|
18272
|
-
var CHAIN_RE = /&&|\||;|\$\(|\x60/;
|
|
18273
|
-
function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
|
|
18274
|
-
if (!actionSummary) return sessionAuthoredCode;
|
|
18275
|
-
if ((actionSummary.subagents ?? 0) > 0) return true;
|
|
18276
|
-
if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
|
|
18277
|
-
const commands = actionSummary.commands ?? [];
|
|
18278
|
-
if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
|
|
18279
|
-
if (sessionAuthoredCode) {
|
|
18280
|
-
const allSafe = commands.length > 0 && commands.every(
|
|
18281
|
-
(c) => !CHAIN_RE.test(c) && (GIT_PLUMBING_RE.test(c) || READ_ONLY_RE.test(c))
|
|
18282
|
-
);
|
|
18283
|
-
if (!allSafe) return true;
|
|
18284
|
-
}
|
|
18285
|
-
return false;
|
|
18286
|
-
}
|
|
18287
|
-
function scopeToAuthored(files, actionSummary) {
|
|
18288
|
-
if (!actionSummary) return { files, signal: "no-transcript" };
|
|
18289
|
-
const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
|
|
18290
|
-
if (touched.length === 0) return { files: [], signal: "none-authored" };
|
|
18291
|
-
return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
|
|
18292
|
-
}
|
|
18293
|
-
function narrowToAgentAuthored(files, actionSummary) {
|
|
18294
|
-
if (!actionSummary) return files;
|
|
18295
|
-
const touched = [
|
|
18296
|
-
...actionSummary.files_edited,
|
|
18297
|
-
...actionSummary.files_created
|
|
18298
|
-
];
|
|
18299
|
-
if (touched.length === 0) return files;
|
|
18300
|
-
return files.filter((f) => {
|
|
18301
|
-
const suffix = "/" + f;
|
|
18302
|
-
return touched.some((t) => t === f || t.endsWith(suffix));
|
|
18303
|
-
});
|
|
18304
|
-
}
|
|
18305
|
-
|
|
18306
18349
|
// src/commands/analyze/phases/05-mode.ts
|
|
18307
18350
|
async function mode(run) {
|
|
18308
18351
|
const { opts, globals } = run;
|
|
@@ -20155,7 +20198,10 @@ async function buildRequest(run) {
|
|
|
20155
20198
|
}
|
|
20156
20199
|
if (specs.length > 0) intentContext.specs = specs;
|
|
20157
20200
|
if (plans.length > 0) intentContext.plans = plans;
|
|
20158
|
-
if (actionSummary)
|
|
20201
|
+
if (actionSummary) {
|
|
20202
|
+
const { user_commands: _uc, user_commands_truncated: _uct, ...onTheWire } = actionSummary;
|
|
20203
|
+
intentContext.action_summary = onTheWire;
|
|
20204
|
+
}
|
|
20159
20205
|
for (const key of Object.keys(intentContext)) {
|
|
20160
20206
|
if (intentContext[key] == null) delete intentContext[key];
|
|
20161
20207
|
}
|
|
@@ -21210,9 +21256,14 @@ function registerGuardCommand(program2) {
|
|
|
21210
21256
|
}
|
|
21211
21257
|
});
|
|
21212
21258
|
}
|
|
21213
|
-
function
|
|
21214
|
-
|
|
21215
|
-
|
|
21259
|
+
function resolveMomentRange(moment, frame, command, on) {
|
|
21260
|
+
return moment === "pre-commit" ? stagedRange() : resolvePushRange(frame, command, on);
|
|
21261
|
+
}
|
|
21262
|
+
function describeRange(range) {
|
|
21263
|
+
if (range.kind === "staged") return "staged";
|
|
21264
|
+
if (range.kind === "nothing" || !range.base) return null;
|
|
21265
|
+
const base = /^[0-9a-f]{40}$/.test(range.base) ? range.base.slice(0, 7) : range.base;
|
|
21266
|
+
return `${base}..${range.head} via ${range.via}`;
|
|
21216
21267
|
}
|
|
21217
21268
|
function matchFlagValue(command, flags) {
|
|
21218
21269
|
const re = new RegExp(`(?<![\\w-])(?:${flags})(?:=|\\s+)('((?:[^'\\\\]|\\\\.)*)'|"((?:[^"\\\\]|\\\\.)*)"|([^\\s'"-][^\\s]*))`);
|
|
@@ -21247,15 +21298,15 @@ function isSubstantiveIntent(text) {
|
|
|
21247
21298
|
if (SHELL_PLUMBING.test(t)) return false;
|
|
21248
21299
|
return true;
|
|
21249
21300
|
}
|
|
21250
|
-
function extractStatedIntent(moment, command) {
|
|
21251
|
-
const text = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ??
|
|
21301
|
+
function extractStatedIntent(moment, command, pushedMessages = null) {
|
|
21302
|
+
const text = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
|
|
21252
21303
|
return isSubstantiveIntent(text) ? text : null;
|
|
21253
21304
|
}
|
|
21254
21305
|
function hasBlockingFinding(response) {
|
|
21255
21306
|
const findings = response.findings ?? [];
|
|
21256
21307
|
return findings.some((f) => f.scope !== "pre-existing" && ["critical", "high"].includes((f.severity ?? "").toLowerCase()));
|
|
21257
21308
|
}
|
|
21258
|
-
function buildGuardRequest(moment, files, codeDelta, iter, sessionId,
|
|
21309
|
+
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
21259
21310
|
const analyzable = filterAnalyzable(files);
|
|
21260
21311
|
const securityFiles = filterSecurity(files);
|
|
21261
21312
|
let staticResults;
|
|
@@ -21284,7 +21335,6 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, command, c
|
|
|
21284
21335
|
if (coverageTelemetry) requestBody.coverage_telemetry = coverageTelemetry;
|
|
21285
21336
|
const specs = discoverSpecs();
|
|
21286
21337
|
const plans = discoverPlans();
|
|
21287
|
-
const statedIntent = extractStatedIntent(moment, command);
|
|
21288
21338
|
if (specs.length > 0 || plans.length > 0 || statedIntent) {
|
|
21289
21339
|
const intentContext = {};
|
|
21290
21340
|
if (statedIntent) intentContext.user_prompt = statedIntent;
|
|
@@ -21294,7 +21344,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, command, c
|
|
|
21294
21344
|
}
|
|
21295
21345
|
return requestBody;
|
|
21296
21346
|
}
|
|
21297
|
-
function buildGuardCoverage(files, codeDelta, frame, frameRange
|
|
21347
|
+
function buildGuardCoverage(files, codeDelta, frame, frameRange) {
|
|
21298
21348
|
const byReason = {};
|
|
21299
21349
|
for (const e of codeDelta.excluded) byReason[e.reason] = (byReason[e.reason] ?? 0) + 1;
|
|
21300
21350
|
return {
|
|
@@ -21308,11 +21358,7 @@ function buildGuardCoverage(files, codeDelta, frame, frameRange, frameFiles, act
|
|
|
21308
21358
|
excluded: codeDelta.excluded.length,
|
|
21309
21359
|
excluded_by_reason: byReason,
|
|
21310
21360
|
transcript_windowed: null,
|
|
21311
|
-
guard_frame: frameTelemetry(frame, frameRange
|
|
21312
|
-
actualRoot,
|
|
21313
|
-
actualFiles: files,
|
|
21314
|
-
frameFiles
|
|
21315
|
-
})
|
|
21361
|
+
guard_frame: frameTelemetry(frame, frameRange)
|
|
21316
21362
|
};
|
|
21317
21363
|
}
|
|
21318
21364
|
function coverageSummary(c) {
|
|
@@ -21341,15 +21387,24 @@ function emitAllowNotice(userMsg, agentMsg) {
|
|
|
21341
21387
|
async function runGuard(opts, globals) {
|
|
21342
21388
|
const on = opts.on.split(",").map((s) => s.trim()).filter((s) => s === "commit" || s === "push");
|
|
21343
21389
|
const { command, cwd, sessionId } = await readPreToolUseStdin();
|
|
21344
|
-
if (cwd && (0, import_node_fs35.existsSync)(cwd)) {
|
|
21345
|
-
try {
|
|
21346
|
-
process.chdir(cwd);
|
|
21347
|
-
} catch {
|
|
21348
|
-
}
|
|
21349
|
-
}
|
|
21350
21390
|
const moment = classifyCommand(command, on);
|
|
21351
21391
|
if (!moment) process.exit(0);
|
|
21352
21392
|
const verb = moment === "pre-commit" ? "commit" : "push";
|
|
21393
|
+
const { frame } = resolveFrame({ command, on, hookCwd: cwd });
|
|
21394
|
+
if (frame.refusal || !frame.worktreeRoot) {
|
|
21395
|
+
logEvent("guard_frame", { moment, ...frameTelemetry(frame, null) });
|
|
21396
|
+
if ((frame.refusal ?? "").startsWith("anchor:")) process.exit(0);
|
|
21397
|
+
emitAllowNotice(
|
|
21398
|
+
`\u26A0 Verity ${moment}: could not resolve the tree this ${verb} targets \u2014 ${verb}ed WITHOUT review`,
|
|
21399
|
+
`Verity ${moment}: the target tree could not be resolved (${frame.refusal}); the ${verb} was allowed WITHOUT a Verity review.`
|
|
21400
|
+
);
|
|
21401
|
+
}
|
|
21402
|
+
try {
|
|
21403
|
+
process.chdir(frame.worktreeRoot);
|
|
21404
|
+
} catch {
|
|
21405
|
+
process.exit(0);
|
|
21406
|
+
}
|
|
21407
|
+
_resetRepoRoot();
|
|
21353
21408
|
const iter = readIter(moment);
|
|
21354
21409
|
if (iter >= GUARD_BLOCK_CAP) {
|
|
21355
21410
|
resetIter(moment);
|
|
@@ -21358,36 +21413,35 @@ async function runGuard(opts, globals) {
|
|
|
21358
21413
|
`Verity ${moment}: review-cycle cap (${GUARD_BLOCK_CAP}) reached; the ${verb} was allowed without a further block.`
|
|
21359
21414
|
);
|
|
21360
21415
|
}
|
|
21361
|
-
const
|
|
21416
|
+
const range = resolveMomentRange(moment, frame, command, on);
|
|
21417
|
+
const files = rangeFiles(frame, range);
|
|
21362
21418
|
if (files.length === 0) process.exit(0);
|
|
21363
21419
|
const tokenResult = await resolveToken(globals.token);
|
|
21364
21420
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
21365
21421
|
if (!tokenResult.ok || !urlResult.ok) process.exit(0);
|
|
21366
|
-
|
|
21367
|
-
const frameRange = moment === "pre-push" ? resolvePushRange(frame, command, on) : stagedRange();
|
|
21368
|
-
const frameFiles = frame.refusal ? [] : rangeFiles(frame, frameRange);
|
|
21369
|
-
const actualRoot = repoRoot();
|
|
21370
|
-
logEvent("guard_frame", {
|
|
21371
|
-
moment,
|
|
21372
|
-
...frameTelemetry(frame, frameRange, { actualRoot, actualFiles: files, frameFiles })
|
|
21373
|
-
});
|
|
21422
|
+
logEvent("guard_frame", { moment, ...frameTelemetry(frame, range) });
|
|
21374
21423
|
const codeDelta = collectCodeDelta(files);
|
|
21375
21424
|
if (codeDelta.total_files === 0) process.exit(0);
|
|
21425
|
+
const statedIntent = extractStatedIntent(
|
|
21426
|
+
moment,
|
|
21427
|
+
command,
|
|
21428
|
+
moment === "pre-push" ? rangeMessages(frame, range) || null : null
|
|
21429
|
+
);
|
|
21376
21430
|
const requestBody = buildGuardRequest(
|
|
21377
21431
|
moment,
|
|
21378
21432
|
files,
|
|
21379
21433
|
codeDelta,
|
|
21380
21434
|
iter,
|
|
21381
21435
|
sessionId,
|
|
21382
|
-
|
|
21383
|
-
buildGuardCoverage(files, codeDelta, frame,
|
|
21436
|
+
statedIntent,
|
|
21437
|
+
buildGuardCoverage(files, codeDelta, frame, range)
|
|
21384
21438
|
);
|
|
21385
21439
|
const coverage = {
|
|
21386
21440
|
moment,
|
|
21387
|
-
root:
|
|
21388
|
-
branch: frame.
|
|
21441
|
+
root: frame.worktreeRoot,
|
|
21442
|
+
branch: frame.branch,
|
|
21389
21443
|
linked: frame.isLinkedWorktree,
|
|
21390
|
-
range:
|
|
21444
|
+
range: describeRange(range),
|
|
21391
21445
|
sent: codeDelta.files.map((f) => f.path),
|
|
21392
21446
|
excluded: codeDelta.excluded.map((e) => ({ path: e.path, reason: e.reason }))
|
|
21393
21447
|
};
|
|
@@ -22811,8 +22865,8 @@ function registerTelemetryCommands(program2) {
|
|
|
22811
22865
|
}
|
|
22812
22866
|
|
|
22813
22867
|
// src/cli.ts
|
|
22814
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.30.0-experimental.
|
|
22815
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.30.0-experimental.
|
|
22868
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.30.0-experimental.5188287").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) => {
|
|
22869
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.30.0-experimental.5188287");
|
|
22816
22870
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
22817
22871
|
try {
|
|
22818
22872
|
await foldLegacyLocalCredential();
|
package/package.json
CHANGED