auto-mode 2.0.2 → 3.0.1
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/dist/{classify-edit-C-CQMndB.js → classify-edit-B660kX2I.js} +74 -72
- package/dist/cli.js +98 -98
- package/dist/{get-edit-fields-BtAvHIsq.js → find-edit-fields-CzkhPA4j.js} +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{parse-action-request-CPpuEqFq.js → parse-action-request-CaQy7FA3.js} +1175 -406
- package/dist/{start-judge-server-D-zcMyFZ.js → start-judge-server-BlhDO_4A.js} +18 -18
- package/dist/start-judge-session-B-KYQG13.js +1 -0
- package/dist/{start-judge-session-DX3Oek85.js → start-judge-session-vxiG-kDp.js} +39 -39
- package/package.json +8 -7
- package/policy/judge.md +2 -0
- package/dist/start-judge-session-DOkwKT_N.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { t as findEditFields } from "./find-edit-fields-CzkhPA4j.js";
|
|
2
2
|
import { basename, relative, sep } from "node:path";
|
|
3
3
|
import { Buffer } from "node:buffer";
|
|
4
4
|
//#region node_modules/.bun/re2js@2.8.6/node_modules/re2js/build/index.js
|
|
@@ -6362,15 +6362,15 @@ var RE2JS = class RE2JS {
|
|
|
6362
6362
|
}
|
|
6363
6363
|
};
|
|
6364
6364
|
//#endregion
|
|
6365
|
-
//#region src/secrets/
|
|
6366
|
-
const
|
|
6367
|
-
source: {
|
|
6365
|
+
//#region src/secrets/betterleaks-rules.ts
|
|
6366
|
+
const BETTERLEAKS_RULES = {
|
|
6367
|
+
"source": {
|
|
6368
6368
|
"repository": "https://github.com/betterleaks/betterleaks",
|
|
6369
6369
|
"version": "v1.9.0",
|
|
6370
6370
|
"commit": "81aff7a638638aae3a659845d089043e1d8fe9ac"
|
|
6371
6371
|
},
|
|
6372
|
-
notice: "MIT License\n\nCopyright (c) 2026 Zachary Rice\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",
|
|
6373
|
-
prefilter: [
|
|
6372
|
+
"notice": "MIT License\n\nCopyright (c) 2026 Zachary Rice\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",
|
|
6373
|
+
"prefilter": [
|
|
6374
6374
|
{
|
|
6375
6375
|
"source": "gitleaks\\.toml",
|
|
6376
6376
|
"flags": "",
|
|
@@ -6497,7 +6497,7 @@ const RULE_SET$1 = {
|
|
|
6497
6497
|
"engine": "js"
|
|
6498
6498
|
}
|
|
6499
6499
|
],
|
|
6500
|
-
filter: [{
|
|
6500
|
+
"filter": [{
|
|
6501
6501
|
"kind": "matches",
|
|
6502
6502
|
"field": "secret",
|
|
6503
6503
|
"patterns": [
|
|
@@ -6574,7 +6574,7 @@ const RULE_SET$1 = {
|
|
|
6574
6574
|
"values": ["abcdefghijklmnopqrstuvwxyz", "014df517-39d1-4453-b7b3-9930c563627c"],
|
|
6575
6575
|
"negate": false
|
|
6576
6576
|
}],
|
|
6577
|
-
rules: [
|
|
6577
|
+
"rules": [
|
|
6578
6578
|
{
|
|
6579
6579
|
"id": "1password-secret-key",
|
|
6580
6580
|
"pattern": {
|
|
@@ -16875,7 +16875,7 @@ const RULE_SET$1 = {
|
|
|
16875
16875
|
"report": true
|
|
16876
16876
|
}
|
|
16877
16877
|
],
|
|
16878
|
-
unported: [
|
|
16878
|
+
"unported": [
|
|
16879
16879
|
{
|
|
16880
16880
|
"rule": "adafruit-api-key",
|
|
16881
16881
|
"part": "tokenRatio"
|
|
@@ -17570,8 +17570,10 @@ const RULE_SET$1 = {
|
|
|
17570
17570
|
}
|
|
17571
17571
|
]
|
|
17572
17572
|
};
|
|
17573
|
+
//#endregion
|
|
17574
|
+
//#region src/secrets/get-secret-rule-set.ts
|
|
17573
17575
|
function getSecretRuleSet() {
|
|
17574
|
-
return
|
|
17576
|
+
return BETTERLEAKS_RULES;
|
|
17575
17577
|
}
|
|
17576
17578
|
//#endregion
|
|
17577
17579
|
//#region src/secrets/find-secret.ts
|
|
@@ -17587,6 +17589,25 @@ function findSecret(content, rules = REPORTED_RULES) {
|
|
|
17587
17589
|
}
|
|
17588
17590
|
return null;
|
|
17589
17591
|
}
|
|
17592
|
+
function hasPatternMatch(pattern, text) {
|
|
17593
|
+
return pattern.engine === "re2" ? getRE2(pattern).matcher(text).find() : getRegExp(pattern).test(text);
|
|
17594
|
+
}
|
|
17595
|
+
const compiledRE2 = /* @__PURE__ */ new WeakMap();
|
|
17596
|
+
function getRE2(pattern) {
|
|
17597
|
+
const cached = compiledRE2.get(pattern);
|
|
17598
|
+
if (cached !== void 0) return cached;
|
|
17599
|
+
const compiled = RE2JS.compile(pattern.source);
|
|
17600
|
+
compiledRE2.set(pattern, compiled);
|
|
17601
|
+
return compiled;
|
|
17602
|
+
}
|
|
17603
|
+
const compiledRegExps = /* @__PURE__ */ new WeakMap();
|
|
17604
|
+
function getRegExp(pattern) {
|
|
17605
|
+
const cached = compiledRegExps.get(pattern);
|
|
17606
|
+
if (cached !== void 0) return cached;
|
|
17607
|
+
const compiled = new RegExp(pattern.source, pattern.flags);
|
|
17608
|
+
compiledRegExps.set(pattern, compiled);
|
|
17609
|
+
return compiled;
|
|
17610
|
+
}
|
|
17590
17611
|
function findRuleSecret(rule, content) {
|
|
17591
17612
|
const path = content.path ?? "";
|
|
17592
17613
|
if (rule.path !== null && !hasPatternMatch(rule.path, path)) return null;
|
|
@@ -17698,30 +17719,11 @@ function countEntropy(text) {
|
|
|
17698
17719
|
}
|
|
17699
17720
|
return entropy;
|
|
17700
17721
|
}
|
|
17701
|
-
function hasPatternMatch(pattern, text) {
|
|
17702
|
-
return pattern.engine === "re2" ? getRE2(pattern).matcher(text).find() : getRegExp(pattern).test(text);
|
|
17703
|
-
}
|
|
17704
|
-
const compiledRegExps = /* @__PURE__ */ new WeakMap();
|
|
17705
|
-
const compiledRE2 = /* @__PURE__ */ new WeakMap();
|
|
17706
|
-
function getRegExp(pattern) {
|
|
17707
|
-
const cached = compiledRegExps.get(pattern);
|
|
17708
|
-
if (cached !== void 0) return cached;
|
|
17709
|
-
const compiled = new RegExp(pattern.source, pattern.flags);
|
|
17710
|
-
compiledRegExps.set(pattern, compiled);
|
|
17711
|
-
return compiled;
|
|
17712
|
-
}
|
|
17713
|
-
function getRE2(pattern) {
|
|
17714
|
-
const cached = compiledRE2.get(pattern);
|
|
17715
|
-
if (cached !== void 0) return cached;
|
|
17716
|
-
const compiled = RE2JS.compile(pattern.source);
|
|
17717
|
-
compiledRE2.set(pattern, compiled);
|
|
17718
|
-
return compiled;
|
|
17719
|
-
}
|
|
17720
17722
|
//#endregion
|
|
17721
17723
|
//#region src/bypass/classify-edit.ts
|
|
17722
17724
|
const MAX_SCANNED_BYTES = 262144;
|
|
17723
17725
|
function classifyEdit(action, scope) {
|
|
17724
|
-
const fields =
|
|
17726
|
+
const fields = findEditFields(action.toolName);
|
|
17725
17727
|
if (fields === null) return {
|
|
17726
17728
|
kind: "jev",
|
|
17727
17729
|
reason: "not a file-tool edit"
|
|
@@ -17766,48 +17768,6 @@ function classifyEdit(action, scope) {
|
|
|
17766
17768
|
reason: `secret scan matched ${secret.rule}`
|
|
17767
17769
|
};
|
|
17768
17770
|
}
|
|
17769
|
-
const CONTEXT_LINES = 12;
|
|
17770
|
-
function buildScanText(action, field) {
|
|
17771
|
-
const content = action.toolInput[field] ?? "";
|
|
17772
|
-
if (typeof content !== "string") return { reason: "edit content is not text" };
|
|
17773
|
-
if (action.toolName !== "Edit") return content;
|
|
17774
|
-
const old = action.toolInput["old_string"];
|
|
17775
|
-
if (typeof old !== "string" || old === "" || action.current === null) return { reason: "the edit cannot be read in the context of its file" };
|
|
17776
|
-
const parts = action.current.split(old);
|
|
17777
|
-
if (parts.length === 1) return { reason: "the edit text is not in the file" };
|
|
17778
|
-
const replaced = action.toolInput["replace_all"] === true ? parts.length - 1 : 1;
|
|
17779
|
-
const spans = [];
|
|
17780
|
-
let produced = parts[0] ?? "";
|
|
17781
|
-
for (let index = 1; index < parts.length; index += 1) {
|
|
17782
|
-
const isReplaced = index <= replaced;
|
|
17783
|
-
if (isReplaced) spans.push({
|
|
17784
|
-
start: produced.length,
|
|
17785
|
-
end: produced.length + content.length
|
|
17786
|
-
});
|
|
17787
|
-
produced += `${isReplaced ? content : old}${parts[index] ?? ""}`;
|
|
17788
|
-
}
|
|
17789
|
-
return collectContext(produced, spans);
|
|
17790
|
-
}
|
|
17791
|
-
function collectContext(text, spans) {
|
|
17792
|
-
const lines = text.split("\n");
|
|
17793
|
-
const starts = [];
|
|
17794
|
-
let offset = 0;
|
|
17795
|
-
for (const line of lines) {
|
|
17796
|
-
starts.push(offset);
|
|
17797
|
-
offset += line.length + 1;
|
|
17798
|
-
}
|
|
17799
|
-
const keep = /* @__PURE__ */ new Set();
|
|
17800
|
-
for (const span of spans) {
|
|
17801
|
-
const first = starts.findLastIndex((start) => start <= span.start);
|
|
17802
|
-
const last = starts.findLastIndex((start) => start <= span.end);
|
|
17803
|
-
for (let line = first - CONTEXT_LINES; line <= last + CONTEXT_LINES; line += 1) keep.add(line);
|
|
17804
|
-
}
|
|
17805
|
-
return lines.filter((_, index) => keep.has(index)).join("\n");
|
|
17806
|
-
}
|
|
17807
|
-
function toWorktreePath(path, worktrees) {
|
|
17808
|
-
const worktree = findWorktree(path, worktrees);
|
|
17809
|
-
return worktree === null ? path : relative(worktree, path).split(sep).join("/");
|
|
17810
|
-
}
|
|
17811
17771
|
function findWorktree(target, worktrees) {
|
|
17812
17772
|
return worktrees.filter((worktree) => isWithin(target, worktree)).toSorted((left, right) => right.length - left.length)[0] ?? null;
|
|
17813
17773
|
}
|
|
@@ -17850,5 +17810,47 @@ function findExclusion(path) {
|
|
|
17850
17810
|
const name = basename(path);
|
|
17851
17811
|
return EXCLUDED_NAMES.find(([pattern]) => pattern.test(name))?.[1] ?? null;
|
|
17852
17812
|
}
|
|
17813
|
+
function toWorktreePath(path, worktrees) {
|
|
17814
|
+
const worktree = findWorktree(path, worktrees);
|
|
17815
|
+
return worktree === null ? path : relative(worktree, path).split(sep).join("/");
|
|
17816
|
+
}
|
|
17817
|
+
function buildScanText(action, field) {
|
|
17818
|
+
const content = action.toolInput[field] ?? "";
|
|
17819
|
+
if (typeof content !== "string") return { reason: "edit content is not text" };
|
|
17820
|
+
if (action.toolName !== "Edit") return content;
|
|
17821
|
+
const old = action.toolInput["old_string"];
|
|
17822
|
+
if (typeof old !== "string" || old === "" || action.current === null) return { reason: "the edit cannot be read in the context of its file" };
|
|
17823
|
+
const parts = action.current.split(old);
|
|
17824
|
+
if (parts.length === 1) return { reason: "the edit text is not in the file" };
|
|
17825
|
+
const replaced = action.toolInput["replace_all"] === true ? parts.length - 1 : 1;
|
|
17826
|
+
const spans = [];
|
|
17827
|
+
let produced = parts[0] ?? "";
|
|
17828
|
+
for (let index = 1; index < parts.length; index += 1) {
|
|
17829
|
+
const isReplaced = index <= replaced;
|
|
17830
|
+
if (isReplaced) spans.push({
|
|
17831
|
+
start: produced.length,
|
|
17832
|
+
end: produced.length + content.length
|
|
17833
|
+
});
|
|
17834
|
+
produced += `${isReplaced ? content : old}${parts[index] ?? ""}`;
|
|
17835
|
+
}
|
|
17836
|
+
return collectContext(produced, spans);
|
|
17837
|
+
}
|
|
17838
|
+
const CONTEXT_LINES = 12;
|
|
17839
|
+
function collectContext(text, spans) {
|
|
17840
|
+
const lines = text.split("\n");
|
|
17841
|
+
const starts = [];
|
|
17842
|
+
let offset = 0;
|
|
17843
|
+
for (const line of lines) {
|
|
17844
|
+
starts.push(offset);
|
|
17845
|
+
offset += line.length + 1;
|
|
17846
|
+
}
|
|
17847
|
+
const keep = /* @__PURE__ */ new Set();
|
|
17848
|
+
for (const span of spans) {
|
|
17849
|
+
const first = starts.findLastIndex((start) => start <= span.start);
|
|
17850
|
+
const last = starts.findLastIndex((start) => start <= span.end);
|
|
17851
|
+
for (let line = first - CONTEXT_LINES; line <= last + CONTEXT_LINES; line += 1) keep.add(line);
|
|
17852
|
+
}
|
|
17853
|
+
return lines.filter((_, index) => keep.has(index)).join("\n");
|
|
17854
|
+
}
|
|
17853
17855
|
//#endregion
|
|
17854
17856
|
export { classifyEdit };
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as pickJudgeLane, E as updateJSONFile, S as CLI_LIMITS, T as resolveXDGDir, _ as
|
|
2
|
+
import { C as pickJudgeLane, E as updateJSONFile, S as CLI_LIMITS, T as resolveXDGDir, _ as readCheckout, a as resolveSessionScopePath, b as loadConfig, c as splitGitCommand, d as loadCheckoutFacts, f as writeActionDiagnostic, g as isUnresolvedWord, h as resolveShellPath, i as classifyAction, l as loadPolicy, m as collectShellCommands, n as readRuntime, o as loadSessionScope, p as toRepositorySlug, s as EMPTY_SESSION_SCOPE, t as parseActionRequest, u as resolveShippedPolicyDir, v as readGitEntry, w as M, x as runCapped, y as DEFAULT_SCOPE_SOURCES } from "./parse-action-request-CaQy7FA3.js";
|
|
3
3
|
import { a as literal, d as string, i as discriminatedUnion, r as boolean, s as number, u as strictObject } from "./schemas-B_w83Dze.js";
|
|
4
4
|
import { createHash, randomUUID } from "node:crypto";
|
|
5
5
|
import { chmod, mkdir, open, readFile, realpath, stat } from "node:fs/promises";
|
|
@@ -2570,10 +2570,10 @@ function resolveCaptureDir(capture, host) {
|
|
|
2570
2570
|
return capture.directory ?? join(resolveXDGDir(host, "state"), "captures");
|
|
2571
2571
|
}
|
|
2572
2572
|
//#endregion
|
|
2573
|
-
//#region src/capture/
|
|
2574
|
-
async function
|
|
2573
|
+
//#region src/capture/read-enclosing-work-tree.ts
|
|
2574
|
+
async function readEnclosingWorkTree(path) {
|
|
2575
2575
|
const real = await resolveExistingPrefix(resolve(path));
|
|
2576
|
-
const entry = await
|
|
2576
|
+
const entry = await readGitEntry(real);
|
|
2577
2577
|
return entry === null ? null : entry.directory;
|
|
2578
2578
|
}
|
|
2579
2579
|
async function resolveExistingPrefix(path) {
|
|
@@ -2593,7 +2593,7 @@ async function tryWriteRequestCapture(directory, record) {
|
|
|
2593
2593
|
reason: `the capture dir ${directory} is not an absolute path`
|
|
2594
2594
|
};
|
|
2595
2595
|
try {
|
|
2596
|
-
const before = await
|
|
2596
|
+
const before = await readEnclosingWorkTree(directory);
|
|
2597
2597
|
if (before !== null) return {
|
|
2598
2598
|
kind: "refused",
|
|
2599
2599
|
reason: `the capture dir is inside the git work tree ${before}`
|
|
@@ -2603,7 +2603,7 @@ async function tryWriteRequestCapture(directory, record) {
|
|
|
2603
2603
|
mode: 448
|
|
2604
2604
|
});
|
|
2605
2605
|
const real = await realpath(directory);
|
|
2606
|
-
const after = await
|
|
2606
|
+
const after = await readEnclosingWorkTree(real);
|
|
2607
2607
|
if (after !== null) return {
|
|
2608
2608
|
kind: "refused",
|
|
2609
2609
|
reason: `the capture dir is inside the git work tree ${after}`
|
|
@@ -2804,6 +2804,7 @@ async function readBranchCreatedAt(commonDir, branch) {
|
|
|
2804
2804
|
}
|
|
2805
2805
|
//#endregion
|
|
2806
2806
|
//#region src/scope/collect-pull-request-addresses.ts
|
|
2807
|
+
const PULL_REQUEST_URL = /https:\/\/(?<repository>[^/\s]+\/[^/\s]+\/[^/\s]+)\/pull\/(?<number>[1-9]\d*)\b/gu;
|
|
2807
2808
|
function collectPullRequestAddresses(text) {
|
|
2808
2809
|
const addresses = /* @__PURE__ */ new Map();
|
|
2809
2810
|
for (const match of text.matchAll(PULL_REQUEST_URL)) {
|
|
@@ -2816,7 +2817,6 @@ function collectPullRequestAddresses(text) {
|
|
|
2816
2817
|
}
|
|
2817
2818
|
return [...addresses.values()];
|
|
2818
2819
|
}
|
|
2819
|
-
const PULL_REQUEST_URL = /https:\/\/(?<repository>[^/\s]+\/[^/\s]+\/[^/\s]+)\/pull\/(?<number>[1-9]\d*)\b/gu;
|
|
2820
2820
|
//#endregion
|
|
2821
2821
|
//#region mods/auto-mode/contract/scope-commands.ts
|
|
2822
2822
|
const SCOPE_COMMANDS = {
|
|
@@ -2843,6 +2843,12 @@ function collectScopeEvents(command, cwd, home) {
|
|
|
2843
2843
|
}] : [];
|
|
2844
2844
|
});
|
|
2845
2845
|
}
|
|
2846
|
+
const GIT_EVENT_COLLECTORS = {
|
|
2847
|
+
"worktree add": collectWorktreeEvents,
|
|
2848
|
+
checkout: collectSwitchEvents,
|
|
2849
|
+
switch: collectSwitchEvents,
|
|
2850
|
+
branch: collectBranchEvents
|
|
2851
|
+
};
|
|
2846
2852
|
function collectGitEvents(args, cwd, home) {
|
|
2847
2853
|
const git = splitGitCommand(args, cwd, home);
|
|
2848
2854
|
const found = findScopeCommand(SCOPE_COMMANDS.git, git.args);
|
|
@@ -2859,12 +2865,6 @@ function findScopeCommand(commands, args) {
|
|
|
2859
2865
|
}
|
|
2860
2866
|
return null;
|
|
2861
2867
|
}
|
|
2862
|
-
const GIT_EVENT_COLLECTORS = {
|
|
2863
|
-
"worktree add": collectWorktreeEvents,
|
|
2864
|
-
checkout: collectSwitchEvents,
|
|
2865
|
-
switch: collectSwitchEvents,
|
|
2866
|
-
branch: collectBranchEvents
|
|
2867
|
-
};
|
|
2868
2868
|
function collectWorktreeEvents(rest, directory, home) {
|
|
2869
2869
|
const path = findWorktreePath(rest);
|
|
2870
2870
|
const resolved = path === null ? null : resolveShellPath(directory, path, home);
|
|
@@ -2903,6 +2903,11 @@ function collectSwitchEvents(rest, directory) {
|
|
|
2903
2903
|
directory
|
|
2904
2904
|
}];
|
|
2905
2905
|
}
|
|
2906
|
+
function findOptionValue(args, options) {
|
|
2907
|
+
const index = args.findIndex((word) => options.includes(word));
|
|
2908
|
+
const value = index === -1 ? void 0 : args[index + 1];
|
|
2909
|
+
return value === void 0 || isUnresolvedWord(value) ? null : value;
|
|
2910
|
+
}
|
|
2906
2911
|
function collectBranchEvents(rest, directory) {
|
|
2907
2912
|
if (rest.some((word) => BRANCH_OTHER_OPTIONS.test(word))) return [];
|
|
2908
2913
|
const name = rest.find((word) => !word.startsWith("-"));
|
|
@@ -2912,11 +2917,6 @@ function collectBranchEvents(rest, directory) {
|
|
|
2912
2917
|
directory
|
|
2913
2918
|
}];
|
|
2914
2919
|
}
|
|
2915
|
-
function findOptionValue(args, options) {
|
|
2916
|
-
const index = args.findIndex((word) => options.includes(word));
|
|
2917
|
-
const value = index === -1 ? void 0 : args[index + 1];
|
|
2918
|
-
return value === void 0 || isUnresolvedWord(value) ? null : value;
|
|
2919
|
-
}
|
|
2920
2920
|
//#endregion
|
|
2921
2921
|
//#region src/scope/merge-session-scope.ts
|
|
2922
2922
|
function mergeSessionScope(all) {
|
|
@@ -2953,11 +2953,10 @@ async function tryVerifyScopeEvent(event, request, options) {
|
|
|
2953
2953
|
return EMPTY_SESSION_SCOPE;
|
|
2954
2954
|
}
|
|
2955
2955
|
}
|
|
2956
|
-
const FORGE_CLOCK_SKEW_MS = 6e4;
|
|
2957
|
-
const FILE_CLOCK_SLACK_MS = 50;
|
|
2958
2956
|
function verifyScopeEvent(event, request, options) {
|
|
2959
2957
|
return M(event).returnType().with({ kind: "worktree" }, (worktree) => verifyWorktreeEvent(worktree.path, request, options)).with({ kind: "branch" }, (branch) => verifyBranchEvent(branch, request, options)).with({ kind: "pull-request" }, (pull) => verifyPullRequestEvent(pull.directory, request, options)).exhaustive();
|
|
2960
2958
|
}
|
|
2959
|
+
const FILE_CLOCK_SLACK_MS = 50;
|
|
2961
2960
|
async function verifyWorktreeEvent(path, request, options) {
|
|
2962
2961
|
const link = await stat(join(path, ".git"));
|
|
2963
2962
|
const facts = await loadCheckoutFacts(path, options.env);
|
|
@@ -2968,7 +2967,7 @@ async function verifyWorktreeEvent(path, request, options) {
|
|
|
2968
2967
|
...EMPTY_SESSION_SCOPE,
|
|
2969
2968
|
worktrees: [path]
|
|
2970
2969
|
};
|
|
2971
|
-
const isNew = await
|
|
2970
|
+
const isNew = await probeBranchCreatedSince(checkout.commonDir, branch, request.startedAt);
|
|
2972
2971
|
return {
|
|
2973
2972
|
...EMPTY_SESSION_SCOPE,
|
|
2974
2973
|
worktrees: [path],
|
|
@@ -2978,10 +2977,16 @@ async function verifyWorktreeEvent(path, request, options) {
|
|
|
2978
2977
|
}] : []
|
|
2979
2978
|
};
|
|
2980
2979
|
}
|
|
2980
|
+
async function probeBranchCreatedSince(commonDir, branch, since) {
|
|
2981
|
+
const createdAt = await readBranchCreatedAt(commonDir, branch);
|
|
2982
|
+
if (createdAt === null || createdAt < Math.floor(since / 1e3) * 1e3) return false;
|
|
2983
|
+
const ref = await stat(join(commonDir, "refs", "heads", branch)).catch(() => null);
|
|
2984
|
+
return ref !== null && ref.mtimeMs >= since - FILE_CLOCK_SLACK_MS;
|
|
2985
|
+
}
|
|
2981
2986
|
async function verifyBranchEvent(event, request, options) {
|
|
2982
|
-
const checkout = await
|
|
2987
|
+
const checkout = await readCheckout(event.directory, options.env);
|
|
2983
2988
|
if (checkout === null) return EMPTY_SESSION_SCOPE;
|
|
2984
|
-
return await
|
|
2989
|
+
return await probeBranchCreatedSince(checkout.commonDir, event.name, request.startedAt) ? {
|
|
2985
2990
|
...EMPTY_SESSION_SCOPE,
|
|
2986
2991
|
branches: [{
|
|
2987
2992
|
name: event.name,
|
|
@@ -2989,6 +2994,7 @@ async function verifyBranchEvent(event, request, options) {
|
|
|
2989
2994
|
}]
|
|
2990
2995
|
} : EMPTY_SESSION_SCOPE;
|
|
2991
2996
|
}
|
|
2997
|
+
const FORGE_CLOCK_SKEW_MS = 6e4;
|
|
2992
2998
|
async function verifyPullRequestEvent(directory, request, options) {
|
|
2993
2999
|
const facts = await loadCheckoutFacts(directory, options.env);
|
|
2994
3000
|
if (facts.checkout === null) return EMPTY_SESSION_SCOPE;
|
|
@@ -3006,12 +3012,6 @@ async function verifyPullRequestEvent(directory, request, options) {
|
|
|
3006
3012
|
pullRequests: pulls.flat()
|
|
3007
3013
|
};
|
|
3008
3014
|
}
|
|
3009
|
-
async function isBranchCreatedSince(commonDir, branch, since) {
|
|
3010
|
-
const createdAt = await readBranchCreatedAt(commonDir, branch);
|
|
3011
|
-
if (createdAt === null || createdAt < Math.floor(since / 1e3) * 1e3) return false;
|
|
3012
|
-
const ref = await stat(join(commonDir, "refs", "heads", branch)).catch(() => null);
|
|
3013
|
-
return ref !== null && ref.mtimeMs >= since - FILE_CLOCK_SLACK_MS;
|
|
3014
|
-
}
|
|
3015
3015
|
//#endregion
|
|
3016
3016
|
//#region src/record-scope.ts
|
|
3017
3017
|
async function recordScope(request, config, runtime) {
|
|
@@ -3145,20 +3145,6 @@ async function runCLI(argv, io) {
|
|
|
3145
3145
|
}
|
|
3146
3146
|
return exitCode;
|
|
3147
3147
|
}
|
|
3148
|
-
function runCommandAfterTerminator(io, values, rest) {
|
|
3149
|
-
const [command, ...positionals] = rest;
|
|
3150
|
-
if (values.help === true || command === void 0) return Promise.resolve(printUsage(io.stdout));
|
|
3151
|
-
const runCommand = COMMANDS.get(command);
|
|
3152
|
-
if (runCommand === void 0) {
|
|
3153
|
-
io.stderr.write(`auto-mode: unknown command '${command}'\n\n${USAGE}`);
|
|
3154
|
-
return Promise.resolve(2);
|
|
3155
|
-
}
|
|
3156
|
-
return runCommand(io, values, positionals);
|
|
3157
|
-
}
|
|
3158
|
-
function printUsage(stdout) {
|
|
3159
|
-
stdout.write(USAGE);
|
|
3160
|
-
return 0;
|
|
3161
|
-
}
|
|
3162
3148
|
async function runClassification(io, values) {
|
|
3163
3149
|
try {
|
|
3164
3150
|
return await run(io, {
|
|
@@ -3172,61 +3158,6 @@ async function runClassification(io, values) {
|
|
|
3172
3158
|
return 0;
|
|
3173
3159
|
}
|
|
3174
3160
|
}
|
|
3175
|
-
async function printPrompt(io, values) {
|
|
3176
|
-
const config = await loadConfig(void 0, io.runtime.host);
|
|
3177
|
-
printWarnings(io.stderr, config.warnings);
|
|
3178
|
-
const prompt = await loadPolicy({
|
|
3179
|
-
classifierPath: values.classifier ?? config.classifierPath,
|
|
3180
|
-
rulesPath: values.rules ?? config.rulesPath
|
|
3181
|
-
}, "decision.md");
|
|
3182
|
-
io.stdout.write(`${prompt}\n`);
|
|
3183
|
-
return 0;
|
|
3184
|
-
}
|
|
3185
|
-
function printModPath(io) {
|
|
3186
|
-
try {
|
|
3187
|
-
io.stdout.write(`${resolveShippedModDir()}\n`);
|
|
3188
|
-
return Promise.resolve(0);
|
|
3189
|
-
} catch (error) {
|
|
3190
|
-
io.stderr.write(`auto-mode: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
3191
|
-
return Promise.resolve(1);
|
|
3192
|
-
}
|
|
3193
|
-
}
|
|
3194
|
-
function requireValidCommandLine(ctx) {
|
|
3195
|
-
if (ctx.validationError !== void 0) throw ctx.validationError;
|
|
3196
|
-
}
|
|
3197
|
-
function isUsageError(error) {
|
|
3198
|
-
return error instanceof AggregateError && error.errors.every((reason) => isArgsValidationError(reason) || isCommandNotFoundError(reason) || isCommandResolutionError(reason));
|
|
3199
|
-
}
|
|
3200
|
-
function formatUsageError(error) {
|
|
3201
|
-
return error.errors.map((reason) => {
|
|
3202
|
-
if (isCommandNotFoundError(reason)) return `unknown command '${reason.commandName}'`;
|
|
3203
|
-
return reason instanceof Error ? reason.message : String(reason);
|
|
3204
|
-
}).join("\n");
|
|
3205
|
-
}
|
|
3206
|
-
function buildJudgeServerSession(io, config, sessionID) {
|
|
3207
|
-
const judge = config.judge ?? null;
|
|
3208
|
-
if (io.judgeServerCommand === void 0 || judge === null || pickJudgeLane(judge).transport !== "agent-sdk") return;
|
|
3209
|
-
const command = io.judgeServerCommand;
|
|
3210
|
-
const entry = command[1] ?? command[0];
|
|
3211
|
-
return makeJudgeServerSession({
|
|
3212
|
-
socketPath: resolveJudgeSocketPath(io.runtime.host, sessionID, entry),
|
|
3213
|
-
command: io.judgeServerCommand,
|
|
3214
|
-
env: io.runtime.host.env,
|
|
3215
|
-
timeoutMs: judge.timeoutMs
|
|
3216
|
-
});
|
|
3217
|
-
}
|
|
3218
|
-
async function runJudgeServer(io, socketPath) {
|
|
3219
|
-
if (socketPath === void 0) {
|
|
3220
|
-
io.stderr.write(`auto-mode: judge-server needs a socket path\n\n${USAGE}`);
|
|
3221
|
-
return 2;
|
|
3222
|
-
}
|
|
3223
|
-
await (await (await import("./start-judge-server-D-zcMyFZ.js")).startJudgeServer({
|
|
3224
|
-
socketPath,
|
|
3225
|
-
env: io.runtime.host.env,
|
|
3226
|
-
idleMs: JUDGE_IDLE_MS
|
|
3227
|
-
}))?.closed;
|
|
3228
|
-
return 0;
|
|
3229
|
-
}
|
|
3230
3161
|
const JUDGE_IDLE_MS = 9e5;
|
|
3231
3162
|
async function run(io, options) {
|
|
3232
3163
|
const raw = await io.stdin();
|
|
@@ -3292,6 +3223,18 @@ function printNote(stderr, explain, message) {
|
|
|
3292
3223
|
function printWarnings(stderr, warnings = []) {
|
|
3293
3224
|
for (const warning of warnings) stderr.write(`auto-mode: ${warning}\n`);
|
|
3294
3225
|
}
|
|
3226
|
+
function buildJudgeServerSession(io, config, sessionID) {
|
|
3227
|
+
const judge = config.judge ?? null;
|
|
3228
|
+
if (io.judgeServerCommand === void 0 || judge === null || pickJudgeLane(judge).transport !== "agent-sdk") return;
|
|
3229
|
+
const command = io.judgeServerCommand;
|
|
3230
|
+
const entry = command[1] ?? command[0];
|
|
3231
|
+
return makeJudgeServerSession({
|
|
3232
|
+
socketPath: resolveJudgeSocketPath(io.runtime.host, sessionID, entry),
|
|
3233
|
+
command: io.judgeServerCommand,
|
|
3234
|
+
env: io.runtime.host.env,
|
|
3235
|
+
timeoutMs: judge.timeoutMs
|
|
3236
|
+
});
|
|
3237
|
+
}
|
|
3295
3238
|
function printVerdict(stdout, verdict) {
|
|
3296
3239
|
stdout.write(renderVerdict(verdict));
|
|
3297
3240
|
}
|
|
@@ -3299,6 +3242,16 @@ function printCaptureNote(stderr, captured) {
|
|
|
3299
3242
|
if (captured.kind === "refused") stderr.write(`auto-mode: capture skipped: ${captured.reason}\n`);
|
|
3300
3243
|
if (captured.kind === "failed") stderr.write("auto-mode: capture unavailable\n");
|
|
3301
3244
|
}
|
|
3245
|
+
async function printPrompt(io, values) {
|
|
3246
|
+
const config = await loadConfig(void 0, io.runtime.host);
|
|
3247
|
+
printWarnings(io.stderr, config.warnings);
|
|
3248
|
+
const prompt = await loadPolicy({
|
|
3249
|
+
classifierPath: values.classifier ?? config.classifierPath,
|
|
3250
|
+
rulesPath: values.rules ?? config.rulesPath
|
|
3251
|
+
}, "decision.md");
|
|
3252
|
+
io.stdout.write(`${prompt}\n`);
|
|
3253
|
+
return 0;
|
|
3254
|
+
}
|
|
3302
3255
|
async function runRecord(io) {
|
|
3303
3256
|
const raw = await io.stdin();
|
|
3304
3257
|
let body;
|
|
@@ -3316,6 +3269,53 @@ async function runRecord(io) {
|
|
|
3316
3269
|
}
|
|
3317
3270
|
return 0;
|
|
3318
3271
|
}
|
|
3272
|
+
function printModPath(io) {
|
|
3273
|
+
try {
|
|
3274
|
+
io.stdout.write(`${resolveShippedModDir()}\n`);
|
|
3275
|
+
return Promise.resolve(0);
|
|
3276
|
+
} catch (error) {
|
|
3277
|
+
io.stderr.write(`auto-mode: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
3278
|
+
return Promise.resolve(1);
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
async function runJudgeServer(io, socketPath) {
|
|
3282
|
+
if (socketPath === void 0) {
|
|
3283
|
+
io.stderr.write(`auto-mode: judge-server needs a socket path\n\n${USAGE}`);
|
|
3284
|
+
return 2;
|
|
3285
|
+
}
|
|
3286
|
+
await (await (await import("./start-judge-server-BlhDO_4A.js")).startJudgeServer({
|
|
3287
|
+
socketPath,
|
|
3288
|
+
env: io.runtime.host.env,
|
|
3289
|
+
idleMs: JUDGE_IDLE_MS
|
|
3290
|
+
}))?.closed;
|
|
3291
|
+
return 0;
|
|
3292
|
+
}
|
|
3293
|
+
function printUsage(stdout) {
|
|
3294
|
+
stdout.write(USAGE);
|
|
3295
|
+
return 0;
|
|
3296
|
+
}
|
|
3297
|
+
function runCommandAfterTerminator(io, values, rest) {
|
|
3298
|
+
const [command, ...positionals] = rest;
|
|
3299
|
+
if (values.help === true || command === void 0) return Promise.resolve(printUsage(io.stdout));
|
|
3300
|
+
const runCommand = COMMANDS.get(command);
|
|
3301
|
+
if (runCommand === void 0) {
|
|
3302
|
+
io.stderr.write(`auto-mode: unknown command '${command}'\n\n${USAGE}`);
|
|
3303
|
+
return Promise.resolve(2);
|
|
3304
|
+
}
|
|
3305
|
+
return runCommand(io, values, positionals);
|
|
3306
|
+
}
|
|
3307
|
+
function requireValidCommandLine(ctx) {
|
|
3308
|
+
if (ctx.validationError !== void 0) throw ctx.validationError;
|
|
3309
|
+
}
|
|
3310
|
+
function isUsageError(error) {
|
|
3311
|
+
return error instanceof AggregateError && error.errors.every((reason) => isArgsValidationError(reason) || isCommandNotFoundError(reason) || isCommandResolutionError(reason));
|
|
3312
|
+
}
|
|
3313
|
+
function formatUsageError(error) {
|
|
3314
|
+
return error.errors.map((reason) => {
|
|
3315
|
+
if (isCommandNotFoundError(reason)) return `unknown command '${reason.commandName}'`;
|
|
3316
|
+
return reason instanceof Error ? reason.message : String(reason);
|
|
3317
|
+
}).join("\n");
|
|
3318
|
+
}
|
|
3319
3319
|
//#endregion
|
|
3320
3320
|
//#region src/cli.ts
|
|
3321
3321
|
process.exitCode = await runCLI(process.argv.slice(2), {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/bypass/
|
|
1
|
+
//#region src/bypass/find-edit-fields.ts
|
|
2
2
|
const EDIT_FIELDS = {
|
|
3
3
|
Edit: {
|
|
4
4
|
path: "file_path",
|
|
@@ -13,8 +13,8 @@ const EDIT_FIELDS = {
|
|
|
13
13
|
content: "new_source"
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
function
|
|
16
|
+
function findEditFields(toolName) {
|
|
17
17
|
return EDIT_FIELDS[toolName] ?? null;
|
|
18
18
|
}
|
|
19
19
|
//#endregion
|
|
20
|
-
export {
|
|
20
|
+
export { findEditFields as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ interface Checkout {
|
|
|
45
45
|
readonly gitDir: string;
|
|
46
46
|
readonly commonDir: string;
|
|
47
47
|
}
|
|
48
|
-
type
|
|
48
|
+
type CheckoutReader = (start: string, env: HostEnvironment['env']) => Promise<Checkout | null>;
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/types.d.ts
|
|
51
51
|
type DecidingStage = 'local' | 'containment' | 'bypass' | 'jev' | 'judge' | 'retry' | 'budget';
|
|
@@ -78,7 +78,7 @@ interface Runtime {
|
|
|
78
78
|
readonly now: () => number;
|
|
79
79
|
readonly timeout: (timeoutMs: number) => AbortSignal;
|
|
80
80
|
readonly fetch: (url: string, init: Readonly<RequestInit>) => Promise<Response>;
|
|
81
|
-
readonly
|
|
81
|
+
readonly readCheckout: CheckoutReader;
|
|
82
82
|
}
|
|
83
83
|
interface ClaudeRules {
|
|
84
84
|
readonly environment: readonly string[];
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as loadConfig$1, i as classifyAction$1, n as readRuntime, r as readHostEnvironment, t as parseActionRequest } from "./parse-action-request-
|
|
1
|
+
import { b as loadConfig$1, i as classifyAction$1, n as readRuntime, r as readHostEnvironment, t as parseActionRequest } from "./parse-action-request-CaQy7FA3.js";
|
|
2
2
|
//#region src/index.ts
|
|
3
3
|
function classifyAction(request, config, options = {}) {
|
|
4
4
|
return classifyAction$1(request, config, {
|