opencode-swarm 7.184.17 → 7.185.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.
Files changed (107) hide show
  1. package/README.md +6 -1
  2. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  3. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  4. package/dist/background/pr-review-trigger-receipt-reader.d.ts +35 -0
  5. package/dist/background/pr-subscriptions.d.ts +18 -0
  6. package/dist/background/stage-b-dispatch-binding-store.d.ts +115 -0
  7. package/dist/cli/{auto-checkpoint-8whpytsm.js → auto-checkpoint-2jecngee.js} +7 -7
  8. package/dist/cli/{checkpoint-zjtcn0tx.js → checkpoint-qm05wdbh.js} +14 -14
  9. package/dist/cli/{coder-settlement-0z8sr1ep.js → coder-settlement-56prayae.js} +10 -10
  10. package/dist/cli/{config-doctor-4zwh0dkn.js → config-doctor-3b99vx74.js} +2 -2
  11. package/dist/cli/{core-fqbga0z4.js → core-cxnqsrxp.js} +3 -3
  12. package/dist/cli/{curation-policy-1rzheh1x.js → curation-policy-ytzwb080.js} +4 -4
  13. package/dist/cli/{curator-fkebhqnh.js → curator-5k3mktpe.js} +39 -39
  14. package/dist/cli/{curator-drift-44ba54w1.js → curator-drift-dt4g79a4.js} +8 -8
  15. package/dist/cli/curator-llm-factory-hkk29g2y.js +81 -0
  16. package/dist/cli/{evidence-summary-service-e6wesfq2.js → evidence-summary-service-8e2fghz0.js} +17 -17
  17. package/dist/cli/{gate-evidence-8chc9f8q.js → gate-evidence-vk8rebsx.js} +5 -5
  18. package/dist/cli/guardrail-explain-ma658hkw.js +82 -0
  19. package/dist/cli/{guardrail-log-t0ketv64.js → guardrail-log-m6mydjet.js} +6 -6
  20. package/dist/cli/{guardrail-reset-rzva9emn.js → guardrail-reset-w41yndke.js} +39 -39
  21. package/dist/cli/{hive-promoter-h60dddna.js → hive-promoter-400xzdds.js} +39 -39
  22. package/dist/cli/{index-r472pepw.js → index-07bk0zm9.js} +1 -1
  23. package/dist/cli/{index-mfqge140.js → index-1fc5aj26.js} +1 -1
  24. package/dist/cli/{index-denfahc5.js → index-2b3bgm20.js} +1 -1
  25. package/dist/cli/{index-7n1pfpnj.js → index-2c6e1p7j.js} +3 -3
  26. package/dist/cli/{index-7rzgdcvc.js → index-373880cv.js} +1 -1
  27. package/dist/cli/{index-y0534tfs.js → index-5n08z6qj.js} +5 -5
  28. package/dist/cli/{index-jtg0zsnx.js → index-62akgg9d.js} +1 -1
  29. package/dist/cli/{index-2y9b45jj.js → index-6sffjy74.js} +1 -1
  30. package/dist/cli/{index-sfsydeh8.js → index-6wqv8f7d.js} +5 -5
  31. package/dist/cli/{index-pwcbtbhd.js → index-74yxwf8y.js} +1 -1
  32. package/dist/cli/{index-bktc2g9n.js → index-7jt24hpz.js} +2 -2
  33. package/dist/cli/{index-y8gxcmnj.js → index-7n3h39h9.js} +7 -7
  34. package/dist/cli/{index-fxf3zhtq.js → index-8nsjefpc.js} +1 -1
  35. package/dist/cli/{index-7r3pkgma.js → index-9g61bfj9.js} +1 -1
  36. package/dist/cli/{index-wxr5me67.js → index-9h93zjm3.js} +5 -1
  37. package/dist/cli/{index-dftztz4y.js → index-afmyp3kt.js} +1 -1
  38. package/dist/cli/{index-m8342y3n.js → index-cnbpht7m.js} +3 -3
  39. package/dist/cli/{index-tyzmjw2s.js → index-cp2nerjd.js} +420 -9
  40. package/dist/cli/{index-a7y29h92.js → index-dryhmaft.js} +3 -3
  41. package/dist/cli/{index-e708d35g.js → index-dz5cbkrm.js} +4 -4
  42. package/dist/cli/{index-naxrpyb0.js → index-ek5gvpvm.js} +7 -7
  43. package/dist/cli/{index-kxacpqwf.js → index-ekyg4p8b.js} +1 -1
  44. package/dist/cli/{index-hk2cap4d.js → index-fa014mra.js} +3 -3
  45. package/dist/cli/{index-pak3x772.js → index-hgfkcb1q.js} +1547 -1115
  46. package/dist/cli/{index-drndbj24.js → index-m1bhg85z.js} +2 -2
  47. package/dist/cli/{index-cftva3pa.js → index-nen885g8.js} +1 -1
  48. package/dist/cli/{index-hx4jkj05.js → index-nhw5rt5x.js} +4 -4
  49. package/dist/cli/{index-cyn2cb6k.js → index-nw16apxs.js} +5 -5
  50. package/dist/cli/{index-4v60grax.js → index-pa6fzbms.js} +4 -4
  51. package/dist/cli/{index-48we80k1.js → index-ppj5bjaq.js} +7 -7
  52. package/dist/cli/{index-gx03v1y5.js → index-pppjg0ct.js} +10 -10
  53. package/dist/cli/{index-vs1y869b.js → index-r9zc92pb.js} +41 -41
  54. package/dist/cli/{index-0pvvktht.js → index-rr1dggfe.js} +8 -3
  55. package/dist/cli/{index-8twhrz1w.js → index-rtznwf0g.js} +39 -39
  56. package/dist/cli/{index-m1pqenq9.js → index-s68z4a39.js} +2 -2
  57. package/dist/cli/{index-ww747mdg.js → index-s7va6n84.js} +3 -3
  58. package/dist/cli/{index-pef8ay7c.js → index-smwybqka.js} +2 -2
  59. package/dist/cli/{index-dky6qwrk.js → index-ss6b8jpz.js} +2 -2
  60. package/dist/cli/{index-yydv4jfy.js → index-vqz0avr4.js} +2 -2
  61. package/dist/cli/{index-yx5z4200.js → index-xgdypzch.js} +1 -1
  62. package/dist/cli/{index-0zjg4kt5.js → index-ycqsnfd1.js} +4 -4
  63. package/dist/cli/{index-bntwj2tp.js → index-yj7etak0.js} +3 -2
  64. package/dist/cli/{index-50q314wd.js → index-zt3taseq.js} +2 -2
  65. package/dist/cli/{index-4g4sr4ah.js → index-zxck9sr7.js} +1 -1
  66. package/dist/cli/index.js +40 -40
  67. package/dist/cli/{knowledge-escalator-kdeqdj0h.js → knowledge-escalator-30bb9fyg.js} +11 -11
  68. package/dist/cli/{knowledge-events-6fs0tz97.js → knowledge-events-gfbx97x0.js} +9 -9
  69. package/dist/cli/{knowledge-link-vvyfhhmr.js → knowledge-link-dv78fb9g.js} +3 -3
  70. package/dist/cli/{knowledge-store-z3fee1x1.js → knowledge-store-2ssd489f.js} +4 -4
  71. package/dist/cli/{knowledge-validator-sz1bmbvt.js → knowledge-validator-7bxvezgv.js} +6 -6
  72. package/dist/cli/{mcp-e1cnm4k3.js → mcp-apr65eya.js} +1 -1
  73. package/dist/cli/{model-preflight-936dhs10.js → model-preflight-g7b12yn2.js} +39 -39
  74. package/dist/cli/{pending-delegations-m0vf63yd.js → pending-delegations-x8q7cxr7.js} +10 -10
  75. package/dist/cli/{pr-subscriptions-2gvfff4q.js → pr-subscriptions-qwr6ybcb.js} +10 -10
  76. package/dist/cli/{pr-workflow-gate-68rg74bk.js → pr-workflow-gate-qd5tfkak.js} +39 -39
  77. package/dist/cli/{runner-cwmgb9rw.js → runner-tb3eppeg.js} +4 -4
  78. package/dist/cli/{scan-cursor-qzsanqx4.js → scan-cursor-1m6dj2s2.js} +5 -5
  79. package/dist/cli/{schema-jx4v0hg7.js → schema-yvhamv41.js} +3 -1
  80. package/dist/cli/{scope-persistence-qk1h0c13.js → scope-persistence-xdedbzdg.js} +13 -13
  81. package/dist/cli/{server-z9az3wc5.js → server-nhdkvdt2.js} +39 -39
  82. package/dist/cli/{skill-generator-h0veywz6.js → skill-generator-fzvp9m8z.js} +13 -13
  83. package/dist/cli/{snapshot-coordination-init-mwrvch16.js → snapshot-coordination-init-xqxek8kn.js} +39 -39
  84. package/dist/cli/{speckit-checkoff-skyray2c.js → speckit-checkoff-57tf4079.js} +4 -4
  85. package/dist/cli/{workspace-snapshot-gnwak61t.js → workspace-snapshot-kcfkk3a2.js} +3 -3
  86. package/dist/cli/{worktree-collision-ownership-wvxm7q1h.js → worktree-collision-ownership-80n814a8.js} +11 -11
  87. package/dist/cli/{worktree-isolation-bmzkxa64.js → worktree-isolation-kaxkr61t.js} +39 -39
  88. package/dist/commands/_shared/url-security.d.ts +20 -9
  89. package/dist/commands/pr-ref.d.ts +44 -8
  90. package/dist/commands/pr-subscribe.d.ts +0 -8
  91. package/dist/commands/pr-unsubscribe.d.ts +2 -1
  92. package/dist/config/schema.d.ts +17 -0
  93. package/dist/hooks/delegation-gate.d.ts +5 -1
  94. package/dist/hooks/extractors.d.ts +24 -0
  95. package/dist/hooks/pr-auto-subscribe.d.ts +5 -4
  96. package/dist/index.js +533 -529
  97. package/dist/pr-review/completion.d.ts +14 -1
  98. package/dist/pr-review/types.d.ts +8 -1
  99. package/dist/providers/forge-provider.d.ts +167 -0
  100. package/dist/providers/host-guards.d.ts +31 -0
  101. package/dist/tools/write-pr-review-trigger-eval.d.ts +2 -0
  102. package/dist/utils/gh-executable.d.ts +10 -0
  103. package/dist/utils/glab-executable.d.ts +85 -0
  104. package/opencode-swarm.schema.json +19 -0
  105. package/package.json +1 -1
  106. package/dist/cli/curator-llm-factory-65qve6xk.js +0 -81
  107. package/dist/cli/guardrail-explain-2prdgvjk.js +0 -82
@@ -4,7 +4,7 @@ import {
4
4
  getProjectDb,
5
5
  projectDbExists,
6
6
  withImmediateTransaction
7
- } from "./index-pwcbtbhd.js";
7
+ } from "./index-74yxwf8y.js";
8
8
  import {
9
9
  derivePlanId,
10
10
  derivePlanIdentityHash
@@ -12,7 +12,7 @@ import {
12
12
  PluginConfigSchema,
13
13
  init_schema,
14
14
  stripKnownSwarmPrefix
15
- } from "./index-0pvvktht.js";
15
+ } from "./index-rr1dggfe.js";
16
16
  import {
17
17
  ALL_AGENT_NAMES,
18
18
  TOOL_NAME_SET,
@@ -1087,6 +1087,10 @@ function validateConfigKey(path2, value) {
1087
1087
  emitObjectTypeMismatch("docs", value, findings);
1088
1088
  break;
1089
1089
  }
1090
+ case "forge": {
1091
+ emitObjectTypeMismatch("forge", value, findings);
1092
+ break;
1093
+ }
1090
1094
  case "design_docs": {
1091
1095
  emitObjectTypeMismatch("design_docs", value, findings);
1092
1096
  break;
@@ -10,7 +10,7 @@ import {
10
10
  readCachedTextFile,
11
11
  wasObservedToExist,
12
12
  wasRecentlyWrittenByThisProcess
13
- } from "./index-bntwj2tp.js";
13
+ } from "./index-yj7etak0.js";
14
14
  import {
15
15
  warn
16
16
  } from "./index-zgwm4ryv.js";
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  autoCommitDirty,
4
4
  cleanUntrackedFiles
5
- } from "./index-7n1pfpnj.js";
5
+ } from "./index-2c6e1p7j.js";
6
6
  import {
7
7
  isSpawnCwdMissing,
8
8
  isSpawnCwdUnreadable
9
9
  } from "./index-g4fs6z4e.js";
10
10
  import {
11
11
  validateSwarmPath
12
- } from "./index-dftztz4y.js";
12
+ } from "./index-afmyp3kt.js";
13
13
  import {
14
14
  bunSpawn
15
15
  } from "./index-2s7dvzff.js";
@@ -17,7 +17,7 @@ import {
17
17
  atomicWriteFile,
18
18
  taskEvidencePath,
19
19
  withTaskEvidenceLock
20
- } from "./index-2y9b45jj.js";
20
+ } from "./index-6sffjy74.js";
21
21
  import {
22
22
  assertProjectRoot
23
23
  } from "./index-t7hmqgjy.js";
@@ -1,21 +1,21 @@
1
1
  // @bun
2
2
  import {
3
3
  validateSwarmPath
4
- } from "./index-dftztz4y.js";
4
+ } from "./index-afmyp3kt.js";
5
5
  import {
6
6
  deleteCoordinationState,
7
7
  importCoordinationOnce,
8
8
  listCoordinationStates,
9
9
  transitionCoordinationState,
10
10
  withCoordinationTransaction
11
- } from "./index-cftva3pa.js";
11
+ } from "./index-nen885g8.js";
12
12
  import {
13
13
  getProjectDb,
14
14
  projectDbExists
15
- } from "./index-pwcbtbhd.js";
15
+ } from "./index-74yxwf8y.js";
16
16
  import {
17
17
  observeStoreHealth
18
- } from "./index-yx5z4200.js";
18
+ } from "./index-xgdypzch.js";
19
19
  import {
20
20
  withEvidenceLock
21
21
  } from "./index-6cjpmvpa.js";
@@ -29,7 +29,7 @@ import {
29
29
  } from "./index-mc72pk74.js";
30
30
  import {
31
31
  atomicWriteSwarmFileSync
32
- } from "./index-bntwj2tp.js";
32
+ } from "./index-yj7etak0.js";
33
33
  import {
34
34
  exports_external,
35
35
  init_zod
@@ -43,6 +43,397 @@ init_zod();
43
43
  import { createHash } from "crypto";
44
44
  import * as fs from "fs";
45
45
  import * as path from "path";
46
+
47
+ // src/providers/host-guards.ts
48
+ var IPV4_PRIVATE = /^10\./;
49
+ var IPV4_LOOPBACK = /^127\./;
50
+ var IPV4_LINK_LOCAL = /^169\.254\./;
51
+ var IPV4_PRIVATE_172 = /^172\.(1[6-9]|2\d|3[0-1])\./;
52
+ var IPV4_PRIVATE_192 = /^192\.168\./;
53
+ var IPV4_ZERO_NETWORK = /^0\./;
54
+ var IPV6_LINK_LOCAL = /^fe80:/i;
55
+ var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
56
+ function containsControlCharacters(value) {
57
+ for (const ch of value) {
58
+ const cp = ch.codePointAt(0);
59
+ if (cp !== undefined && (cp <= 31 || cp === 127)) {
60
+ return true;
61
+ }
62
+ }
63
+ return false;
64
+ }
65
+ function hasNonAsciiHostname(hostname) {
66
+ for (const ch of hostname) {
67
+ const cp = ch.codePointAt(0);
68
+ if (cp !== undefined && cp > 127)
69
+ return true;
70
+ }
71
+ return false;
72
+ }
73
+ function isIpv4MappedPrivateHost(inner) {
74
+ if (IPV4_PRIVATE.test(inner) || IPV4_LOOPBACK.test(inner) || IPV4_LINK_LOCAL.test(inner) || IPV4_PRIVATE_172.test(inner) || IPV4_PRIVATE_192.test(inner) || IPV4_ZERO_NETWORK.test(inner)) {
75
+ return true;
76
+ }
77
+ const firstSegment = inner.split(":", 1)[0];
78
+ if (!firstSegment)
79
+ return false;
80
+ const firstWord = Number.parseInt(firstSegment, 16);
81
+ if (!Number.isFinite(firstWord))
82
+ return false;
83
+ return firstWord >= 0 && firstWord <= 255 || firstWord >= 2560 && firstWord <= 2815 || firstWord >= 32512 && firstWord <= 32767 || firstWord === 43518 || firstWord >= 44048 && firstWord <= 44063 || firstWord === 49320;
84
+ }
85
+ function isPrivateHost(url) {
86
+ const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
87
+ if (host === "localhost" || host === "::1" || host === "0.0.0.0" || IPV4_LOOPBACK.test(host) || IPV4_ZERO_NETWORK.test(host)) {
88
+ return true;
89
+ }
90
+ if (host.startsWith("localhost") || host === "localhost.com") {
91
+ return true;
92
+ }
93
+ if (host.endsWith(".localhost")) {
94
+ return true;
95
+ }
96
+ if (IPV4_PRIVATE.test(host) || IPV4_LINK_LOCAL.test(host) || IPV4_PRIVATE_172.test(host) || IPV4_PRIVATE_192.test(host) || IPV6_LINK_LOCAL.test(host) || IPV6_UNIQUE_LOCAL.test(host)) {
97
+ return true;
98
+ }
99
+ if (host.startsWith("::ffff:")) {
100
+ const inner = host.slice(7);
101
+ if (isIpv4MappedPrivateHost(inner)) {
102
+ return true;
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+ function hasPunycodeLabel(host) {
108
+ const lower = host.toLowerCase();
109
+ return lower.split(".").some((label) => label.startsWith("xn--"));
110
+ }
111
+
112
+ // src/providers/forge-provider.ts
113
+ var GITHUB_CANONICAL_HOST = "github.com";
114
+ var GITLAB_PUBLIC_HOST = "gitlab.com";
115
+ function isGitLabIndicatingHost(host) {
116
+ const lower = host.toLowerCase();
117
+ if (lower === GITLAB_PUBLIC_HOST)
118
+ return true;
119
+ if (!lower.startsWith("gitlab."))
120
+ return false;
121
+ const remainder = lower.slice("gitlab.".length);
122
+ if (remainder.length === 0)
123
+ return false;
124
+ return remainder.split(".").every((label) => /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(label));
125
+ }
126
+ function isForgePrUrl(url, configured) {
127
+ return canonicalForgePrUrl(url, configured) !== null;
128
+ }
129
+ function detectForgeFromUrl(url, configured) {
130
+ try {
131
+ const parsed = new URL(url);
132
+ if (parsed.protocol !== "https:")
133
+ return null;
134
+ const host = parsed.hostname.toLowerCase();
135
+ if (hasUserinfo(parsed))
136
+ return null;
137
+ if (hasNonAsciiHostname(host) || hasPunycodeLabel(host))
138
+ return null;
139
+ if (isPrivateHost(parsed))
140
+ return null;
141
+ if (host === GITHUB_CANONICAL_HOST) {
142
+ return { provider: "github", host };
143
+ }
144
+ if (isGitLabIndicatingHost(host)) {
145
+ return { provider: "gitlab", host };
146
+ }
147
+ if (configured && configured.provider === "gitlab" && host === configured.host) {
148
+ return { provider: "gitlab", host };
149
+ }
150
+ return null;
151
+ } catch {
152
+ return null;
153
+ }
154
+ }
155
+ function hasUserinfo(parsed) {
156
+ return parsed.username !== "" || parsed.password !== "";
157
+ }
158
+ function isConfiguredGitLabHost(host, configured) {
159
+ return configured !== undefined && configured.provider === "gitlab" && host === configured.host;
160
+ }
161
+ var GITLAB_PROJECT_PATH_PATTERN = /^\/(.+)\/([^/]+)\/-\/(merge_requests|issues)\/(\d+)\/?$/;
162
+ function matchForgeResourceUrl(url, resource, configured) {
163
+ if (containsControlCharacters(url))
164
+ return null;
165
+ let parsed;
166
+ try {
167
+ parsed = new URL(url);
168
+ } catch {
169
+ return null;
170
+ }
171
+ if (parsed.protocol !== "https:")
172
+ return null;
173
+ if (hasUserinfo(parsed))
174
+ return null;
175
+ const host = parsed.hostname.toLowerCase();
176
+ if (hasNonAsciiHostname(host) || hasPunycodeLabel(host))
177
+ return null;
178
+ if (isPrivateHost(parsed))
179
+ return null;
180
+ try {
181
+ if (containsControlCharacters(decodeURIComponent(parsed.pathname))) {
182
+ return null;
183
+ }
184
+ } catch {
185
+ return null;
186
+ }
187
+ if (host === GITHUB_CANONICAL_HOST) {
188
+ const m = parsed.pathname.match(new RegExp(`^\\/([^/]+)\\/([^/]+)\\/${resource === "pull" ? "pull" : "issues"}\\/([0-9]+)\\/?$`));
189
+ if (!m)
190
+ return null;
191
+ if (containsControlCharacters(m[1]) || containsControlCharacters(m[2])) {
192
+ return null;
193
+ }
194
+ const number = Number.parseInt(m[3], 10);
195
+ if (!Number.isSafeInteger(number) || number <= 0)
196
+ return null;
197
+ return { provider: "github", host, owner: m[1], repo: m[2], number };
198
+ }
199
+ if (isGitLabIndicatingHost(host) || isConfiguredGitLabHost(host, configured)) {
200
+ const resourceSegment = resource === "pull" ? "merge_requests" : "issues";
201
+ const m = parsed.pathname.match(GITLAB_PROJECT_PATH_PATTERN);
202
+ if (!m || m[3] !== resourceSegment)
203
+ return null;
204
+ if (containsControlCharacters(m[1]) || containsControlCharacters(m[2])) {
205
+ return null;
206
+ }
207
+ const number = Number.parseInt(m[4], 10);
208
+ if (!Number.isSafeInteger(number) || number <= 0)
209
+ return null;
210
+ return { provider: "gitlab", host, owner: m[1], repo: m[2], number };
211
+ }
212
+ return null;
213
+ }
214
+ function parseForgeRemoteUrl(remoteUrl) {
215
+ const https = remoteUrl.match(/^https:\/\/([^/]+)\/(.+?)(?:\.git)?\/?$/i);
216
+ if (https) {
217
+ return remotePathResult(https[1], https[2]);
218
+ }
219
+ const ssh = remoteUrl.match(/^git@([^:/]+):(.+?)(?:\.git)?$/i);
220
+ if (ssh) {
221
+ return remotePathResult(ssh[1], ssh[2]);
222
+ }
223
+ return null;
224
+ }
225
+ function remotePathResult(rawHost, projectPath) {
226
+ const host = rawHost.toLowerCase();
227
+ if (!host || hasNonAsciiHostname(host) || hasPunycodeLabel(host))
228
+ return null;
229
+ if (!isGitLabIndicatingHost(host) && host !== GITHUB_CANONICAL_HOST) {
230
+ return null;
231
+ }
232
+ const segments = projectPath.split("/").filter((s) => s.length > 0);
233
+ if (segments.length < 2)
234
+ return null;
235
+ const repo = segments[segments.length - 1];
236
+ const owner = segments.slice(0, -1).join("/");
237
+ if (!owner || !repo)
238
+ return null;
239
+ if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
240
+ return null;
241
+ }
242
+ return {
243
+ provider: host === GITHUB_CANONICAL_HOST ? "github" : "gitlab",
244
+ host,
245
+ owner,
246
+ repo
247
+ };
248
+ }
249
+ function buildPrUrl(ctx, owner, repo, number) {
250
+ if (ctx.provider === "gitlab") {
251
+ return `https://${ctx.host}/${owner}/${repo}/-/merge_requests/${number}`;
252
+ }
253
+ return `https://github.com/${owner}/${repo}/pull/${number}`;
254
+ }
255
+ function buildIssueUrl(ctx, owner, repo, number) {
256
+ if (ctx.provider === "gitlab") {
257
+ return `https://${ctx.host}/${owner}/${repo}/-/issues/${number}`;
258
+ }
259
+ return `https://github.com/${owner}/${repo}/issues/${number}`;
260
+ }
261
+ function canonicalForgePrUrl(value, configured) {
262
+ try {
263
+ const url = new URL(value);
264
+ if (url.protocol !== "https:")
265
+ return null;
266
+ if (hasUserinfo(url))
267
+ return null;
268
+ const host = url.hostname.toLowerCase();
269
+ if (hasNonAsciiHostname(host) || hasPunycodeLabel(host))
270
+ return null;
271
+ if (isPrivateHost(url))
272
+ return null;
273
+ if (host === GITHUB_CANONICAL_HOST) {
274
+ const m = url.pathname.match(/^\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/);
275
+ if (!m)
276
+ return null;
277
+ const number = Number(m[3]);
278
+ if (!Number.isSafeInteger(number) || number <= 0)
279
+ return null;
280
+ return `github.com/${m[1].toLowerCase()}/${m[2].toLowerCase()}/pull/${number}`;
281
+ }
282
+ if (isGitLabIndicatingHost(host) || isConfiguredGitLabHost(host, configured)) {
283
+ const m = url.pathname.match(/^\/(.+)\/([^/]+)\/-\/merge_requests\/(\d+)\/?$/);
284
+ if (!m)
285
+ return null;
286
+ const number = Number(m[3]);
287
+ if (!Number.isSafeInteger(number) || number <= 0)
288
+ return null;
289
+ return `${host}/${m[1].toLowerCase()}/${m[2].toLowerCase()}/-/merge_requests/${number}`;
290
+ }
291
+ return null;
292
+ } catch {
293
+ return null;
294
+ }
295
+ }
296
+ function getProviderCapabilities(provider) {
297
+ if (provider === "gitlab") {
298
+ return {
299
+ statusCheckRollup: false,
300
+ reviewDecision: false,
301
+ mergeStateStatus: false
302
+ };
303
+ }
304
+ return {
305
+ statusCheckRollup: true,
306
+ reviewDecision: true,
307
+ mergeStateStatus: true
308
+ };
309
+ }
310
+ function resolveForgeContextFromPluginConfig(pluginConfig, remotes) {
311
+ if (!pluginConfig?.forge)
312
+ return null;
313
+ const forge = pluginConfig.forge;
314
+ const provider = forge.provider === "github" || forge.provider === "gitlab" || forge.provider === "auto" ? forge.provider : undefined;
315
+ const selection = resolveProviderSelection({
316
+ config: { provider, baseUrl: forge.base_url },
317
+ remotes
318
+ });
319
+ return selection.ok ? selection.context : null;
320
+ }
321
+ function invalidBaseUrlError(reason) {
322
+ return `Invalid forge.base_url (${reason}) \u2014 provider config rejected; base_url must be an HTTPS URL on a public, ASCII host and is never a trust whitelist.`;
323
+ }
324
+ function resolveProviderSelection(input) {
325
+ const provider = input.config?.provider ?? "auto";
326
+ const remotes = input.remotes;
327
+ let baseUrlHost;
328
+ const rawBaseUrl = input.config?.baseUrl ?? input.config?.base_url;
329
+ if (rawBaseUrl !== undefined) {
330
+ const raw = rawBaseUrl.trim();
331
+ let parsed;
332
+ try {
333
+ parsed = new URL(raw);
334
+ } catch {
335
+ return { ok: false, error: invalidBaseUrlError("not a valid URL") };
336
+ }
337
+ if (parsed.protocol !== "https:") {
338
+ return { ok: false, error: invalidBaseUrlError("must use HTTPS") };
339
+ }
340
+ const host = parsed.hostname.toLowerCase();
341
+ if (hasNonAsciiHostname(host) || hasPunycodeLabel(host)) {
342
+ return {
343
+ ok: false,
344
+ error: invalidBaseUrlError("non-ASCII (IDN) hosts are not allowed")
345
+ };
346
+ }
347
+ if (isPrivateHost(parsed)) {
348
+ return {
349
+ ok: false,
350
+ error: invalidBaseUrlError("private or localhost hosts are not allowed")
351
+ };
352
+ }
353
+ if (!host) {
354
+ return { ok: false, error: invalidBaseUrlError("empty host") };
355
+ }
356
+ baseUrlHost = host;
357
+ }
358
+ if (provider === "github") {
359
+ if (baseUrlHost !== undefined) {
360
+ return {
361
+ ok: false,
362
+ error: 'Provider config conflict: forge.provider is "github" but forge.base_url is set \u2014 GitHub has a fixed base (github.com) and accepts no override. Remove base_url or set provider to "gitlab".'
363
+ };
364
+ }
365
+ return {
366
+ ok: true,
367
+ context: { provider: "github", host: GITHUB_CANONICAL_HOST }
368
+ };
369
+ }
370
+ if (baseUrlHost !== undefined) {
371
+ return { ok: true, context: { provider: "gitlab", host: baseUrlHost } };
372
+ }
373
+ const gitlabHosts = new Set;
374
+ let sawGithub = false;
375
+ let sawUnrecognized = false;
376
+ for (const remote of remotes) {
377
+ const parsed = parseForgeRemoteUrl(remote);
378
+ if (!parsed) {
379
+ sawUnrecognized = true;
380
+ continue;
381
+ }
382
+ if (parsed.provider === "github") {
383
+ sawGithub = true;
384
+ } else {
385
+ gitlabHosts.add(parsed.host);
386
+ }
387
+ }
388
+ if (provider === "gitlab") {
389
+ if (gitlabHosts.size === 1 && !sawGithub && !sawUnrecognized) {
390
+ return {
391
+ ok: true,
392
+ context: { provider: "gitlab", host: [...gitlabHosts][0] }
393
+ };
394
+ }
395
+ return {
396
+ ok: false,
397
+ error: 'Provider config incomplete: forge.provider is "gitlab" but no forge.base_url is set and the git remotes do not unanimously indicate a single GitLab host \u2014 set forge.base_url (e.g. https://gitlab.example.com) in config.'
398
+ };
399
+ }
400
+ if (sawGithub && gitlabHosts.size > 0) {
401
+ return {
402
+ ok: false,
403
+ error: "Provider selection ambiguous: git remotes indicate both GitHub and GitLab \u2014 set forge.provider (and forge.base_url for self-hosted GitLab) explicitly in config."
404
+ };
405
+ }
406
+ if (sawUnrecognized) {
407
+ return {
408
+ ok: false,
409
+ error: "Provider selection ambiguous: a git remote host matches no recognized provider (generic self-hosted) \u2014 set forge.provider and forge.base_url explicitly in config."
410
+ };
411
+ }
412
+ if (sawGithub) {
413
+ return {
414
+ ok: true,
415
+ context: { provider: "github", host: GITHUB_CANONICAL_HOST }
416
+ };
417
+ }
418
+ if (gitlabHosts.size === 1) {
419
+ return {
420
+ ok: true,
421
+ context: { provider: "gitlab", host: [...gitlabHosts][0] }
422
+ };
423
+ }
424
+ if (gitlabHosts.size > 1) {
425
+ return {
426
+ ok: false,
427
+ error: "Provider selection ambiguous: git remotes indicate multiple different GitLab hosts \u2014 set forge.provider and forge.base_url explicitly in config."
428
+ };
429
+ }
430
+ return {
431
+ ok: false,
432
+ error: "Provider selection failed: no workflow-relevant git remote and no forge.base_url \u2014 set forge.provider (and forge.base_url for self-hosted GitLab) explicitly in config."
433
+ };
434
+ }
435
+
436
+ // src/background/pr-subscriptions.ts
46
437
  var PR_SUBSCRIPTIONS_FILE = "pr-monitor/subscriptions.jsonl";
47
438
  var PR_SUBSCRIPTIONS_CHECKPOINT_FILE = "pr-monitor/subscriptions.checkpoint.json";
48
439
  var PR_SUBSCRIPTIONS_AUDIT_FILE = "pr-monitor/subscriptions.audit.jsonl";
@@ -115,8 +506,12 @@ var RecordSchema = exports_external.object({
115
506
  correlationId: exports_external.string().min(1),
116
507
  sessionID: exports_external.string().min(1),
117
508
  prNumber: exports_external.number().int().positive(),
118
- repoFullName: exports_external.string().regex(/^[^/]+\/[^/]+$/, "Must be owner/repo format"),
119
- prUrl: exports_external.string().min(1).regex(/^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+$/, "Must be a valid GitHub PR URL"),
509
+ repoFullName: exports_external.string().regex(/^[^/\s]+(?:\/[^/\s]+)+$/, "Must be owner/repo format (GitLab nested namespaces allowed)"),
510
+ prUrl: exports_external.string().min(1),
511
+ forge: exports_external.object({
512
+ provider: exports_external.literal("gitlab"),
513
+ host: exports_external.string().min(1)
514
+ }).optional(),
120
515
  headRefOid: exports_external.string().optional(),
121
516
  lastCheckedAt: exports_external.number(),
122
517
  lastCommentId: exports_external.string().optional(),
@@ -134,7 +529,21 @@ var RecordSchema = exports_external.object({
134
529
  customPollIntervalSeconds: exports_external.number().int().positive().optional(),
135
530
  customFailureThreshold: exports_external.number().int().min(0).optional(),
136
531
  customCooldownSeconds: exports_external.number().int().min(0).optional()
137
- }).strict();
532
+ }).strict().superRefine((record, ctx) => {
533
+ if (isForgePrUrl(record.prUrl))
534
+ return;
535
+ if (record.forge && isForgePrUrl(record.prUrl, {
536
+ provider: record.forge.provider,
537
+ host: record.forge.host
538
+ })) {
539
+ return;
540
+ }
541
+ ctx.addIssue({
542
+ code: exports_external.ZodIssueCode.custom,
543
+ path: ["prUrl"],
544
+ message: "Must be a valid PR URL (GitHub /pull/N or GitLab /-/merge_requests/N)"
545
+ });
546
+ });
138
547
  var TerminalSummarySchema = exports_external.object({
139
548
  removed: exports_external.number().int().min(0),
140
549
  expired: exports_external.number().int().min(0),
@@ -2050,6 +2459,7 @@ async function subscribe(directory, input) {
2050
2459
  prNumber: input.prNumber,
2051
2460
  repoFullName: input.repoFullName,
2052
2461
  prUrl: input.prUrl,
2462
+ ...input.forge ? { forge: input.forge } : {},
2053
2463
  lastCheckedAt: now,
2054
2464
  isWatching: true,
2055
2465
  hasUnaddressedEvents: false,
@@ -2086,6 +2496,7 @@ async function subscribe(directory, input) {
2086
2496
  prNumber: input.prNumber,
2087
2497
  repoFullName: input.repoFullName,
2088
2498
  prUrl: input.prUrl,
2499
+ ...input.forge ? { forge: input.forge } : {},
2089
2500
  lastCheckedAt: now,
2090
2501
  isWatching: true,
2091
2502
  hasUnaddressedEvents: false,
@@ -2463,4 +2874,4 @@ var _internals = {
2463
2874
  writeCheckpointFile
2464
2875
  };
2465
2876
 
2466
- export { PR_SUBSCRIPTIONS_FILE, PR_SUBSCRIPTIONS_CHECKPOINT_FILE, PR_SUBSCRIPTIONS_AUDIT_FILE, PR_SUBSCRIPTION_LIMITS, setOnSubscriptionCreated, registerPrMonitorWorkerHandler, removePrMonitorWorkerHandler, ensurePrSubscriptionDispatcherInstalled, PrSubscriptionCapacityError, isPrSubscriptionCapacityError, buildCorrelationId, subscribe, unsubscribe, listActive, lookupByPr, updateSnapshot, sweepStale, getPrSubscriptionHealth, _internals };
2877
+ export { containsControlCharacters, hasNonAsciiHostname, isPrivateHost, detectForgeFromUrl, matchForgeResourceUrl, parseForgeRemoteUrl, buildPrUrl, buildIssueUrl, canonicalForgePrUrl, getProviderCapabilities, resolveForgeContextFromPluginConfig, PR_SUBSCRIPTIONS_FILE, PR_SUBSCRIPTIONS_CHECKPOINT_FILE, PR_SUBSCRIPTIONS_AUDIT_FILE, PR_SUBSCRIPTION_LIMITS, setOnSubscriptionCreated, registerPrMonitorWorkerHandler, removePrMonitorWorkerHandler, ensurePrSubscriptionDispatcherInstalled, PrSubscriptionCapacityError, isPrSubscriptionCapacityError, buildCorrelationId, subscribe, unsubscribe, listActive, lookupByPr, updateSnapshot, sweepStale, getPrSubscriptionHealth, _internals };
@@ -4,7 +4,7 @@ import {
4
4
  projectDbExists,
5
5
  withImmediateTransaction,
6
6
  withProjectDbReadOnly
7
- } from "./index-pwcbtbhd.js";
7
+ } from "./index-74yxwf8y.js";
8
8
  import {
9
9
  derivePlanId,
10
10
  derivePlanIdentityHash
@@ -27,11 +27,11 @@ import {
27
27
  import {
28
28
  init_loader,
29
29
  loadPluginConfig
30
- } from "./index-kxacpqwf.js";
30
+ } from "./index-ekyg4p8b.js";
31
31
  import {
32
32
  init_package,
33
33
  package_default
34
- } from "./index-0pvvktht.js";
34
+ } from "./index-rr1dggfe.js";
35
35
  import {
36
36
  criticalWarn,
37
37
  init_logger,
@@ -5,18 +5,18 @@ import {
5
5
  import {
6
6
  effectiveRetrievalOutcomes,
7
7
  readAuthoritativeKnowledgeCounterRollups
8
- } from "./index-48we80k1.js";
8
+ } from "./index-ppj5bjaq.js";
9
9
  import {
10
10
  ALLOWED_SKILL_PATH_PREFIXES,
11
11
  validateSkillPath
12
- } from "./index-0zjg4kt5.js";
12
+ } from "./index-ycqsnfd1.js";
13
13
  import {
14
14
  computeOutcomeSignal,
15
15
  readKnowledge,
16
16
  resolveHiveKnowledgePath,
17
17
  resolveSwarmKnowledgePath,
18
18
  transactKnowledge
19
- } from "./index-y8gxcmnj.js";
19
+ } from "./index-7n3h39h9.js";
20
20
  import {
21
21
  appendCappedJsonl,
22
22
  resolveRetentionCap
@@ -27,7 +27,7 @@ import {
27
27
  import {
28
28
  atomicWriteFileAnyRoot,
29
29
  atomicWriteSwarmFile
30
- } from "./index-bntwj2tp.js";
30
+ } from "./index-yj7etak0.js";
31
31
  import {
32
32
  advisoryWarn,
33
33
  init_warning_buffer
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  captureWorkspaceSnapshotAsync,
4
4
  changedFilesSinceSnapshotAsync
5
- } from "./index-m1pqenq9.js";
5
+ } from "./index-s68z4a39.js";
6
6
  import {
7
7
  removeWorktreeProvisioningOwner
8
- } from "./index-yydv4jfy.js";
8
+ } from "./index-vqz0avr4.js";
9
9
  import {
10
10
  SOURCE_WORKTREE_GONE_STAGE,
11
11
  ensureTaskGateRequirementsReceiptForSettledTransition,
@@ -14,13 +14,13 @@ import {
14
14
  reconcileLandedMerge,
15
15
  withTaskEvidenceTransaction,
16
16
  writeWorkflowWalFile
17
- } from "./index-m8342y3n.js";
17
+ } from "./index-cnbpht7m.js";
18
18
  import {
19
19
  validateSwarmPath
20
- } from "./index-dftztz4y.js";
20
+ } from "./index-afmyp3kt.js";
21
21
  import {
22
22
  appendCoreEventSync
23
- } from "./index-7rzgdcvc.js";
23
+ } from "./index-373880cv.js";
24
24
  import {
25
25
  canonicalRootKeyFresh
26
26
  } from "./index-mc72pk74.js";
@@ -512,7 +512,7 @@ async function cleanupRecoveredWorktree(directory, descriptor, options) {
512
512
  awaitingMergeByCallID,
513
513
  cleanupStandardWorktreeForCallId,
514
514
  standardWorktreeByCallID
515
- } = await import("./worktree-isolation-bmzkxa64.js");
515
+ } = await import("./worktree-isolation-kaxkr61t.js");
516
516
  standardWorktreeByCallID.delete(descriptor.callID);
517
517
  if (hasResidue)
518
518
  awaitingMergeByCallID.set(descriptor.callID, {
@@ -648,7 +648,7 @@ async function recoverCoderSettlement(directory, taskId) {
648
648
  awaitingMergeByCallID,
649
649
  finishStandardWorktreeDispatch,
650
650
  standardWorktreeByCallID
651
- } = await import("./worktree-isolation-bmzkxa64.js");
651
+ } = await import("./worktree-isolation-kaxkr61t.js");
652
652
  const descriptor = wal.worktree;
653
653
  const reconstructedDispatch = {
654
654
  callID: descriptor.callID,
@@ -13,7 +13,7 @@ import {
13
13
  PluginConfigSchema,
14
14
  init_schema,
15
15
  resolveExternalSkillsConfig
16
- } from "./index-0pvvktht.js";
16
+ } from "./index-rr1dggfe.js";
17
17
  import {
18
18
  DangerousMergeKeyError,
19
19
  MAX_MERGE_DEPTH,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  _internals,
4
4
  resolveWorktreeIsolationConfig
5
- } from "./index-bktc2g9n.js";
5
+ } from "./index-7jt24hpz.js";
6
6
  import {
7
7
  ApprovalEvidenceSchema,
8
8
  BaseEvidenceSchema,
@@ -46,7 +46,7 @@ import {
46
46
  loadPluginConfigWithMeta,
47
47
  loadPluginConfigWithMetaAsync,
48
48
  resetConfigAdvisoryDedup
49
- } from "./index-kxacpqwf.js";
49
+ } from "./index-ekyg4p8b.js";
50
50
  import"./index-zxdawwc7.js";
51
51
  import {
52
52
  AUTO_REVIEW_V8_BURN_IN_DECISION,
@@ -72,7 +72,7 @@ import {
72
72
  TurboConfigSchema,
73
73
  WorktreeIsolationConfigSchema,
74
74
  resolveAutoReviewConfig
75
- } from "./index-0pvvktht.js";
75
+ } from "./index-rr1dggfe.js";
76
76
  import {
77
77
  ALL_AGENT_NAMES,
78
78
  ALL_SUBAGENT_NAMES,