@cursor/july 0.1.55 → 0.1.62
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/bin/agent-serve.js +30 -23
- package/dist/channels/github/github-channel.d.ts +13 -1
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +81 -16
- package/dist/channels/github/types.d.ts +29 -1
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/cursor-account.d.ts +22 -0
- package/dist/channels/origin/cursor-account.d.ts.map +1 -0
- package/dist/channels/origin/cursor-account.js +35 -0
- package/dist/channels/origin/events.d.ts +10 -0
- package/dist/channels/origin/events.d.ts.map +1 -0
- package/dist/channels/origin/events.js +27 -0
- package/dist/channels/origin/index.d.ts +29 -0
- package/dist/channels/origin/index.d.ts.map +1 -0
- package/dist/channels/origin/index.js +28 -0
- package/dist/channels/origin/origin-channel.d.ts +68 -0
- package/dist/channels/origin/origin-channel.d.ts.map +1 -0
- package/dist/channels/origin/origin-channel.js +567 -0
- package/dist/channels/origin/origin-webhook.d.ts +38 -0
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -0
- package/dist/channels/origin/origin-webhook.js +151 -0
- package/dist/channels/origin/types.d.ts +152 -0
- package/dist/channels/origin/types.d.ts.map +1 -0
- package/dist/channels/origin/types.js +1 -0
- package/dist/channels/slack/doctor.d.ts +17 -1
- package/dist/channels/slack/doctor.d.ts.map +1 -1
- package/dist/channels/slack/doctor.js +186 -10
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.CVQxhV85.js → app.B-biogkN.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.5ozYNf74.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.QAPzJjql.js → VPLocalSearchBox.DZqKtFZS.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CSxTCOFu.js → theme.BwC5zP2r.js} +2 -2
- package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.js → example-agents_fsd.md.ZeGEpAw_.js} +2 -2
- package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.lean.js → example-agents_fsd.md.ZeGEpAw_.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.js → example-agents_security-reviewer.md.DBL1TwtP.js} +2 -2
- package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.lean.js → example-agents_security-reviewer.md.DBL1TwtP.lean.js} +1 -1
- package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.js +12 -0
- package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.lean.js +1 -0
- package/dist/docs/assets/{guides_github.md.B8QKtIpw.js → guides_github.md.CLLQJKRB.js} +4 -4
- package/dist/docs/assets/{guides_github.md.B8QKtIpw.lean.js → guides_github.md.CLLQJKRB.lean.js} +1 -1
- package/dist/docs/assets/index.md.DhRHS_-L.js +5 -0
- package/dist/docs/assets/{index.md.COeoSkcF.lean.js → index.md.DhRHS_-L.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.D_CCfG8R.js → reference_cli.md.Cl14Jfo3.js} +8 -2
- package/dist/docs/assets/{reference_cli.md.D_CCfG8R.lean.js → reference_cli.md.Cl14Jfo3.lean.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +1 -0
- package/dist/docs/assets/{scaffolding-agents.md.mkc3B_ZW.lean.js → scaffolding-agents.md.CrWSA0Ko.lean.js} +1 -1
- package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.js +14 -0
- package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.lean.js +1 -0
- package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.js +4 -0
- package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.lean.js +1 -0
- package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.js +8 -0
- package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.lean.js +1 -0
- package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.js +2 -0
- package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.lean.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +4 -4
- package/dist/docs/example-agents/approval-buddy.html +4 -4
- package/dist/docs/example-agents/benny.html +4 -4
- package/dist/docs/example-agents/bugbot.html +4 -4
- package/dist/docs/example-agents/codebase-wiki.html +4 -4
- package/dist/docs/example-agents/codeowners-review.html +4 -4
- package/dist/docs/example-agents/concierge.html +4 -4
- package/dist/docs/example-agents/fsd.html +5 -5
- package/dist/docs/example-agents/index.html +4 -4
- package/dist/docs/example-agents/knowledge-base.html +4 -4
- package/dist/docs/example-agents/oncall.html +4 -4
- package/dist/docs/example-agents/security-reviewer.html +5 -5
- package/dist/docs/example-agents/slack-agent.html +4 -4
- package/dist/docs/example-agents/weather-agent.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +36 -0
- package/dist/docs/guides/github.html +7 -7
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +12 -6
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +38 -0
- package/dist/docs/templates/demo.html +28 -0
- package/dist/docs/templates/pr-autofixer.html +32 -0
- package/dist/docs/templates/security-reviewer.html +26 -0
- package/dist/docs/templates/triage.html +5 -5
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/internal/cli-ax.d.ts +2 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +20 -0
- package/dist/internal/cli-slack.d.ts +2 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +11 -2
- package/dist/internal/cursor-event-relay.d.ts +64 -12
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +138 -26
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +11 -2
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +1 -0
- package/dist/internal/handleAgentServeTrigger.d.ts +33 -6
- package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
- package/dist/internal/handleAgentServeTrigger.js +97 -19
- package/dist/internal/init-interview.d.ts +67 -0
- package/dist/internal/init-interview.d.ts.map +1 -0
- package/dist/internal/init-interview.js +300 -0
- package/dist/internal/init-project.d.ts +4 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +40 -16
- package/dist/internal/mcp-endpoint.d.ts +7 -0
- package/dist/internal/mcp-endpoint.d.ts.map +1 -1
- package/dist/internal/mcp-endpoint.js +7 -0
- package/dist/internal/mcp-oauth.d.ts +0 -4
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +0 -4
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +160 -58
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +20 -21
- package/dist/internal/session-links.d.ts +14 -0
- package/dist/internal/session-links.d.ts.map +1 -0
- package/dist/internal/session-links.js +69 -0
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +1 -0
- package/dist/playground/assets/index-B4rcOgeP.css +1 -0
- package/dist/playground/assets/{index-0oqXUkrR.js → index-DXcY42Jv.js} +42 -42
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +19 -12
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +15 -0
- package/docs/example-agents/fsd.md +3 -0
- package/docs/example-agents/security-reviewer.md +3 -0
- package/docs/guides/convert-automation.md +176 -0
- package/docs/guides/github.md +6 -2
- package/docs/reference/cli.md +34 -10
- package/docs/scaffolding-agents.md +3 -0
- package/docs/templates/agentic-owners.md +97 -0
- package/docs/templates/demo.md +84 -0
- package/docs/templates/pr-autofixer.md +136 -0
- package/docs/templates/security-reviewer.md +89 -0
- package/package.json +9 -1
- package/skills/github/SKILL.md +6 -6
- package/src/bin/agent-serve.ts +13 -6
- package/src/channels/github/github-channel.ts +113 -20
- package/src/channels/github/types.ts +33 -0
- package/src/channels/origin/cursor-account.ts +64 -0
- package/src/channels/origin/events.ts +41 -0
- package/src/channels/origin/index.ts +29 -0
- package/src/channels/origin/origin-channel.ts +784 -0
- package/src/channels/origin/origin-webhook.ts +202 -0
- package/src/channels/origin/types.ts +186 -0
- package/src/channels/slack/doctor.ts +218 -5
- package/src/index.ts +3 -1
- package/src/internal/cli-ax.ts +23 -0
- package/src/internal/cli-slack.ts +11 -1
- package/src/internal/cursor-event-relay.ts +201 -32
- package/src/internal/discovery.ts +15 -5
- package/src/internal/distribution.ts +1 -0
- package/src/internal/handleAgentServeTrigger.ts +129 -19
- package/src/internal/init-interview.ts +384 -0
- package/src/internal/init-project.ts +70 -15
- package/src/internal/mcp-endpoint.ts +7 -0
- package/src/internal/mcp-oauth.ts +0 -4
- package/src/internal/server.ts +190 -60
- package/src/internal/session-engine.ts +5 -21
- package/src/internal/session-links.ts +88 -0
- package/src/internal/sessions-client.ts +1 -0
- package/src/types.ts +19 -12
- package/templates/agentic-owners/README.md +73 -0
- package/templates/agentic-owners/agent/agent.ts +15 -0
- package/templates/agentic-owners/agent/channels/github.ts +85 -0
- package/templates/agentic-owners/agent/instructions.md +34 -0
- package/templates/agentic-owners/agent/lib/config.ts +13 -0
- package/templates/agentic-owners/agent/lib/github.ts +241 -0
- package/templates/agentic-owners/agent/lib/owners/README.md +50 -0
- package/templates/agentic-owners/agent/lib/owners/constants.ts +22 -0
- package/templates/agentic-owners/agent/lib/owners/decision.ts +485 -0
- package/templates/agentic-owners/agent/lib/owners/handles.ts +54 -0
- package/templates/agentic-owners/agent/lib/owners/match.ts +177 -0
- package/templates/agentic-owners/agent/lib/owners/matching.ts +95 -0
- package/templates/agentic-owners/agent/lib/owners/parse.ts +589 -0
- package/templates/agentic-owners/agent/lib/owners/policyMode.ts +65 -0
- package/templates/agentic-owners/agent/lib/owners/prompt.ts +66 -0
- package/templates/agentic-owners/agent/lib/owners/prompts/base-review.md +105 -0
- package/templates/agentic-owners/agent/lib/owners/types.ts +45 -0
- package/templates/agentic-owners/agent/lib/review.ts +777 -0
- package/templates/agentic-owners/agent/tools/record_review.ts +69 -0
- package/templates/agentic-owners/evals/evals.config.ts +5 -0
- package/templates/agentic-owners/evals/owners.eval.ts +116 -0
- package/templates/agentic-owners/package.json +20 -0
- package/templates/agentic-owners/tsconfig.json +12 -0
- package/templates/demo/README.md +33 -0
- package/templates/demo/agent/agent.ts +15 -0
- package/templates/demo/agent/channels/github.ts +50 -0
- package/templates/demo/agent/channels/queue.ts +30 -0
- package/templates/demo/agent/instructions.md +8 -0
- package/templates/demo/agent/lib/collect.ts +78 -0
- package/templates/demo/agent/tools/record_demo.ts +40 -0
- package/templates/demo/evals/demo.eval.ts +33 -0
- package/templates/demo/evals/evals.config.ts +5 -0
- package/templates/demo/package.json +18 -0
- package/templates/demo/tsconfig.json +12 -0
- package/templates/pr-autofixer/README.md +44 -0
- package/templates/pr-autofixer/agent/agent.ts +22 -0
- package/templates/pr-autofixer/agent/channels/drive.ts +40 -0
- package/templates/pr-autofixer/agent/channels/github.ts +167 -0
- package/templates/pr-autofixer/agent/channels/slack.ts +17 -0
- package/templates/pr-autofixer/agent/hooks/bind-agent.ts +19 -0
- package/templates/pr-autofixer/agent/instructions.md +83 -0
- package/templates/pr-autofixer/agent/lib/affinity.ts +33 -0
- package/templates/pr-autofixer/agent/lib/drive-schemas.ts +15 -0
- package/templates/pr-autofixer/agent/lib/drive.ts +79 -0
- package/templates/pr-autofixer/agent/lib/merge-watch.ts +123 -0
- package/templates/pr-autofixer/agent/lib/pr-state.ts +54 -0
- package/templates/pr-autofixer/agent/lib/repos.ts +19 -0
- package/templates/pr-autofixer/agent/lib/start-drive.ts +122 -0
- package/templates/pr-autofixer/agent/lib/webhook-buffer.ts +225 -0
- package/templates/pr-autofixer/agent/lib/webhook-routing.ts +231 -0
- package/templates/pr-autofixer/agent/storage.ts +7 -0
- package/templates/pr-autofixer/agent/tools/drive_pr.ts +22 -0
- package/templates/pr-autofixer/evals/coordinator.eval.ts +16 -0
- package/templates/pr-autofixer/evals/evals.config.ts +5 -0
- package/templates/pr-autofixer/init.json +25 -0
- package/templates/pr-autofixer/package.json +18 -0
- package/templates/pr-autofixer/tsconfig.json +12 -0
- package/templates/security-reviewer/README.md +31 -0
- package/templates/security-reviewer/agent/agent.ts +15 -0
- package/templates/security-reviewer/agent/channels/github.ts +46 -0
- package/templates/security-reviewer/agent/instructions.md +22 -0
- package/templates/security-reviewer/agent/lib/repos.ts +5 -0
- package/templates/security-reviewer/agent/tools/post_findings.ts +72 -0
- package/templates/security-reviewer/evals/evals.config.ts +5 -0
- package/templates/security-reviewer/evals/review.eval.ts +53 -0
- package/templates/security-reviewer/init.json +25 -0
- package/templates/security-reviewer/package.json +18 -0
- package/templates/security-reviewer/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.BFpWSo6D.js +0 -1
- package/dist/docs/assets/index.md.COeoSkcF.js +0 -5
- package/dist/docs/assets/scaffolding-agents.md.mkc3B_ZW.js +0 -1
- package/dist/playground/assets/index-tHCjJxv4.css +0 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Vendored from the Agentic Owners policy core; see README.md in this
|
|
2
|
+
// directory. Precedence must stay identical to the source's.
|
|
3
|
+
|
|
4
|
+
import { patternMatchesFile, patternSpecificity } from "./matching.js";
|
|
5
|
+
import type {
|
|
6
|
+
AgenticOwnersMatchedConfig,
|
|
7
|
+
AgenticOwnersPathRule,
|
|
8
|
+
AgenticOwnersRepoConfig,
|
|
9
|
+
} from "./types.js";
|
|
10
|
+
|
|
11
|
+
type PathScopedRule = {
|
|
12
|
+
readonly scopeDepth: number;
|
|
13
|
+
readonly sourcePath: string;
|
|
14
|
+
readonly paths: readonly string[];
|
|
15
|
+
/** Root-only absolute exemption, produced from `global_exclusions`. */
|
|
16
|
+
readonly globalExclusion?: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function ruleMatchesFile({
|
|
20
|
+
rule,
|
|
21
|
+
filepath,
|
|
22
|
+
}: {
|
|
23
|
+
rule: PathScopedRule;
|
|
24
|
+
filepath: string;
|
|
25
|
+
}): boolean {
|
|
26
|
+
return rule.paths.some((pattern) => patternMatchesFile(pattern, filepath));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function bestMatchingPatternSpecificity(
|
|
30
|
+
rule: PathScopedRule,
|
|
31
|
+
filepath: string
|
|
32
|
+
): number {
|
|
33
|
+
let best = 0;
|
|
34
|
+
for (const pattern of rule.paths) {
|
|
35
|
+
if (patternMatchesFile(pattern, filepath)) {
|
|
36
|
+
best = Math.max(best, patternSpecificity(pattern));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return best;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function compareRulePrecedence(
|
|
43
|
+
left: PathScopedRule,
|
|
44
|
+
right: PathScopedRule,
|
|
45
|
+
filepath?: string
|
|
46
|
+
): number {
|
|
47
|
+
// Root `global_exclusions` model repository-wide owner-clearing rules. They
|
|
48
|
+
// must win before normal closest-directory precedence or every nested policy
|
|
49
|
+
// would need to repeat the same carve-outs. Parsing only permits them in the
|
|
50
|
+
// root policy, and the caller reads that policy from the base branch first.
|
|
51
|
+
const leftGlobalExclusion = left.globalExclusion === true;
|
|
52
|
+
const rightGlobalExclusion = right.globalExclusion === true;
|
|
53
|
+
if (leftGlobalExclusion !== rightGlobalExclusion) {
|
|
54
|
+
return leftGlobalExclusion ? 1 : -1;
|
|
55
|
+
}
|
|
56
|
+
if (left.scopeDepth !== right.scopeDepth) {
|
|
57
|
+
return left.scopeDepth - right.scopeDepth;
|
|
58
|
+
}
|
|
59
|
+
if (filepath !== undefined) {
|
|
60
|
+
const leftSpecificity = bestMatchingPatternSpecificity(left, filepath);
|
|
61
|
+
const rightSpecificity = bestMatchingPatternSpecificity(right, filepath);
|
|
62
|
+
if (leftSpecificity !== rightSpecificity) {
|
|
63
|
+
return leftSpecificity - rightSpecificity;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return left.sourcePath.localeCompare(right.sourcePath);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function pickWinningRuleForFile<T extends PathScopedRule>({
|
|
70
|
+
filepath,
|
|
71
|
+
rules,
|
|
72
|
+
}: {
|
|
73
|
+
filepath: string;
|
|
74
|
+
rules: readonly T[];
|
|
75
|
+
}): T | undefined {
|
|
76
|
+
let winner: T | undefined;
|
|
77
|
+
for (const rule of rules) {
|
|
78
|
+
if (!ruleMatchesFile({ rule, filepath })) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (
|
|
82
|
+
winner === undefined ||
|
|
83
|
+
compareRulePrecedence(rule, winner, filepath) > 0
|
|
84
|
+
) {
|
|
85
|
+
winner = rule;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return winner;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function matchRepoConfigForChangedFiles({
|
|
92
|
+
changedFiles,
|
|
93
|
+
config,
|
|
94
|
+
}: {
|
|
95
|
+
changedFiles: readonly string[];
|
|
96
|
+
config: AgenticOwnersRepoConfig;
|
|
97
|
+
}): AgenticOwnersMatchedConfig {
|
|
98
|
+
// Dedupe by rule identity, not sourcePath: two different rules in the same
|
|
99
|
+
// policy.yml can each win for different changed files, and collapsing them by
|
|
100
|
+
// file path would silently drop one (e.g. a hard-gate rule lost behind an
|
|
101
|
+
// advisory rule from the same policy).
|
|
102
|
+
const winners = new Set<AgenticOwnersPathRule>();
|
|
103
|
+
for (const filepath of changedFiles) {
|
|
104
|
+
const winner = pickWinningRuleForFile({ filepath, rules: config.rules });
|
|
105
|
+
if (winner !== undefined) {
|
|
106
|
+
winners.add(winner);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
matchedRules: [...winners].sort((left, right) =>
|
|
111
|
+
compareRulePrecedence(left, right)
|
|
112
|
+
),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The changed files that NO rule wins — not owned, not carved out, not
|
|
118
|
+
* globally excluded. These are the files that enroll a change through the
|
|
119
|
+
* default fallback: a file won by an ownerless carve-out or an exclusion was
|
|
120
|
+
* deliberately opted out, but a file nothing matches has simply never been
|
|
121
|
+
* governed and still deserves a risk review.
|
|
122
|
+
*
|
|
123
|
+
* Pure; the caller passes the already-loaded rule set (committed policy rules
|
|
124
|
+
* plus the synthetic `global_exclusions` rule) and the reviewable file set.
|
|
125
|
+
*/
|
|
126
|
+
export function changedFilesWithoutWinningRule({
|
|
127
|
+
changedFiles,
|
|
128
|
+
rules,
|
|
129
|
+
}: {
|
|
130
|
+
changedFiles: readonly string[];
|
|
131
|
+
rules: readonly AgenticOwnersPathRule[];
|
|
132
|
+
}): string[] {
|
|
133
|
+
return changedFiles.filter(
|
|
134
|
+
(filepath) => pickWinningRuleForFile({ filepath, rules }) === undefined
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* True when there is at least one changed file AND every one of them is won by a
|
|
140
|
+
* root `global_exclusions` rule. Such a PR is inherently low risk (it only
|
|
141
|
+
* touches globally-excluded paths — Bazel files, generated trees, …), so it
|
|
142
|
+
* keeps a clean not-enrolled pass: no risk assessment, no reviewer inference.
|
|
143
|
+
* An empty file set, an unmatched file, or a file won by any non-exclusion rule
|
|
144
|
+
* all make this false.
|
|
145
|
+
*/
|
|
146
|
+
export function everyChangedFileGloballyExcluded({
|
|
147
|
+
changedFiles,
|
|
148
|
+
rules,
|
|
149
|
+
}: {
|
|
150
|
+
changedFiles: readonly string[];
|
|
151
|
+
rules: readonly AgenticOwnersPathRule[];
|
|
152
|
+
}): boolean {
|
|
153
|
+
if (changedFiles.length === 0) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
return changedFiles.every(
|
|
157
|
+
(filepath) =>
|
|
158
|
+
pickWinningRuleForFile({ filepath, rules })?.globalExclusion === true
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function hasOwners(rule: AgenticOwnersPathRule): boolean {
|
|
163
|
+
return rule.teams.length > 0 || rule.users.length > 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Keep only owned policy rules — drop ownerless precedence carve-outs
|
|
168
|
+
* (`always_approve`, `global_exclusions`), which intentionally clear broader
|
|
169
|
+
* ownership and must not enroll the review. This is the same enrollment
|
|
170
|
+
* signal the CI gate uses, so "which PRs the agent reviews" cannot drift
|
|
171
|
+
* from "which PRs the gate blocks".
|
|
172
|
+
*/
|
|
173
|
+
export function committedMatchedRules(
|
|
174
|
+
rules: readonly AgenticOwnersPathRule[]
|
|
175
|
+
): AgenticOwnersPathRule[] {
|
|
176
|
+
return rules.filter(hasOwners);
|
|
177
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Vendored verbatim from the Agentic Owners policy core; see README.md in
|
|
2
|
+
// this directory. Matching semantics must stay identical to the source's.
|
|
3
|
+
|
|
4
|
+
import { minimatch } from "minimatch";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* CODEOWNERS-style path matching. Complex prefixes before a terminal `/**`
|
|
8
|
+
* deliberately fall through to minimatch below.
|
|
9
|
+
*/
|
|
10
|
+
export function patternMatchesFile(pattern: string, filepath: string): boolean {
|
|
11
|
+
const patternIsRooted = pattern.startsWith("/");
|
|
12
|
+
const normalizedPattern = pattern.replace(/^\/+/, "");
|
|
13
|
+
const normalizedPath = filepath.replace(/^\/+/, "");
|
|
14
|
+
|
|
15
|
+
if (normalizedPattern === "**" || normalizedPattern === "*") {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Keep the fast prefix path for literal `dir/**` rules. A wildcard before
|
|
20
|
+
// the terminal `/**` (for example `**/agent-serve/**`) must fall through to
|
|
21
|
+
// minimatch; treating its wildcard text as a literal prefix never matches.
|
|
22
|
+
if (
|
|
23
|
+
normalizedPattern.endsWith("**") &&
|
|
24
|
+
!hasComplexGlob(normalizedPattern.replace(/\*+$/, ""))
|
|
25
|
+
) {
|
|
26
|
+
const rawPrefix = normalizedPattern.replace(/\*+$/, "");
|
|
27
|
+
const prefix = rawPrefix.replace(/\\(.)/g, "$1").replace(/\/+$/, "");
|
|
28
|
+
return (
|
|
29
|
+
normalizedPath === prefix ||
|
|
30
|
+
(prefix !== "" && normalizedPath.startsWith(`${prefix}/`))
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (normalizedPattern.endsWith("/")) {
|
|
35
|
+
const prefix = normalizedPattern
|
|
36
|
+
.replace(/\\(.)/g, "$1")
|
|
37
|
+
.replace(/\/+$/, "");
|
|
38
|
+
if (!patternIsRooted && !prefix.includes("/")) {
|
|
39
|
+
return (
|
|
40
|
+
normalizedPath.startsWith(`${prefix}/`) ||
|
|
41
|
+
normalizedPath.includes(`/${prefix}/`)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return prefix !== "" && normalizedPath.startsWith(`${prefix}/`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (globstarDirectoryPatternMatches(normalizedPattern, normalizedPath)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
return minimatch(normalizedPath, normalizedPattern, {
|
|
53
|
+
dot: true,
|
|
54
|
+
matchBase: !normalizedPattern.includes("/"),
|
|
55
|
+
nocase: false,
|
|
56
|
+
});
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function hasComplexGlob(pattern: string): boolean {
|
|
63
|
+
return /[*?[\]{}!()+@]/.test(pattern);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Higher score means a more specific pattern (used to break ties within one policy.yml). */
|
|
67
|
+
export function patternSpecificity(pattern: string): number {
|
|
68
|
+
const normalized = pattern.replace(/^\/+/, "");
|
|
69
|
+
const globIndex = normalized.search(/[*?[\]{}!]/);
|
|
70
|
+
const literalPrefix =
|
|
71
|
+
globIndex === -1 ? normalized : normalized.slice(0, globIndex);
|
|
72
|
+
const segments = literalPrefix
|
|
73
|
+
.split("/")
|
|
74
|
+
.filter((segment) => segment !== "").length;
|
|
75
|
+
return literalPrefix.length * 100 + segments;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function globstarDirectoryPatternMatches(
|
|
79
|
+
pattern: string,
|
|
80
|
+
filepath: string
|
|
81
|
+
): boolean {
|
|
82
|
+
if (!pattern.startsWith("**/")) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const suffix = pattern.slice("**/".length);
|
|
86
|
+
if (suffix === "" || hasComplexGlob(suffix)) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return (
|
|
90
|
+
filepath === suffix ||
|
|
91
|
+
filepath.endsWith(`/${suffix}`) ||
|
|
92
|
+
filepath.startsWith(`${suffix}/`) ||
|
|
93
|
+
filepath.includes(`/${suffix}/`)
|
|
94
|
+
);
|
|
95
|
+
}
|