@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.
Files changed (265) hide show
  1. package/dist/bin/agent-serve.js +30 -23
  2. package/dist/channels/github/github-channel.d.ts +13 -1
  3. package/dist/channels/github/github-channel.d.ts.map +1 -1
  4. package/dist/channels/github/github-channel.js +81 -16
  5. package/dist/channels/github/types.d.ts +29 -1
  6. package/dist/channels/github/types.d.ts.map +1 -1
  7. package/dist/channels/origin/cursor-account.d.ts +22 -0
  8. package/dist/channels/origin/cursor-account.d.ts.map +1 -0
  9. package/dist/channels/origin/cursor-account.js +35 -0
  10. package/dist/channels/origin/events.d.ts +10 -0
  11. package/dist/channels/origin/events.d.ts.map +1 -0
  12. package/dist/channels/origin/events.js +27 -0
  13. package/dist/channels/origin/index.d.ts +29 -0
  14. package/dist/channels/origin/index.d.ts.map +1 -0
  15. package/dist/channels/origin/index.js +28 -0
  16. package/dist/channels/origin/origin-channel.d.ts +68 -0
  17. package/dist/channels/origin/origin-channel.d.ts.map +1 -0
  18. package/dist/channels/origin/origin-channel.js +567 -0
  19. package/dist/channels/origin/origin-webhook.d.ts +38 -0
  20. package/dist/channels/origin/origin-webhook.d.ts.map +1 -0
  21. package/dist/channels/origin/origin-webhook.js +151 -0
  22. package/dist/channels/origin/types.d.ts +152 -0
  23. package/dist/channels/origin/types.d.ts.map +1 -0
  24. package/dist/channels/origin/types.js +1 -0
  25. package/dist/channels/slack/doctor.d.ts +17 -1
  26. package/dist/channels/slack/doctor.d.ts.map +1 -1
  27. package/dist/channels/slack/doctor.js +186 -10
  28. package/dist/docs/404.html +2 -2
  29. package/dist/docs/ab.html +4 -4
  30. package/dist/docs/assets/{app.CVQxhV85.js → app.B-biogkN.js} +1 -1
  31. package/dist/docs/assets/chunks/@localSearchIndexroot.5ozYNf74.js +1 -0
  32. package/dist/docs/assets/chunks/{VPLocalSearchBox.QAPzJjql.js → VPLocalSearchBox.DZqKtFZS.js} +1 -1
  33. package/dist/docs/assets/chunks/{theme.CSxTCOFu.js → theme.BwC5zP2r.js} +2 -2
  34. package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.js → example-agents_fsd.md.ZeGEpAw_.js} +2 -2
  35. package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.lean.js → example-agents_fsd.md.ZeGEpAw_.lean.js} +1 -1
  36. package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.js → example-agents_security-reviewer.md.DBL1TwtP.js} +2 -2
  37. package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.lean.js → example-agents_security-reviewer.md.DBL1TwtP.lean.js} +1 -1
  38. package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.js +12 -0
  39. package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.lean.js +1 -0
  40. package/dist/docs/assets/{guides_github.md.B8QKtIpw.js → guides_github.md.CLLQJKRB.js} +4 -4
  41. package/dist/docs/assets/{guides_github.md.B8QKtIpw.lean.js → guides_github.md.CLLQJKRB.lean.js} +1 -1
  42. package/dist/docs/assets/index.md.DhRHS_-L.js +5 -0
  43. package/dist/docs/assets/{index.md.COeoSkcF.lean.js → index.md.DhRHS_-L.lean.js} +1 -1
  44. package/dist/docs/assets/{reference_cli.md.D_CCfG8R.js → reference_cli.md.Cl14Jfo3.js} +8 -2
  45. package/dist/docs/assets/{reference_cli.md.D_CCfG8R.lean.js → reference_cli.md.Cl14Jfo3.lean.js} +1 -1
  46. package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +1 -0
  47. package/dist/docs/assets/{scaffolding-agents.md.mkc3B_ZW.lean.js → scaffolding-agents.md.CrWSA0Ko.lean.js} +1 -1
  48. package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.js +14 -0
  49. package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.lean.js +1 -0
  50. package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.js +4 -0
  51. package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.lean.js +1 -0
  52. package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.js +8 -0
  53. package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.lean.js +1 -0
  54. package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.js +2 -0
  55. package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.lean.js +1 -0
  56. package/dist/docs/building-with-agents.html +4 -4
  57. package/dist/docs/concepts.html +5 -5
  58. package/dist/docs/deployment.html +4 -4
  59. package/dist/docs/evals.html +4 -4
  60. package/dist/docs/example-agents/approval-buddy.html +4 -4
  61. package/dist/docs/example-agents/benny.html +4 -4
  62. package/dist/docs/example-agents/bugbot.html +4 -4
  63. package/dist/docs/example-agents/codebase-wiki.html +4 -4
  64. package/dist/docs/example-agents/codeowners-review.html +4 -4
  65. package/dist/docs/example-agents/concierge.html +4 -4
  66. package/dist/docs/example-agents/fsd.html +5 -5
  67. package/dist/docs/example-agents/index.html +4 -4
  68. package/dist/docs/example-agents/knowledge-base.html +4 -4
  69. package/dist/docs/example-agents/oncall.html +4 -4
  70. package/dist/docs/example-agents/security-reviewer.html +5 -5
  71. package/dist/docs/example-agents/slack-agent.html +4 -4
  72. package/dist/docs/example-agents/weather-agent.html +4 -4
  73. package/dist/docs/guides/agent-to-agent.html +4 -4
  74. package/dist/docs/guides/cloud-runtime.html +4 -4
  75. package/dist/docs/guides/convert-automation.html +36 -0
  76. package/dist/docs/guides/github.html +7 -7
  77. package/dist/docs/guides/human-in-the-loop.html +4 -4
  78. package/dist/docs/guides/mcp-oauth.html +4 -4
  79. package/dist/docs/guides/opentelemetry.html +4 -4
  80. package/dist/docs/guides/slack.html +4 -4
  81. package/dist/docs/guides/webhooks.html +4 -4
  82. package/dist/docs/hashmap.json +1 -1
  83. package/dist/docs/hillclimbing.html +4 -4
  84. package/dist/docs/index.html +6 -6
  85. package/dist/docs/quickstart.html +4 -4
  86. package/dist/docs/reference/agent-config.html +4 -4
  87. package/dist/docs/reference/artifacts.html +4 -4
  88. package/dist/docs/reference/channels.html +4 -4
  89. package/dist/docs/reference/cli.html +12 -6
  90. package/dist/docs/reference/connections.html +4 -4
  91. package/dist/docs/reference/hooks.html +4 -4
  92. package/dist/docs/reference/http-api.html +4 -4
  93. package/dist/docs/reference/instructions.html +4 -4
  94. package/dist/docs/reference/playground.html +4 -4
  95. package/dist/docs/reference/project-layout.html +4 -4
  96. package/dist/docs/reference/prompt.html +4 -4
  97. package/dist/docs/reference/schedules.html +4 -4
  98. package/dist/docs/reference/sessions.html +4 -4
  99. package/dist/docs/reference/skills.html +4 -4
  100. package/dist/docs/reference/subagents.html +4 -4
  101. package/dist/docs/reference/tools.html +4 -4
  102. package/dist/docs/scaffolding-agents.html +5 -5
  103. package/dist/docs/storage.html +4 -4
  104. package/dist/docs/templates/agentic-owners.html +38 -0
  105. package/dist/docs/templates/demo.html +28 -0
  106. package/dist/docs/templates/pr-autofixer.html +32 -0
  107. package/dist/docs/templates/security-reviewer.html +26 -0
  108. package/dist/docs/templates/triage.html +5 -5
  109. package/dist/docs/troubleshooting.html +4 -4
  110. package/dist/index.d.ts +3 -3
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +2 -2
  113. package/dist/internal/cli-ax.d.ts +2 -0
  114. package/dist/internal/cli-ax.d.ts.map +1 -1
  115. package/dist/internal/cli-ax.js +20 -0
  116. package/dist/internal/cli-slack.d.ts +2 -0
  117. package/dist/internal/cli-slack.d.ts.map +1 -1
  118. package/dist/internal/cli-slack.js +11 -2
  119. package/dist/internal/cursor-event-relay.d.ts +64 -12
  120. package/dist/internal/cursor-event-relay.d.ts.map +1 -1
  121. package/dist/internal/cursor-event-relay.js +138 -26
  122. package/dist/internal/discovery.d.ts.map +1 -1
  123. package/dist/internal/discovery.js +11 -2
  124. package/dist/internal/distribution.d.ts.map +1 -1
  125. package/dist/internal/distribution.js +1 -0
  126. package/dist/internal/handleAgentServeTrigger.d.ts +33 -6
  127. package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
  128. package/dist/internal/handleAgentServeTrigger.js +97 -19
  129. package/dist/internal/init-interview.d.ts +67 -0
  130. package/dist/internal/init-interview.d.ts.map +1 -0
  131. package/dist/internal/init-interview.js +300 -0
  132. package/dist/internal/init-project.d.ts +4 -0
  133. package/dist/internal/init-project.d.ts.map +1 -1
  134. package/dist/internal/init-project.js +40 -16
  135. package/dist/internal/mcp-endpoint.d.ts +7 -0
  136. package/dist/internal/mcp-endpoint.d.ts.map +1 -1
  137. package/dist/internal/mcp-endpoint.js +7 -0
  138. package/dist/internal/mcp-oauth.d.ts +0 -4
  139. package/dist/internal/mcp-oauth.d.ts.map +1 -1
  140. package/dist/internal/mcp-oauth.js +0 -4
  141. package/dist/internal/server.d.ts.map +1 -1
  142. package/dist/internal/server.js +160 -58
  143. package/dist/internal/session-engine.d.ts.map +1 -1
  144. package/dist/internal/session-engine.js +20 -21
  145. package/dist/internal/session-links.d.ts +14 -0
  146. package/dist/internal/session-links.d.ts.map +1 -0
  147. package/dist/internal/session-links.js +69 -0
  148. package/dist/internal/sessions-client.d.ts.map +1 -1
  149. package/dist/internal/sessions-client.js +1 -0
  150. package/dist/playground/assets/index-B4rcOgeP.css +1 -0
  151. package/dist/playground/assets/{index-0oqXUkrR.js → index-DXcY42Jv.js} +42 -42
  152. package/dist/playground/index.html +2 -2
  153. package/dist/types.d.ts +19 -12
  154. package/dist/types.d.ts.map +1 -1
  155. package/docs/README.md +15 -0
  156. package/docs/example-agents/fsd.md +3 -0
  157. package/docs/example-agents/security-reviewer.md +3 -0
  158. package/docs/guides/convert-automation.md +176 -0
  159. package/docs/guides/github.md +6 -2
  160. package/docs/reference/cli.md +34 -10
  161. package/docs/scaffolding-agents.md +3 -0
  162. package/docs/templates/agentic-owners.md +97 -0
  163. package/docs/templates/demo.md +84 -0
  164. package/docs/templates/pr-autofixer.md +136 -0
  165. package/docs/templates/security-reviewer.md +89 -0
  166. package/package.json +9 -1
  167. package/skills/github/SKILL.md +6 -6
  168. package/src/bin/agent-serve.ts +13 -6
  169. package/src/channels/github/github-channel.ts +113 -20
  170. package/src/channels/github/types.ts +33 -0
  171. package/src/channels/origin/cursor-account.ts +64 -0
  172. package/src/channels/origin/events.ts +41 -0
  173. package/src/channels/origin/index.ts +29 -0
  174. package/src/channels/origin/origin-channel.ts +784 -0
  175. package/src/channels/origin/origin-webhook.ts +202 -0
  176. package/src/channels/origin/types.ts +186 -0
  177. package/src/channels/slack/doctor.ts +218 -5
  178. package/src/index.ts +3 -1
  179. package/src/internal/cli-ax.ts +23 -0
  180. package/src/internal/cli-slack.ts +11 -1
  181. package/src/internal/cursor-event-relay.ts +201 -32
  182. package/src/internal/discovery.ts +15 -5
  183. package/src/internal/distribution.ts +1 -0
  184. package/src/internal/handleAgentServeTrigger.ts +129 -19
  185. package/src/internal/init-interview.ts +384 -0
  186. package/src/internal/init-project.ts +70 -15
  187. package/src/internal/mcp-endpoint.ts +7 -0
  188. package/src/internal/mcp-oauth.ts +0 -4
  189. package/src/internal/server.ts +190 -60
  190. package/src/internal/session-engine.ts +5 -21
  191. package/src/internal/session-links.ts +88 -0
  192. package/src/internal/sessions-client.ts +1 -0
  193. package/src/types.ts +19 -12
  194. package/templates/agentic-owners/README.md +73 -0
  195. package/templates/agentic-owners/agent/agent.ts +15 -0
  196. package/templates/agentic-owners/agent/channels/github.ts +85 -0
  197. package/templates/agentic-owners/agent/instructions.md +34 -0
  198. package/templates/agentic-owners/agent/lib/config.ts +13 -0
  199. package/templates/agentic-owners/agent/lib/github.ts +241 -0
  200. package/templates/agentic-owners/agent/lib/owners/README.md +50 -0
  201. package/templates/agentic-owners/agent/lib/owners/constants.ts +22 -0
  202. package/templates/agentic-owners/agent/lib/owners/decision.ts +485 -0
  203. package/templates/agentic-owners/agent/lib/owners/handles.ts +54 -0
  204. package/templates/agentic-owners/agent/lib/owners/match.ts +177 -0
  205. package/templates/agentic-owners/agent/lib/owners/matching.ts +95 -0
  206. package/templates/agentic-owners/agent/lib/owners/parse.ts +589 -0
  207. package/templates/agentic-owners/agent/lib/owners/policyMode.ts +65 -0
  208. package/templates/agentic-owners/agent/lib/owners/prompt.ts +66 -0
  209. package/templates/agentic-owners/agent/lib/owners/prompts/base-review.md +105 -0
  210. package/templates/agentic-owners/agent/lib/owners/types.ts +45 -0
  211. package/templates/agentic-owners/agent/lib/review.ts +777 -0
  212. package/templates/agentic-owners/agent/tools/record_review.ts +69 -0
  213. package/templates/agentic-owners/evals/evals.config.ts +5 -0
  214. package/templates/agentic-owners/evals/owners.eval.ts +116 -0
  215. package/templates/agentic-owners/package.json +20 -0
  216. package/templates/agentic-owners/tsconfig.json +12 -0
  217. package/templates/demo/README.md +33 -0
  218. package/templates/demo/agent/agent.ts +15 -0
  219. package/templates/demo/agent/channels/github.ts +50 -0
  220. package/templates/demo/agent/channels/queue.ts +30 -0
  221. package/templates/demo/agent/instructions.md +8 -0
  222. package/templates/demo/agent/lib/collect.ts +78 -0
  223. package/templates/demo/agent/tools/record_demo.ts +40 -0
  224. package/templates/demo/evals/demo.eval.ts +33 -0
  225. package/templates/demo/evals/evals.config.ts +5 -0
  226. package/templates/demo/package.json +18 -0
  227. package/templates/demo/tsconfig.json +12 -0
  228. package/templates/pr-autofixer/README.md +44 -0
  229. package/templates/pr-autofixer/agent/agent.ts +22 -0
  230. package/templates/pr-autofixer/agent/channels/drive.ts +40 -0
  231. package/templates/pr-autofixer/agent/channels/github.ts +167 -0
  232. package/templates/pr-autofixer/agent/channels/slack.ts +17 -0
  233. package/templates/pr-autofixer/agent/hooks/bind-agent.ts +19 -0
  234. package/templates/pr-autofixer/agent/instructions.md +83 -0
  235. package/templates/pr-autofixer/agent/lib/affinity.ts +33 -0
  236. package/templates/pr-autofixer/agent/lib/drive-schemas.ts +15 -0
  237. package/templates/pr-autofixer/agent/lib/drive.ts +79 -0
  238. package/templates/pr-autofixer/agent/lib/merge-watch.ts +123 -0
  239. package/templates/pr-autofixer/agent/lib/pr-state.ts +54 -0
  240. package/templates/pr-autofixer/agent/lib/repos.ts +19 -0
  241. package/templates/pr-autofixer/agent/lib/start-drive.ts +122 -0
  242. package/templates/pr-autofixer/agent/lib/webhook-buffer.ts +225 -0
  243. package/templates/pr-autofixer/agent/lib/webhook-routing.ts +231 -0
  244. package/templates/pr-autofixer/agent/storage.ts +7 -0
  245. package/templates/pr-autofixer/agent/tools/drive_pr.ts +22 -0
  246. package/templates/pr-autofixer/evals/coordinator.eval.ts +16 -0
  247. package/templates/pr-autofixer/evals/evals.config.ts +5 -0
  248. package/templates/pr-autofixer/init.json +25 -0
  249. package/templates/pr-autofixer/package.json +18 -0
  250. package/templates/pr-autofixer/tsconfig.json +12 -0
  251. package/templates/security-reviewer/README.md +31 -0
  252. package/templates/security-reviewer/agent/agent.ts +15 -0
  253. package/templates/security-reviewer/agent/channels/github.ts +46 -0
  254. package/templates/security-reviewer/agent/instructions.md +22 -0
  255. package/templates/security-reviewer/agent/lib/repos.ts +5 -0
  256. package/templates/security-reviewer/agent/tools/post_findings.ts +72 -0
  257. package/templates/security-reviewer/evals/evals.config.ts +5 -0
  258. package/templates/security-reviewer/evals/review.eval.ts +53 -0
  259. package/templates/security-reviewer/init.json +25 -0
  260. package/templates/security-reviewer/package.json +18 -0
  261. package/templates/security-reviewer/tsconfig.json +12 -0
  262. package/dist/docs/assets/chunks/@localSearchIndexroot.BFpWSo6D.js +0 -1
  263. package/dist/docs/assets/index.md.COeoSkcF.js +0 -5
  264. package/dist/docs/assets/scaffolding-agents.md.mkc3B_ZW.js +0 -1
  265. 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
+ }