@visulima/vis 1.0.0-alpha.37 → 1.0.0-alpha.38

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 (177) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE.md +1 -503
  3. package/dist/bin.js +1 -1
  4. package/dist/binx.js +1 -1
  5. package/dist/config/index.d.ts +7 -0
  6. package/dist/packem_chunks/DEFAULT_CLEAN_KEEP.js +1 -0
  7. package/dist/packem_chunks/bin.js +302 -515
  8. package/dist/packem_chunks/bloom-sync.js +1 -1
  9. package/dist/packem_chunks/catalog-detector.js +1 -0
  10. package/dist/packem_chunks/detect.js +3 -0
  11. package/dist/packem_chunks/detect2.js +8 -0
  12. package/dist/packem_chunks/discord.js +4 -0
  13. package/dist/packem_chunks/dynamic-import.js +1 -0
  14. package/dist/packem_chunks/extra-files.js +3 -0
  15. package/dist/packem_chunks/fix.js +1 -1
  16. package/dist/packem_chunks/git.js +3 -0
  17. package/dist/packem_chunks/handler10.js +1 -1
  18. package/dist/packem_chunks/handler12.js +1 -1
  19. package/dist/packem_chunks/handler13.js +1 -1
  20. package/dist/packem_chunks/handler14.js +1 -1
  21. package/dist/packem_chunks/handler15.js +1 -1
  22. package/dist/packem_chunks/handler16.js +1 -1
  23. package/dist/packem_chunks/handler17.js +1 -1
  24. package/dist/packem_chunks/handler18.js +1 -1
  25. package/dist/packem_chunks/handler19.js +1 -1
  26. package/dist/packem_chunks/handler21.js +1 -1
  27. package/dist/packem_chunks/handler27.js +1 -1
  28. package/dist/packem_chunks/handler28.js +1 -1
  29. package/dist/packem_chunks/handler29.js +1 -1
  30. package/dist/packem_chunks/handler3.js +4 -4
  31. package/dist/packem_chunks/handler30.js +2 -7
  32. package/dist/packem_chunks/handler31.js +2 -33
  33. package/dist/packem_chunks/handler32.js +2 -3
  34. package/dist/packem_chunks/handler33.js +3 -8
  35. package/dist/packem_chunks/handler34.js +6 -4
  36. package/dist/packem_chunks/handler35.js +1 -1
  37. package/dist/packem_chunks/handler36.js +42 -5
  38. package/dist/packem_chunks/handler37.js +8 -11
  39. package/dist/packem_chunks/handler38.js +9 -3
  40. package/dist/packem_chunks/handler39.js +74 -21
  41. package/dist/packem_chunks/handler4.js +1 -1
  42. package/dist/packem_chunks/handler40.js +5 -61
  43. package/dist/packem_chunks/handler41.js +4 -3
  44. package/dist/packem_chunks/handler42.js +3 -6
  45. package/dist/packem_chunks/handler43.js +2 -24
  46. package/dist/packem_chunks/handler44.js +1 -25
  47. package/dist/packem_chunks/handler45.js +1 -153
  48. package/dist/packem_chunks/handler46.js +1 -10
  49. package/dist/packem_chunks/handler47.js +3 -24
  50. package/dist/packem_chunks/handler48.js +1 -322
  51. package/dist/packem_chunks/handler49.js +7 -708
  52. package/dist/packem_chunks/handler5.js +6 -6
  53. package/dist/packem_chunks/handler50.js +33 -48
  54. package/dist/packem_chunks/handler51.js +3 -27
  55. package/dist/packem_chunks/handler52.js +8 -3
  56. package/dist/packem_chunks/handler53.js +4 -200
  57. package/dist/packem_chunks/handler54.js +1 -38
  58. package/dist/packem_chunks/handler55.js +12 -0
  59. package/dist/packem_chunks/handler56.js +7 -0
  60. package/dist/packem_chunks/handler57.js +5 -0
  61. package/dist/packem_chunks/handler58.js +11 -0
  62. package/dist/packem_chunks/handler59.js +3 -0
  63. package/dist/packem_chunks/handler60.js +22 -0
  64. package/dist/packem_chunks/handler61.js +61 -0
  65. package/dist/packem_chunks/handler62.js +3 -0
  66. package/dist/packem_chunks/handler63.js +6 -0
  67. package/dist/packem_chunks/handler64.js +708 -0
  68. package/dist/packem_chunks/handler65.js +24 -0
  69. package/dist/packem_chunks/handler66.js +25 -0
  70. package/dist/packem_chunks/handler67.js +153 -0
  71. package/dist/packem_chunks/handler68.js +10 -0
  72. package/dist/packem_chunks/handler69.js +24 -0
  73. package/dist/packem_chunks/handler7.js +1 -1
  74. package/dist/packem_chunks/handler70.js +322 -0
  75. package/dist/packem_chunks/handler71.js +48 -0
  76. package/dist/packem_chunks/handler72.js +27 -0
  77. package/dist/packem_chunks/handler73.js +3 -0
  78. package/dist/packem_chunks/handler74.js +190 -0
  79. package/dist/packem_chunks/handler75.js +38 -0
  80. package/dist/packem_chunks/handler8.js +1 -1
  81. package/dist/packem_chunks/handler9.js +1 -1
  82. package/dist/packem_chunks/heal-accept.js +1 -1
  83. package/dist/packem_chunks/heal.js +1 -1
  84. package/dist/packem_chunks/help-command.js +1 -1
  85. package/dist/packem_chunks/index.js +1 -7
  86. package/dist/packem_chunks/index2.js +7 -0
  87. package/dist/packem_chunks/interface.js +2 -0
  88. package/dist/packem_chunks/keys-refresh.js +1 -1
  89. package/dist/packem_chunks/list.js +1 -1
  90. package/dist/packem_chunks/loader.js +1 -1
  91. package/dist/packem_chunks/orchestrator.js +39 -0
  92. package/dist/packem_chunks/pre-mode.js +2 -0
  93. package/dist/packem_chunks/print-config.js +2 -0
  94. package/dist/packem_chunks/prompts.js +7 -0
  95. package/dist/packem_chunks/publish-guards.js +1 -0
  96. package/dist/packem_chunks/registry.js +48 -0
  97. package/dist/packem_chunks/resolveFormatter.js +9 -0
  98. package/dist/packem_chunks/security.js +1 -0
  99. package/dist/packem_chunks/shell-runner.js +1 -0
  100. package/dist/packem_chunks/slack.js +2 -0
  101. package/dist/packem_chunks/snapshot.js +2 -0
  102. package/dist/packem_chunks/stage-publisher.js +1 -0
  103. package/dist/packem_chunks/staged-registry.js +2 -0
  104. package/dist/packem_chunks/state.js +3 -0
  105. package/dist/packem_chunks/success-walk.js +8 -0
  106. package/dist/packem_chunks/sync.js +1 -1
  107. package/dist/packem_chunks/sync2.js +1 -1
  108. package/dist/packem_chunks/tripwire.js +1 -1
  109. package/dist/packem_chunks/verify-lockfile.js +2 -2
  110. package/dist/packem_chunks/version-resolver.js +2 -0
  111. package/dist/packem_chunks/webhook.js +1 -0
  112. package/dist/packem_chunks/workflow-templates.js +167 -0
  113. package/dist/packem_chunks/workspace.js +2 -0
  114. package/dist/packem_shared/AfterAllProjectsVersioned-CAKI2nWf.js +1 -0
  115. package/dist/packem_shared/ReleaseClient-YHzBIxYS.js +1 -0
  116. package/dist/packem_shared/VisReleaseError-DMGRBTNO.js +1 -0
  117. package/dist/packem_shared/{ai-analysis-DT3bU-_M.js → ai-analysis-K-DKU3ZA.js} +1 -1
  118. package/dist/packem_shared/{ai-fix-BkNqd5nP.js → ai-fix-BPrYoCk8.js} +1 -1
  119. package/dist/packem_shared/api.d-BPftyU9r.d.ts +27 -0
  120. package/dist/packem_shared/createAdapter-bU4DIP3F.js +1 -0
  121. package/dist/packem_shared/createVersionActions-BK43SNDH.js +1 -0
  122. package/dist/packem_shared/{cyclonedx-86-DbHtf.js → cyclonedx-kYozDyxp.js} +3 -3
  123. package/dist/packem_shared/defineFormatter-D5dCp6Kv.js +1 -0
  124. package/dist/packem_shared/dependency-scan-anTuZB1t.js +1 -0
  125. package/dist/packem_shared/{docker-tNrDU3oK.js → docker-BMLrNtWm.js} +1 -1
  126. package/dist/packem_shared/{failure-log-Dwqt6_Ga.js → failure-log-CEWP3bP0.js} +1 -1
  127. package/dist/packem_shared/index-BJbpNthk.js +1 -0
  128. package/dist/packem_shared/index-CgcF6_wo.js +1 -0
  129. package/dist/packem_shared/{index-dQ37x8_P.js → index-D1_fbGbj.js} +1 -1
  130. package/dist/packem_shared/interface.d-B7VK2rcH.d.ts +148 -0
  131. package/dist/packem_shared/interface.d-Cezzifoh.d.ts +106 -0
  132. package/dist/packem_shared/{missing-package-json-41VUWFBY.js → missing-package-json-BfWUxTGv.js} +1 -1
  133. package/dist/packem_shared/{native-config-sync-BKAZ0NIs.js → native-config-sync-BEkJW7g3.js} +8 -8
  134. package/dist/packem_shared/pm-runner-OGResYrA.js +1 -0
  135. package/dist/packem_shared/provenance-_CJjMKwu.js +1 -0
  136. package/dist/packem_shared/public-api-WqUCiyIe.js +131 -0
  137. package/dist/packem_shared/{registry-keys-Bf2zzlcZ.js → registry-keys-BfFto6vI.js} +1 -1
  138. package/dist/packem_shared/{resolve-explicit-jH0RKyMJ.js → resolve-explicit-CMDl55Nz.js} +2 -2
  139. package/dist/packem_shared/s1ngularity-Dhr3bPk0.js +1 -0
  140. package/dist/packem_shared/{scan-progress-JBbd9QeT.js → scan-progress-DG7_JmTV.js} +1 -1
  141. package/dist/packem_shared/{signatures-D1H6h6GH.js → signatures-C730vkyK.js} +2 -2
  142. package/dist/packem_shared/slug-DoueYuLo.js +1 -0
  143. package/dist/packem_shared/spinner-CV3WVJLv.js +1 -0
  144. package/dist/packem_shared/sticky-comment-D6_7-w8T.js +1 -0
  145. package/dist/packem_shared/{tabs-BqUepRaD.js → tabs-BuTy5gPV.js} +1 -1
  146. package/dist/packem_shared/{typosquats-C8qg1neE.js → typosquats-DN78xx1x.js} +1 -1
  147. package/dist/packem_shared/use-measured-height-_eVGWtWt.js +1 -0
  148. package/dist/packem_shared/verify-6WCmFmy8.js +1 -0
  149. package/dist/packem_shared/{vis-update-app-CTwRkNgj.js → vis-update-app-k3fDxech.js} +1 -1
  150. package/dist/release/core/changelog/index.d.ts +5 -0
  151. package/dist/release/core/changelog/index.js +1 -0
  152. package/dist/release/core/package-managers/index.d.ts +6 -0
  153. package/dist/release/core/package-managers/index.js +1 -0
  154. package/dist/release/core/version-actions/index.d.ts +14 -0
  155. package/dist/release/core/version-actions/index.js +1 -0
  156. package/dist/release/index.d.ts +196 -0
  157. package/dist/release/index.js +1 -0
  158. package/dist/release/plugin-sdk.d.ts +127 -0
  159. package/dist/release/plugin-sdk.js +1 -0
  160. package/dist/release/presets.d.ts +225 -0
  161. package/dist/release/presets.js +1 -0
  162. package/dist/release/types.d.ts +1377 -0
  163. package/dist/release/types.js +1 -0
  164. package/index.d.ts +201 -201
  165. package/index.js +578 -752
  166. package/package.json +52 -10
  167. package/schemas/vis-config.schema.json +1394 -6
  168. package/schemas/vis-release-config.schema.json +1390 -0
  169. package/dist/packem_shared/dependency-scan-BDTH898x.js +0 -1
  170. package/dist/packem_shared/index-CB4p298r.js +0 -1
  171. package/dist/packem_shared/index-DMefdF51.js +0 -1
  172. package/dist/packem_shared/pm-runner-pVihAfxV.js +0 -1
  173. package/dist/packem_shared/provenance-DMuEftgc.js +0 -1
  174. package/dist/packem_shared/s1ngularity-BkfgC6NO.js +0 -1
  175. package/dist/packem_shared/spinner-BXSl864p.js +0 -1
  176. package/dist/packem_shared/use-measured-height-BBJ9intr.js +0 -1
  177. package/dist/packem_shared/verify-Du7xZ2BJ.js +0 -1
@@ -0,0 +1,1377 @@
1
+ /**
2
+ * Public types for the vis release subsystem.
3
+ *
4
+ * Imported via `@visulima/vis/release/types` sub-export. See the RFC at
5
+ * `packages/tooling/vis/rfc/design-release-manager.md` for the full design.
6
+ *
7
+ * Stability: every type here is part of vis's public API surface — breaking
8
+ * changes require a vis major version bump (RFC §21.1).
9
+ */
10
+ type BumpLevel = "major" | "minor" | "patch" | "none";
11
+ declare const BUMP_LEVELS: ReadonlyArray<BumpLevel>;
12
+ /**
13
+ * Numeric ranking used to compare two bump levels.
14
+ * `major` &gt; `minor` &gt; `patch` &gt; `none`.
15
+ */
16
+ declare const bumpRank: (level: BumpLevel) => number;
17
+ /** Take the maximum of two bump levels. */
18
+ declare const maxBump: (a: BumpLevel, b: BumpLevel) => BumpLevel;
19
+ interface ChangeFileSimple {
20
+ /** Map of package-name → bump level. */
21
+ bumps: Record<string, BumpLevel>;
22
+ }
23
+ interface ChangeFileNested {
24
+ /** Bump level for the primary. */
25
+ bump: BumpLevel;
26
+ /** Optional cascade: package-glob → bump level. */
27
+ cascade?: Record<string, BumpLevel>;
28
+ /** Single primary package being bumped. */
29
+ package: string;
30
+ /**
31
+ * Pin the resulting version to this exact value, bypassing the
32
+ * computed bump. Useful for "I need to ship 2.0.0 right now"
33
+ * scenarios. Must be a valid semver string. Maps to release-please's
34
+ * `Release-As: &lt;version>` PR footer.
35
+ *
36
+ * When set, the `bump` field is still required (for tooling
37
+ * consistency + cascade triggering) but the resulting newVersion is
38
+ * `releaseAs` literally, ignored by `bumpVersion`.
39
+ */
40
+ releaseAs?: string;
41
+ }
42
+ interface ChangeFile {
43
+ /** Markdown body — used as changelog entry verbatim. May be empty. */
44
+ body: string;
45
+ /** Slug of the file (filename without `.md` extension). */
46
+ id: string;
47
+ /** Optional inline metadata recognized by github formatter. */
48
+ meta?: {
49
+ author?: string;
50
+ commit?: string;
51
+ pr?: number;
52
+ };
53
+ /** File path relative to the repo root. */
54
+ path: string;
55
+ /** Either-or: simple multi-package or nested with cascade. */
56
+ payload: ChangeFileSimple | ChangeFileNested;
57
+ }
58
+ interface WorkspacePackage {
59
+ /** Absolute directory containing the package. */
60
+ dir: string;
61
+ /** Raw `package.json` contents. */
62
+ manifest: PackageManifest;
63
+ /** Path to `package.json`. */
64
+ manifestPath: string;
65
+ /** Package name from `package.json#name`. */
66
+ name: string;
67
+ /** Whether `package.json#private === true`. */
68
+ private: boolean;
69
+ /** Current version from `package.json#version`. */
70
+ version: string;
71
+ }
72
+ interface PackageManifest {
73
+ [key: string]: unknown;
74
+ dependencies?: Record<string, string>;
75
+ devDependencies?: Record<string, string>;
76
+ name: string;
77
+ napi?: Record<string, unknown>;
78
+ optionalDependencies?: Record<string, string>;
79
+ peerDependencies?: Record<string, string>;
80
+ private?: boolean;
81
+ publishConfig?: Record<string, unknown>;
82
+ version: string;
83
+ "vis-release"?: PerPackageReleaseConfig;
84
+ }
85
+ type DependencyKind = "dependencies" | "devDependencies" | "peerDependencies" | "optionalDependencies";
86
+ interface DependentInfo {
87
+ /** Which dep field the source appears in. */
88
+ kind: DependencyKind;
89
+ /** Package depending on the source. */
90
+ name: string;
91
+ /** The raw range string (`workspace:^1.2.3`, `^1.2.3`, `catalog:dev`, etc.). */
92
+ range: string;
93
+ }
94
+ /**
95
+ * Why a particular package ended up in the release plan.
96
+ * Used for log lines and changelog attribution.
97
+ */
98
+ type BumpReason = "EXPLICIT" | "DEPENDENCY_OUT_OF_RANGE" | "DEPENDENCY_BUMPED" | "DEVDEPENDENCY_BUMPED" | "CASCADE" | "CASCADE_TO" | "CATALOG_CHANGED" | "FIXED_GROUP" | "LINKED_GROUP" | "PEER_DEP_MATCH";
99
+ interface BumpSource {
100
+ bumpType: BumpLevel;
101
+ name: string;
102
+ newVersion: string;
103
+ }
104
+ interface PlannedRelease {
105
+ /** Change files contributing to this release (may be empty for pure dep bumps). */
106
+ changeFiles: ChangeFile[];
107
+ /** True when bumped by a cascade rule. */
108
+ isCascadeBump: boolean;
109
+ /** True when no change file directly named this package. */
110
+ isDependencyBump: boolean;
111
+ /** True when bumped by a fixed/linked group. */
112
+ isGroupBump: boolean;
113
+ /** Package name. */
114
+ name: string;
115
+ /** Post-bump version. */
116
+ newVersion: string;
117
+ /** Pre-bump version. */
118
+ oldVersion: string;
119
+ /** Reason this package made it into the plan. */
120
+ reasons: BumpReason[];
121
+ /** Sources that triggered cascading bumps (for changelog attribution). */
122
+ sources: BumpSource[];
123
+ /** Bump level applied. */
124
+ type: Exclude<BumpLevel, "none">;
125
+ }
126
+ interface ReleasePlan {
127
+ /** Change files consumed by this plan (deleted on `vis release version`). */
128
+ consumedChangeFiles: ChangeFile[];
129
+ /** Sorted alphabetically by package name. */
130
+ releases: PlannedRelease[];
131
+ /** Non-fatal warnings to surface to the user. */
132
+ warnings: string[];
133
+ }
134
+ type ChannelMode = "auto-publish" | "version-pr";
135
+ interface ChannelConfig {
136
+ /** CI behavior: `auto-publish` (push triggers publish) or `version-pr` (review gate). */
137
+ mode?: ChannelMode;
138
+ /** Pre-release identifier (e.g. `"alpha"`, `"beta"`, `"rc"`). Omit for stable channels. */
139
+ prerelease?: string;
140
+ /** For maintenance branches: `"match"` keeps releases inside the branch's semver range. */
141
+ range?: string;
142
+ /** npm dist-tag for publishes on this channel. Use `"branch-name"` to mirror the branch name. */
143
+ tag: string;
144
+ }
145
+ type BumpAs = BumpLevel | "match";
146
+ interface DependencyBumpRule {
147
+ /** Bump level to apply to the dependent. `"match"` = same as source. */
148
+ bumpAs: BumpAs;
149
+ /** Minimum source bump that activates this rule. */
150
+ trigger: BumpLevel;
151
+ }
152
+ type DependencyBumpRules = Partial<Record<DependencyKind, DependencyBumpRule | false>>;
153
+ type UpdateInternalDependenciesMode = "patch" | "minor" | "out-of-range";
154
+ /**
155
+ * Per-group changelog routing.
156
+ *
157
+ * - `"per-package"` (default) — every member writes to its own
158
+ * `&lt;pkg-dir>/CHANGELOG.md` exactly as if it weren't grouped.
159
+ * - `"shared"` — every member's entry is rendered into ONE shared
160
+ * file. `path` overrides the default location
161
+ * (`&lt;first-member-dir>/GROUP-CHANGELOG.md`). Useful for `core/utils`
162
+ * pairs and other tightly-coupled package sets where one
163
+ * consolidated changelog reads better than N tiny ones.
164
+ */
165
+ interface ReleaseGroupChangelogConfig {
166
+ mode: "per-package" | "shared";
167
+ /** Override file path. Default: `&lt;first-member-dir>/GROUP-CHANGELOG.md`. */
168
+ path?: string;
169
+ }
170
+ /**
171
+ * Dual-shape config for `release.fixed` / `release.linked` entries.
172
+ *
173
+ * Bare `string[]` is interpreted as `{ packages, changelog: { mode: "per-package" } }`
174
+ * — keeps existing configs working without migration.
175
+ */
176
+ type ReleaseGroupConfig = string[] | {
177
+ changelog?: ReleaseGroupChangelogConfig;
178
+ /**
179
+ * Optional name for the group. Used as the heading in the
180
+ * shared changelog when set; defaults to a "group-N"-style
181
+ * identifier derived from the array index.
182
+ */
183
+ name?: string;
184
+ /** Package names or globs that belong to this group. */
185
+ packages: string[];
186
+ };
187
+ /**
188
+ * Normalise a `ReleaseGroupConfig` (bare array or object form) into the
189
+ * object form. Centralised so plan-assembly, changelog routing, and
190
+ * print-config all see the same shape.
191
+ */
192
+ declare const normaliseGroup: (group: ReleaseGroupConfig) => {
193
+ changelog: ReleaseGroupChangelogConfig;
194
+ name?: string;
195
+ packages: string[];
196
+ };
197
+ type SnapshotTagKind = "sha" | "short-sha" | "branch" | "pr";
198
+ type SnapshotBackend = "pkg-pr-new" | "registry" | {
199
+ auth?: string;
200
+ url: string;
201
+ };
202
+ /**
203
+ * Common fields shared across built-in notification channels.
204
+ * `id` is an operator-supplied disambiguator that surfaces in log lines
205
+ * when fanning out to multiple instances of the same channel kind
206
+ * (e.g. `slack:engineering` vs `slack:releases`).
207
+ */
208
+ interface CommonChannelConfig {
209
+ /** Optional disambiguator for log lines + doctor checks. */
210
+ id?: string;
211
+ /** Skip the `Skipped (N):` block. Default false (skipped are surfaced). */
212
+ includeSkipped?: boolean;
213
+ /**
214
+ * Title template — see `expandNotificationTemplate` for tokens
215
+ * (`{count}`, `{packages}`, `{firstName}`, `{firstVersion}`,
216
+ * `{channel}`, `{repo}`, `{date}`). When omitted, a sensible
217
+ * "🚀 Released N packages" default is used.
218
+ */
219
+ title?: string;
220
+ }
221
+ interface SlackConfig extends CommonChannelConfig {
222
+ /**
223
+ * Override the channel the webhook posts to. Only honoured when
224
+ * the webhook was created with multi-channel posting allowed (rare).
225
+ */
226
+ channelOverride?: string;
227
+ /** Bot icon emoji (e.g. `":rocket:"`). */
228
+ iconEmoji?: string;
229
+ /** Bot display name override. */
230
+ username?: string;
231
+ /**
232
+ * Slack incoming-webhook URL. Workspace+channel scoped. Use env
233
+ * substitution if you don't want it inline:
234
+ * `webhook: "${SLACK_WEBHOOK_URL}"`.
235
+ */
236
+ webhook: string;
237
+ }
238
+ interface DiscordConfig extends CommonChannelConfig {
239
+ /** Override the embed avatar. */
240
+ avatarUrl?: string;
241
+ /** Embed colour as an integer RGB (e.g. `0x3B82F6` = blue-500). */
242
+ color?: number;
243
+ /** Bot display name override. */
244
+ username?: string;
245
+ /** Discord webhook URL. Server+channel scoped. */
246
+ webhook: string;
247
+ }
248
+ interface WebhookConfig extends CommonChannelConfig {
249
+ /**
250
+ * Body template. When omitted, the full `NotificationContext` is
251
+ * sent verbatim as JSON. When provided, every string leaf is run
252
+ * through `expandNotificationTemplate`.
253
+ */
254
+ body?: unknown;
255
+ /** Additional headers (values run through template interpolation). */
256
+ headers?: Record<string, string>;
257
+ /** HTTP method. Default `POST`. */
258
+ method?: "POST" | "PUT";
259
+ /** Target URL. */
260
+ url: string;
261
+ }
262
+ interface NotificationsConfig {
263
+ /**
264
+ * Built-in Discord channel(s). Single config or array. Each posts a
265
+ * formatted embed with title + bullet-list of packages.
266
+ */
267
+ discord?: DiscordConfig | DiscordConfig[];
268
+ /**
269
+ * Custom channels loaded from a path. The module must export a
270
+ * default `NotificationChannel` (object with `.send`) OR a factory
271
+ * `(options) => NotificationChannel` for the tuple `[path, options]`
272
+ * form.
273
+ */
274
+ plugins?: (string | [string, Record<string, unknown>])[];
275
+ /**
276
+ * Skip notifications on prerelease waves (when every published
277
+ * version has a `-…` suffix). Default `true` — most teams want
278
+ * Slack noise only on stable releases.
279
+ */
280
+ skipPrerelease?: boolean;
281
+ /**
282
+ * Built-in Slack channel(s). Each posts a Block Kit message with
283
+ * a header + package list + context block.
284
+ */
285
+ slack?: SlackConfig | SlackConfig[];
286
+ /** Generic webhook(s) for Teams / Mattermost / internal dashboards. */
287
+ webhook?: WebhookConfig | WebhookConfig[];
288
+ }
289
+ interface SnapshotConfig {
290
+ backend?: SnapshotBackend;
291
+ /** Whether to delete published snapshots on PR-close (no-op for `pkg-pr-new`). */
292
+ cleanupOnPrClose?: boolean;
293
+ /** When backend is `pkg-pr-new`, the registry URL is supplied automatically. */
294
+ registry?: string;
295
+ /** Multi-tag publish — pick which tag types to emit per snapshot. */
296
+ tags?: SnapshotTagKind[];
297
+ /** Version template — interpolation tokens: `{tag}`, `{shortSha}`, `{sha}`, `{branch}`, `{pr}`, `{timestamp}`. */
298
+ versionTemplate?: string;
299
+ }
300
+ interface PerPackageReleaseConfig {
301
+ /**
302
+ * Extra directories (or globs) that logically belong to this package.
303
+ * Used by `vis release check --strict` to attribute changes outside
304
+ * the package's own directory to this package — e.g. a shared
305
+ * `docs/api/` directory whose updates should still trip the
306
+ * "covered by a change file?" gate for the package they document.
307
+ *
308
+ * Globs are workspace-root-relative (NOT package-directory-relative).
309
+ * Examples:
310
+ *
311
+ * ```ts
312
+ * release: {
313
+ * packages: {
314
+ * "@scope/cli": {
315
+ * additionalPaths: ["docs/cli/**", "examples/cli/**"],
316
+ * },
317
+ * },
318
+ * }
319
+ * ```
320
+ *
321
+ * Default: `undefined` (only the package's own directory is
322
+ * attributed to it). Release-please parity: #1921.
323
+ */
324
+ additionalPaths?: string[];
325
+ /** Custom shell command run before publish (requires `allowCustomCommands`). */
326
+ buildCommand?: string;
327
+ /**
328
+ * Build context passed to `docker buildx build` (the final positional
329
+ * argument). Honoured by the `container` versionActions; defaults to
330
+ * the package directory.
331
+ */
332
+ buildContext?: string;
333
+ /**
334
+ * Relative path from the package directory to `Cargo.toml` for the
335
+ * `cargo` versionActions. Set automatically by the `cargo()` preset
336
+ * from its `crateDir` option. Defaults to `"Cargo.toml"`.
337
+ */
338
+ cargoTomlPath?: string;
339
+ /** Source-side cascade: glob → rule. */
340
+ cascadeTo?: Record<string, DependencyBumpRule>;
341
+ /** Per-pkg override of `release.changedFilePatterns`. Replaces (does not merge). */
342
+ changedFilePatterns?: string[];
343
+ /** Custom shell command that prints currently-published version to stdout. */
344
+ checkPublished?: string;
345
+ /**
346
+ * Extra `--build-arg KEY=VALUE` pairs forwarded to `docker buildx
347
+ * build`. Useful for stamping the version into the image at build
348
+ * time. Consumed by the `container` versionActions.
349
+ */
350
+ containerBuildArgs?: Record<string, string>;
351
+ /**
352
+ * Fully-qualified container image reference, e.g.
353
+ * `"ghcr.io/scope/foo"`. Required by the `container` versionActions
354
+ * (no built-in default since the registry hostname is operator-
355
+ * specific). Set automatically by the `container()` preset.
356
+ */
357
+ containerImage?: string;
358
+ /**
359
+ * Target platforms passed to `docker buildx build --platform`.
360
+ * Defaults to `["linux/amd64", "linux/arm64"]`. Single-arch builds
361
+ * can pass a one-entry array.
362
+ */
363
+ containerPlatforms?: ReadonlyArray<string>;
364
+ /**
365
+ * Post-push signing scheme for the `container` versionActions.
366
+ * `"cosign"` runs `cosign sign --yes &lt;image>:&lt;version>` against the
367
+ * just-pushed immutable tag. Future schemes (sigstore-bundle,
368
+ * notation, etc.) can extend this union.
369
+ */
370
+ containerSigning?: "cosign";
371
+ /**
372
+ * Skip the conventional `:latest` floating tag on push. Useful for
373
+ * pre-release / channel-specific images that shouldn't move the
374
+ * shared `latest` pointer.
375
+ */
376
+ containerSkipLatest?: boolean;
377
+ /**
378
+ * Per-package override of the workspace-level `currentVersionResolver`.
379
+ * Same set of modes: `"disk"`, `"registry"`, `"git-tag"`. Useful when
380
+ * one package in the monorepo lags behind the registry / git-tag baseline
381
+ * (e.g. a newly-added package that hasn't been published yet).
382
+ */
383
+ currentVersionResolver?: "disk" | "git-tag" | "registry";
384
+ /** Per-pkg override of inbound dep-bump rules. */
385
+ dependencyBumpRules?: DependencyBumpRules;
386
+ /**
387
+ * Per-package `extra-files` rules with paths relative to the
388
+ * package directory. Merged with workspace-level
389
+ * `release.publish.extraFiles` (per-package wins on path collision).
390
+ */
391
+ extraFiles?: ExtraFileRule[];
392
+ /**
393
+ * Relative path from the package directory to the JSR manifest
394
+ * (`jsr.json` or `deno.json`) for the `jsr` versionActions. Set
395
+ * automatically by the `jsr()` preset from its `manifestPath`
396
+ * option. Defaults to `"jsr.json"`.
397
+ */
398
+ jsrConfigPath?: string;
399
+ /**
400
+ * Extra arguments forwarded verbatim to `jsr publish` for the `jsr`
401
+ * versionActions (the `jsr()` preset wires this from its `publishArgs` /
402
+ * `allowSlowTypes` options). The most common entry is
403
+ * `"--allow-slow-types"`, which JSR requires for packages whose public
404
+ * API has types it can't statically infer. `--allow-dirty` is always
405
+ * passed by vis (the version is bumped on disk before publish) and need
406
+ * not be listed here.
407
+ */
408
+ jsrPublishArgs?: string[];
409
+ /** Hard opt-in/out — overrides every other rule. */
410
+ managed?: boolean;
411
+ /**
412
+ * Override the Maven Central metadata URL used by the `maven`
413
+ * versionActions for already-published detection. Set this when
414
+ * publishing to a custom repository (Artifactory, Nexus, GitHub
415
+ * Packages); the URL should point at
416
+ * `&lt;base>/&lt;groupId>/&lt;artifactId>/maven-metadata.xml`. Pass `""`
417
+ * (empty string) to disable the metadata check entirely.
418
+ */
419
+ mavenMetadataUrl?: string;
420
+ /**
421
+ * Override the path to `pom.xml` for the `maven` versionActions,
422
+ * relative to the package directory. Defaults to `"pom.xml"`.
423
+ */
424
+ pomPath?: string;
425
+ /** Custom shell command run instead of `npm publish` (requires `allowCustomCommands`). */
426
+ publishCommand?: string | string[];
427
+ /**
428
+ * Relative path from the package directory to the directory
429
+ * containing `pyproject.toml` for the `python` versionActions.
430
+ * Set automatically by the `pyproject()` preset from its
431
+ * `projectDir` option. Defaults to the package directory.
432
+ */
433
+ pythonProjectDir?: string;
434
+ /** Custom registry URL (overrides `publish.registry`). */
435
+ registry?: string;
436
+ /**
437
+ * Override the workspace-wide releaseTagPattern.
438
+ * Tokens: `{name}`, `{unscopedName}`, `{version}`, `{major}`, `{minor}`,
439
+ * `{patch}`, `{date}`, `{channel}`.
440
+ */
441
+ releaseTagPattern?: string;
442
+ /** Skip the npm publish step but still create a git tag. */
443
+ skipNpmPublish?: boolean;
444
+ /**
445
+ * Relative path from the package directory (or workspace root, for
446
+ * uv-workspace setups) to `uv.lock`. Set when the operator wants
447
+ * vis to acknowledge a uv-managed lockfile during doctor checks.
448
+ *
449
+ * vis does NOT mutate `uv.lock` itself — uv regenerates it on
450
+ * `uv sync` / `uv build`. The path is recorded only so doctor can
451
+ * warn when the file is missing despite the operator configuring
452
+ * uv-aware tooling. Operators wanting `uv.lock` in the release
453
+ * commit should run `uv lock` between `vis release version` and
454
+ * the commit step (typically wired via `postVersionCommand`).
455
+ *
456
+ * release-please parity: #2561.
457
+ */
458
+ uvLockPath?: string;
459
+ /**
460
+ * uv workspace configuration. When set, the `python` versionActions
461
+ * and the `pyproject()` preset treat this package as a member of a
462
+ * uv workspace rooted at `uvWorkspace.root` (relative to the package
463
+ * directory — typically `".."` or the path up to the repo root).
464
+ *
465
+ * Doctor checks:
466
+ * - the root's pyproject.toml exists at `&lt;root>/pyproject.toml`
467
+ * - `[tool.uv.workspace] members` lists the package's project
468
+ * directory (relative path from the workspace root)
469
+ *
470
+ * Set automatically by the `pyproject({ uvWorkspace })` preset.
471
+ *
472
+ * release-please parity: #2560.
473
+ */
474
+ uvWorkspace?: {
475
+ root: string;
476
+ };
477
+ /**
478
+ * Built-in id (`"npm"`, `"native-addon"`, `"private"`, `"shell"`,
479
+ * `"cargo"`, `"python"`, `"maven"`, `"container"`, `"jsr"`) or a
480
+ * path to a custom implementation module.
481
+ */
482
+ versionActions?: string;
483
+ }
484
+ interface CleanPackageJsonConfig {
485
+ /** Fields to keep — overrides default strip behaviour. */
486
+ keep?: string[];
487
+ /** Fields to strip from the published package.json (extends defaults). */
488
+ strip?: string[];
489
+ }
490
+ type ProtocolResolutionMode = "pack" | "in-place" | "none";
491
+ type CatalogResolutionMode = "auto" | "in-place" | "delegate";
492
+ type PublishStrategy = "npm-publish-tarball" | "native";
493
+ type PackManager = "auto" | "npm" | "pnpm" | "yarn" | "bun";
494
+ /**
495
+ * Pre-publish security gates — run after the manifest is rewritten and the
496
+ * tarball is packed but BEFORE `npm publish` is invoked. Each gate is opt-in;
497
+ * defaults aim for "useful for new repos, easy to disable for established ones".
498
+ */
499
+ interface PublishGuardsConfig {
500
+ /**
501
+ * Run `npm audit --omit=dev` against the resolved package and fail at the
502
+ * configured severity. Skips devDependency CVEs (which don't ship to
503
+ * consumers). `"off"` disables.
504
+ */
505
+ audit?: "critical" | "high" | "low" | "moderate" | "off";
506
+ /**
507
+ * Verify every leaf path declared in `package.json#exports` /
508
+ * `main` / `module` / `types` / `bin` exists post-build. Wildcard exports
509
+ * (`./feat/*.js`) check that the directory is non-empty after build.
510
+ *
511
+ * Catches "deleted file but forgot to update exports" before publish.
512
+ */
513
+ exportsExist?: boolean;
514
+ /**
515
+ * Gate on lifecycle scripts (`preinstall` / `install` / `postinstall`)
516
+ * declared on the package being published. These run on the consumer's
517
+ * machine at install time, so unauthorized additions are a supply-chain
518
+ * vector.
519
+ *
520
+ * Modes: `"off"` (skip), `"warn"` (log + continue), `"strict"` (fail).
521
+ * Object form provides an exact-match `allow` table — only commands matching
522
+ * the listed value pass through.
523
+ */
524
+ lifecycleScripts?: "off" | "strict" | "warn" | {
525
+ allow?: Record<string, string>;
526
+ mode: "off" | "strict" | "warn";
527
+ };
528
+ /**
529
+ * Scan the resolved tarball contents (post `npm pack`) for secrets.
530
+ * Catches `.npmignore`/`files` misconfigurations that would ship `.env`,
531
+ * AWS keys, etc. Different scope than log redaction — this gates what
532
+ * actually leaves the machine.
533
+ *
534
+ * `true` runs the default `@visulima/secret-scanner` ruleset.
535
+ * Object form lets callers narrow the rule set or skip files.
536
+ */
537
+ packSecretScan?: boolean | {
538
+ ignore?: string[];
539
+ };
540
+ }
541
+ /**
542
+ * Optional asset-attestation work done after a successful publish. Both
543
+ * GitHub and GitLab adapters honor these knobs — GitHub uploads the .tgz
544
+ * directly, GitLab uses the project upload endpoint registered as a release
545
+ * link. SHA256/SHA512 are stamped into the release body either way so
546
+ * consumers can verify the registry tarball matches the audited build.
547
+ */
548
+ /**
549
+ * Regex-based file-substitution rule used by `publish.extraFiles`
550
+ * (workspace) or `packages.&lt;name>.extraFiles` (per-package) to keep
551
+ * version strings in non-package.json files in sync with the release.
552
+ */
553
+ interface ExtraFileRegexRule {
554
+ /** Regex flags (default `"g"`). Combine as needed: `"gm"`, `"gmi"`, etc. */
555
+ flags?: string;
556
+ /**
557
+ * File path. Workspace-root-relative when declared on
558
+ * `release.publish.extraFiles`; package-directory-relative when on
559
+ * `release.packages.&lt;name>.extraFiles`.
560
+ */
561
+ path: string;
562
+ /**
563
+ * Substitution template. `{version}` is replaced with the new
564
+ * version literal. Standard regex backreferences (`$1`, `$2`, `$&amp;`)
565
+ * work too. When omitted, the entire match is replaced with the new
566
+ * version.
567
+ */
568
+ replace?: string;
569
+ /** JavaScript regex source (without delimiters). */
570
+ search: string;
571
+ /**
572
+ * Explicit type discriminator. Defaults to `"regex"` when omitted —
573
+ * legacy rules without a `type` field continue to work as regex rules.
574
+ */
575
+ type?: "regex";
576
+ }
577
+ /**
578
+ * Annotation-comment file-substitution rule — release-please parity.
579
+ *
580
+ * Instead of authoring a regex, the operator drops an `x-release-please-
581
+ * version` (or custom-named) marker comment in the target file and vis
582
+ * locates the semver-shaped substring on the marked line (or the line
583
+ * immediately following an own-line marker) and replaces it with the
584
+ * new version. Far more ergonomic than the regex form for the common
585
+ * case of "bump this version string here".
586
+ *
587
+ * Two recognised placements:
588
+ *
589
+ * 1. **Inline** — marker on the same line as the version:
590
+ * ```ts
591
+ * export const VERSION = "0.1.0"; // x-release-please-version
592
+ * ```
593
+ *
594
+ * 2. **Preceding-line** — marker on the line just above the version:
595
+ * ```dockerfile
596
+ * # x-release-please-version
597
+ * ENV APP_VERSION="0.1.0"
598
+ * ```
599
+ *
600
+ * Like the regex path, missing files / no marker found surface as
601
+ * `plan.warnings` rather than throwing.
602
+ */
603
+ interface ExtraFileAnnotationRule {
604
+ /**
605
+ * Limit the semver-replacement to occurrences anchored by this
606
+ * literal prefix on the marked line. Useful when the file has
607
+ * multiple version-shaped substrings (e.g. a lockfile or a
608
+ * Dockerfile referencing both APP_VERSION and a base-image tag).
609
+ *
610
+ * Example — `ENV APP_VERSION="0.1.0"` with `anchor: "APP_VERSION"`
611
+ * only touches the version after that prefix. When omitted, the
612
+ * FIRST semver substring on the marked line is replaced.
613
+ *
614
+ * **Strongly recommended** for any file that contains more than one
615
+ * version-shaped substring (lockfiles, Dockerfiles with both APP
616
+ * and base-image tags, multi-version compose files). The default
617
+ * "first semver wins" behaviour is convenient for single-version
618
+ * files but a footgun on lockfiles — annotating a `package-lock
619
+ * .json` without an anchor would happily rewrite the first nested
620
+ * dep's `version`.
621
+ */
622
+ anchor?: string;
623
+ /**
624
+ * Override the marker string. Default `"x-release-please-version"`
625
+ * (release-please compatibility). Match is plain substring (no
626
+ * regex), case-sensitive.
627
+ */
628
+ marker?: string;
629
+ /**
630
+ * File path. Workspace-root-relative when declared on
631
+ * `release.publish.extraFiles`; package-directory-relative when on
632
+ * `release.packages.&lt;name>.extraFiles`.
633
+ */
634
+ path: string;
635
+ /**
636
+ * Switch to annotation-comment mode. The substitution engine looks
637
+ * for lines tagged with the configured marker — by default
638
+ * `x-release-please-version` (release-please compatibility). The
639
+ * marked line (or the line immediately following an own-line marker)
640
+ * has its semver-shaped substring replaced with the new version.
641
+ */
642
+ type: "annotation";
643
+ }
644
+ /**
645
+ * Union of every extra-files rule shape. The regex form is the historical
646
+ * default; the annotation form was added for release-please ergonomics.
647
+ *
648
+ * When `type` is omitted, the rule is treated as a regex rule (preserves
649
+ * backwards-compat for every existing vis.config.ts in the wild).
650
+ */
651
+ type ExtraFileRule = ExtraFileAnnotationRule | ExtraFileRegexRule;
652
+ interface ReleaseAssetsConfig {
653
+ /**
654
+ * Compute SHA256 + SHA512 of the published tarball and append them to
655
+ * the release body. Lets consumers verify the registry tarball matches
656
+ * the audited build, defending against post-publish substitution.
657
+ */
658
+ stampHashes?: boolean;
659
+ /**
660
+ * Upload the published tarball as a release asset alongside the GH
661
+ * release. Belt-and-suspenders alongside `stampHashes` — registry
662
+ * tampering is detectable by hash comparison.
663
+ */
664
+ uploadTarball?: boolean;
665
+ }
666
+ interface PublishConfig {
667
+ /**
668
+ * Semantic-release/github parity — when set, prepend ("top") or append
669
+ * ("bottom") a "Related releases" block to the per-package GitHub release
670
+ * body that links to the immediately previous N releases of the same
671
+ * package. Aids navigation in the Releases UI ("what did 1.4.2 fix?" is a
672
+ * single click from 1.5.0's release page).
673
+ *
674
+ * Honoured only on the GitHub adapter; GitLab logs a warning and skips
675
+ * the block. Aggregate-release mode is skipped — there's no per-package
676
+ * prior release to point at.
677
+ *
678
+ * Default `false` (no link block).
679
+ */
680
+ addReleases?: false | "bottom" | "top";
681
+ /** How to resolve `catalog:` protocols. */
682
+ catalogResolution?: CatalogResolutionMode;
683
+ /** Strip/keep config for the published `package.json`. `false` ships unmodified. */
684
+ cleanPackageJson?: boolean | CleanPackageJsonConfig;
685
+ /**
686
+ * GitHub-only: link each created release to a Discussion in the
687
+ * named category (e.g. `"Announcements"`, `"Releases"`). The
688
+ * category must already exist on the repository; GitHub creates the
689
+ * discussion automatically. Ignored on GitLab.
690
+ */
691
+ discussionCategory?: string;
692
+ /**
693
+ * Create the forge release (GitHub Release / GitLab Release) as a
694
+ * draft. A draft release is invisible to consumers until a human
695
+ * publishes it through the UI — useful when release notes need a
696
+ * human review before going public. Default `false`.
697
+ *
698
+ * Maps to GitHub's `draft: true` API field and GitLab's released_at
699
+ * being absent (GitLab models drafts implicitly via no released_at).
700
+ */
701
+ draftRelease?: boolean;
702
+ /**
703
+ * Bump version strings in arbitrary files alongside package.json.
704
+ * Each rule's `path` is workspace-root-relative; per-package rules
705
+ * (under `packages.&lt;name>.extraFiles`) resolve relative to the
706
+ * package directory.
707
+ *
708
+ * The `search` is a JavaScript regex source. Default `flags: "g"`
709
+ * for global replacement. The `replace` template supports the
710
+ * `{version}` token and standard regex backreferences (`$1`, `$2`,
711
+ * `$&amp;`, etc.). When `replace` is absent, the entire match is
712
+ * substituted with the new version.
713
+ *
714
+ * Examples — README badge, TS constant, Cargo.toml field:
715
+ * `{ path: "README.md", search: "v\\d+\\.\\d+\\.\\d+" }`
716
+ * `{ path: "src/version.ts", search: 'VERSION = "[^"]+"',
717
+ * replace: 'VERSION = "{version}"' }`
718
+ * `{ path: "Cargo.toml", search: '^version = "[^"]+"',
719
+ * replace: 'version = "{version}"', flags: "m" }`
720
+ *
721
+ * Failed matches are non-fatal — the publish carries on, but a
722
+ * warning surfaces so misconfigured rules don't silently rot.
723
+ */
724
+ extraFiles?: ExtraFileRule[];
725
+ /** Pre-publish security gates. Each gate is opt-in. */
726
+ guards?: PublishGuardsConfig;
727
+ /**
728
+ * Skip creating the GitHub / GitLab Release entirely while still
729
+ * pushing the git tag and publishing the package to the registry.
730
+ * Useful for teams that maintain release notes elsewhere (a docs
731
+ * site, in-product changelog, etc.) and don't want the duplicate
732
+ * forge artifact.
733
+ *
734
+ * Default `false`. Release-please parity: #1295.
735
+ */
736
+ noRelease?: boolean;
737
+ /** Which manager to invoke for `&lt;pm> pack`. */
738
+ packManager?: PackManager;
739
+ /**
740
+ * Auth-precedence escape hatch for the multi-language actions
741
+ * (cargo, python). Default `false`.
742
+ *
743
+ * Default behaviour (false): when both an OIDC env signal
744
+ * (`ACTIONS_ID_TOKEN_REQUEST_URL`) AND a static token
745
+ * (`CARGO_REGISTRY_TOKEN` / `TWINE_PASSWORD`) are present, OIDC
746
+ * wins — an operator who enabled OIDC trusted publishing wants
747
+ * OIDC by default and a leftover token in the env shouldn't
748
+ * silently switch auth modes (M-3).
749
+ *
750
+ * Set `true` to flip the precedence: when both signals are
751
+ * present, the static token wins. Useful for operators migrating
752
+ * off OIDC, shadow-publishing during a cutover, or working around
753
+ * a temporary trusted-publishing outage at the registry.
754
+ */
755
+ preferStaticToken?: boolean;
756
+ /** How to resolve `workspace:` protocols. */
757
+ protocolResolution?: ProtocolResolutionMode;
758
+ /** Extra args appended to publish (`--provenance`, etc.). Skipped for managers that don't support them. */
759
+ publishArgs?: string[];
760
+ /** Publish strategy — see RFC §11.3. */
761
+ publishStrategy?: PublishStrategy;
762
+ /** Override default registry. */
763
+ registry?: string;
764
+ /** Post-publish asset attestation work. */
765
+ releaseAssets?: ReleaseAssetsConfig;
766
+ /**
767
+ * Use npm's staged-publishing flow (`npm stage publish`) instead of
768
+ * `npm publish`. The published version is invisible to consumers until
769
+ * a maintainer approves it via 2FA (`vis release stage approve` or the
770
+ * npmjs.com web UI). Requires npm CLI ≥ 11.15.0 and `registry.npmjs.org`
771
+ * as the registry; doctor warns when those preconditions aren't met.
772
+ *
773
+ * Publish blocks on the human-review gate so downstream pipeline steps
774
+ * (tags, GH release, post-hooks) only run against actually-live packages.
775
+ * Rejection and timeout are NOT CI failures — they flow through the
776
+ * skipped[] result so `vis release publish` exits 0; the unapproved
777
+ * package just doesn't get its downstream side-effects.
778
+ *
779
+ * Pass `true` for defaults (30-min timeout, 15s poll). Pass an object
780
+ * to override per-workspace. Snapshots always publish directly (preview
781
+ * content shouldn't gate on review).
782
+ */
783
+ stage?: boolean | {
784
+ /**
785
+ * Sleep between consecutive `npm stage view` checks while waiting.
786
+ * Default: 15_000 (15 seconds).
787
+ */
788
+ pollIntervalMs?: number;
789
+ /**
790
+ * Hard deadline before the wait gives up and skips the publish.
791
+ * Default: 1_800_000 (30 minutes).
792
+ */
793
+ timeoutMs?: number;
794
+ };
795
+ }
796
+ interface VersionPrConfig {
797
+ /**
798
+ * Auto-assign these users (logins) as the PR assignees on creation.
799
+ * Existing assignees are preserved; this only adds. Defaults to
800
+ * unassigned.
801
+ */
802
+ assignees?: string[];
803
+ /**
804
+ * Enable GitHub's auto-merge once status checks pass. Maps to
805
+ * `gh pr merge --auto`. Requires the repo to have auto-merge
806
+ * enabled in settings. Default `false`.
807
+ */
808
+ autoMerge?: boolean;
809
+ /**
810
+ * Merge strategy for auto-merge — defaults to `"squash"`. Honoured
811
+ * only when `autoMerge: true`.
812
+ */
813
+ autoMergeMethod?: "merge" | "rebase" | "squash";
814
+ /**
815
+ * Periodically rebase the version-PR branch on top of `base` so
816
+ * the PR doesn't drift behind. Default `false`. Enable when
817
+ * the version-PR sits open for long periods and conflicts with
818
+ * other PRs are likely. The actual rebase runs via
819
+ * `vis release ci rebase-pr` (which the CI workflow can schedule
820
+ * on a cron).
821
+ */
822
+ autoRebase?: boolean;
823
+ branch?: string;
824
+ /** Sentinel comment marker for sticky-update detection. */
825
+ commentMarker?: string;
826
+ /**
827
+ * Labels applied to the version-PR. Defaults to `["autorelease: pending"]`.
828
+ * Set to `[]` to disable. The label is added on every PR refresh —
829
+ * external automation can rely on it being present until the
830
+ * lifecycle moves on (`autorelease: tagged` post-publish, etc.).
831
+ */
832
+ labels?: string[];
833
+ /** Markdown prepended to the PR body. */
834
+ preamble?: string;
835
+ /**
836
+ * Auto-request reviews from these users / teams on PR creation.
837
+ * Format: GitHub usernames or `org/team`. Existing reviewers are
838
+ * preserved.
839
+ */
840
+ reviewers?: string[];
841
+ title?: string;
842
+ }
843
+ interface GitUserConfig {
844
+ email: string;
845
+ name: string;
846
+ }
847
+ /**
848
+ * Post-release notification walk — semantic-release parity.
849
+ *
850
+ * **Default OFF.** Set `release.successWalk: {}` to opt in with defaults.
851
+ * Leaving `successWalk` undefined in the workspace config is the explicit
852
+ * "don't touch third-party PRs" stance — sticky comments and the
853
+ * `released` label are an irreversible side effect on every PR mentioned
854
+ * in a changelog body, so we never apply them implicitly.
855
+ *
856
+ * When opted in, after a successful publish wave vis walks every PR /
857
+ * issue referenced in the rendered changelog entries and:
858
+ * 1. Posts (or upserts) a sticky comment announcing the release version.
859
+ * 2. Adds the configured labels (default `["released"]`).
860
+ *
861
+ * Failure to walk a single ref is non-fatal — the publish itself already
862
+ * succeeded; we don't want a forge API blip rolling that back.
863
+ */
864
+ interface SuccessWalkConfig {
865
+ /**
866
+ * Comment body template posted on every referenced PR / issue. Tokens:
867
+ * - `{version}` — the published version (e.g. `1.2.0`)
868
+ * - `{name}` — the published package name
869
+ * - `{tag}` — the git tag created for this release
870
+ * - `{url}` — the forge release URL when available
871
+ *
872
+ * Default mirrors semantic-release's `successComment`.
873
+ */
874
+ commentBody?: string;
875
+ /**
876
+ * Enable the walk. Default `true` when `successWalk` is present in
877
+ * the config. Setting `enabled: false` is functionally equivalent to
878
+ * omitting `successWalk` entirely (no walk runs) — the difference is
879
+ * one of intent: an explicit `enabled: false` documents that the
880
+ * operator has considered the walk and disabled it.
881
+ *
882
+ * Leaving `successWalk` undefined at the top level is the recommended
883
+ * "off" stance — see the interface docstring.
884
+ */
885
+ enabled?: boolean;
886
+ /** Labels added to every walked PR / issue. Default `["released"]`. */
887
+ labels?: string[];
888
+ /**
889
+ * Skip the walk entirely on prerelease channels — the typical "don't
890
+ * notify users their PR shipped in a beta" guardrail. Default `true`.
891
+ */
892
+ skipPrerelease?: boolean;
893
+ }
894
+ interface VisReleaseConfig {
895
+ /** Default npm `--access` flag. Default: `"public"`. */
896
+ access?: "public" | "restricted";
897
+ /** Suppress the unstable warning printed on first invocation (RFC §21.2). */
898
+ acknowledgeUnstable?: boolean;
899
+ /** Single GH release per wave vs per-package. */
900
+ aggregateRelease?: boolean | {
901
+ enabled: boolean;
902
+ title?: string;
903
+ };
904
+ /**
905
+ * Pattern for the workspace-level aggregate release tag (when
906
+ * `aggregateRelease.enabled`). Tokens: `{date}`, `{version}` (latest
907
+ * bumped pkg's version). Default: `"release-{date}"`.
908
+ */
909
+ aggregateReleaseTagPattern?: string;
910
+ /** Trust gate for per-package custom commands. */
911
+ allowCustomCommands?: boolean | string[];
912
+ /** Branch used for `--from` baseline in `status`/`generate`. Default: `"main"`. */
913
+ baseBranch?: string;
914
+ /**
915
+ * Opt-in cascade for `devDependencies` bumps (changesets #944 parity).
916
+ *
917
+ * By default, when a workspace package is bumped, only its
918
+ * `dependencies` / `peerDependencies` / `optionalDependencies`
919
+ * consumers are considered for propagation — devDependency
920
+ * consumers are silently ignored because consumers of the
921
+ * dependent don't observe the devDep at runtime.
922
+ *
923
+ * Some teams disagree (especially for type-only packages or build
924
+ * plugins) and want a devDep bump to still trigger a patch on its
925
+ * consumer so the lockfile stays in sync across machines. Set this
926
+ * to:
927
+ *
928
+ * - `true` — every devDep cascade fires (patch-level on the
929
+ * dependent), regardless of the source package.
930
+ * - `string[]` — narrow allow-list of source package names. Only
931
+ * bumps to packages whose name appears in the list will cascade
932
+ * through devDependencies. Useful when only specific
933
+ * "infrastructure" packages should propagate via devDeps.
934
+ *
935
+ * Default: `false` (devDep cascades remain off — historical behaviour).
936
+ */
937
+ bumpDevDependencies?: boolean | string[];
938
+ /**
939
+ * For pre-1.0 versions, demote `major` bumps to `minor`. Common for
940
+ * 0.x libraries that don't want their first breaking change to leap
941
+ * to 2.0. Maps to release-please's `bump-minor-pre-major`. Default
942
+ * `false`.
943
+ */
944
+ bumpMinorPreMajor?: boolean;
945
+ /**
946
+ * Companion to `bumpMinorPreMajor` — also demote `minor` bumps to
947
+ * `patch` for pre-1.0 versions. Maps to release-please's
948
+ * `bump-patch-for-minor-pre-major`. No-op without
949
+ * `bumpMinorPreMajor`. Default `false`.
950
+ */
951
+ bumpPatchForMinorPreMajor?: boolean;
952
+ /** Globs that count toward "package changed" detection. */
953
+ changedFilePatterns?: string[];
954
+ /**
955
+ * Changelog formatter selection. Pass `false` to disable changelog output,
956
+ * one of the built-in names (`"default"`, `"github"`, `"keep-a-changelog"`),
957
+ * a path to a custom module, or a `[path, options]` tuple.
958
+ */
959
+ changelog?: false | string | [string, Record<string, unknown>];
960
+ /** Directory holding change files. Default: `".vis/release"`. */
961
+ changesDir?: string;
962
+ /** Per-channel routing config (semantic-release-style). */
963
+ channels?: Record<string, ChannelConfig>;
964
+ /**
965
+ * Source of truth for "what is the current version of this package?",
966
+ * controlling how `oldVersion` is resolved when building the release plan.
967
+ *
968
+ * `"disk"` (default) — read `package.json#version` (or the equivalent
969
+ * manifest field for non-npm versionActions). Preserves vis's
970
+ * historical behaviour and is the right choice when the manifest
971
+ * on disk is the canonical source.
972
+ * `"registry"` — query the package registry via the package's
973
+ * `versionActions.readPublishedVersion()`. Useful when the manifest
974
+ * drifts between repo and registry (e.g. teams that publish
975
+ * out-of-band) and you want the registry to win.
976
+ * `"git-tag"` — find the highest `releaseTagPattern`-matching tag in
977
+ * the current commit's ancestry and parse the version out of it.
978
+ * Matches nx's `git-tag` resolver and release-please's tag-based
979
+ * lookup.
980
+ *
981
+ * `"registry"` and `"git-tag"` fall back to the manifest version when
982
+ * their primary source cannot produce a valid semver (e.g. registry 404
983
+ * on a freshly-added package, no matching tag yet, etc.) and surface a
984
+ * plan warning so the operator sees what happened.
985
+ *
986
+ * Overridable per-package via `packages.&lt;name>.currentVersionResolver`.
987
+ *
988
+ * The `--first-release` CLI flag is the bootstrap shortcut for this
989
+ * setting — it forces `"disk"` regardless of config and additionally
990
+ * skips remote-tag collision checks, so the very first run on a
991
+ * greenfield monorepo can't trip over missing tags or registry 404s.
992
+ */
993
+ currentVersionResolver?: "disk" | "git-tag" | "registry";
994
+ /** Default `release.managed` for unconfigured packages. Default: `false`. */
995
+ defaultManaged?: boolean;
996
+ /** Default dep-bump rules (overridable per-package). */
997
+ dependencyBumpRules?: DependencyBumpRules;
998
+ /**
999
+ * Opt-in cascade for `pnpm-workspace.yaml` catalog version bumps
1000
+ * (changesets #1707 parity).
1001
+ *
1002
+ * pnpm's `catalog:` / `catalogs:` blocks let multiple packages
1003
+ * share a single version range. When the operator bumps a catalog
1004
+ * entry (e.g. `react: ^18.2.0` → `react: ^18.3.0`) every consumer
1005
+ * package pulls the new version on its next `pnpm install`. Without
1006
+ * detection, vis sees no change to the consumer's `package.json`
1007
+ * and skips it — so the published tarball ends up shipping a stale
1008
+ * `"react": "catalog:"` reference that resolves differently across
1009
+ * machines.
1010
+ *
1011
+ * When `true`, vis diffs `pnpm-workspace.yaml` between `HEAD~1`
1012
+ * (the previous release commit) and `HEAD` (working tree). Every
1013
+ * catalog dep that moved triggers a `patch` bump on each consumer
1014
+ * package, attributed as `BumpReason.CATALOG_CHANGED` in the
1015
+ * release plan. Set on the consumer's dep cascade rules to widen
1016
+ * the bump level via the same `dependencyBumpRules` knob used for
1017
+ * direct dependency bumps.
1018
+ *
1019
+ * Default: `false` (backwards-compat — the prior behaviour was to
1020
+ * silently ignore catalog changes during plan assembly).
1021
+ */
1022
+ detectCatalogChanges?: boolean;
1023
+ /**
1024
+ * Fixed groups: members share the same version, all bump on any change.
1025
+ *
1026
+ * Two accepted shapes (backwards-compatible — the original
1027
+ * `string[][]` keeps working):
1028
+ *
1029
+ * - `string[]` — bare list of package names / globs.
1030
+ * Implicitly `{ changelog: { mode: "per-package" } }`.
1031
+ * - `{ packages, changelog }` — object form, lets you opt into a
1032
+ * SHARED changelog file for the group
1033
+ * (changesets #1059 parity). When
1034
+ * `changelog.mode === "shared"`, every
1035
+ * member's entry is rendered into one
1036
+ * group file (default
1037
+ * `&lt;first-member-dir>/GROUP-CHANGELOG.md`).
1038
+ */
1039
+ fixed?: ReleaseGroupConfig[];
1040
+ /**
1041
+ * Floating major-version tag. When `true`, every non-prerelease,
1042
+ * non-private release also force-updates a `&lt;safe-name>-v&lt;major>`
1043
+ * tag to point at the release commit. `safe-name` is the package
1044
+ * name with the leading `@` stripped and `/` replaced by `-`:
1045
+ *
1046
+ * - `@acme/action` → `acme-action-v1`
1047
+ * - `@vendor/cli` → `vendor-cli-v1`
1048
+ * - unscoped `cli` → `cli-v1`
1049
+ *
1050
+ * Useful for reusable GitHub Actions consumers who pin to
1051
+ * `acme/action@acme-action-v1` and expect automatic patch / minor
1052
+ * delivery without a tag-rev migration. The scope is included so
1053
+ * two packages with the same unscoped name from different scopes
1054
+ * (`@acme/cli` + `@vendor/cli`) don't both retarget the same
1055
+ * floating tag.
1056
+ *
1057
+ * Skipped on:
1058
+ * - Prereleases (per-channel `prerelease` configured). The float
1059
+ * would otherwise yank the major pointer across an unstable
1060
+ * pre-release boundary.
1061
+ * - Packages whose `releaseTagPattern` already includes `{major}`
1062
+ * (the pattern is already serving the same role).
1063
+ * - Private packages (`package.json#private === true`) and
1064
+ * packages that set `skipNpmPublish: true` — there's no
1065
+ * published artifact for a consumer to pin against, so a
1066
+ * floating tag would just clutter the tag history.
1067
+ *
1068
+ * Default: `false`. Semantic-release parity: #1515.
1069
+ */
1070
+ floatingMajorTag?: boolean;
1071
+ /**
1072
+ * Run the project's Prettier over the files the version step writes
1073
+ * (package.json bumps + CHANGELOG.md entries) before committing them
1074
+ * (RFC §14 step 7). Scoped to the changed files only — never the whole
1075
+ * tree. Resolves the project's own Prettier from the workspace root;
1076
+ * soft-fails if Prettier isn't installed.
1077
+ *
1078
+ * Default: `false` (opt-in — a project that doesn't use Prettier, or
1079
+ * whose Prettier config conflicts with how vis writes JSON, leaves this
1080
+ * off).
1081
+ */
1082
+ formatChangedFiles?: boolean;
1083
+ /**
1084
+ * Self-hosted GitHub Enterprise host (e.g. `"github.acme.com"` — no
1085
+ * scheme). Translates to the `GH_HOST` env var that the `gh` CLI
1086
+ * consumes natively, so all adapter calls land on the right
1087
+ * instance. Operators can also export `GH_HOST` directly; this
1088
+ * config knob is the typed, vis.config.ts-discoverable equivalent.
1089
+ * Ignored when `provider` resolves to anything other than `github`.
1090
+ */
1091
+ githubHost?: string;
1092
+ /**
1093
+ * Self-hosted GitLab host (e.g. `"gitlab.example.com"`). Translates to
1094
+ * the `GITLAB_HOST` env var that `glab` consumes natively, so all
1095
+ * adapter calls land on the right instance. Ignored when `provider`
1096
+ * resolves to anything other than `gitlab`.
1097
+ */
1098
+ gitlabHost?: string;
1099
+ /**
1100
+ * Sign release-flow commits with `git commit -S`. Set to `true` in
1101
+ * workspaces that enforce `commit.gpgsign = true`. The active git
1102
+ * identity must have a configured signing key (gpg, ssh, x509).
1103
+ * Default `false`.
1104
+ */
1105
+ gitSignCommits?: boolean;
1106
+ /** Git committer identity used by CI workflows. */
1107
+ gitUser?: GitUserConfig;
1108
+ /**
1109
+ * Group-scoped preVersion command. Runs once before any package in the
1110
+ * group is versioned. `groupName` matches a `fixed`/`linked` array's index
1111
+ * (group-0, group-1, …) or a named entry (future).
1112
+ */
1113
+ groupPreVersionCommands?: Record<string, string>;
1114
+ /**
1115
+ * HTTPS proxy URL (e.g. `"http://proxy.acme.com:8080"`) for
1116
+ * enterprise networks that route outbound HTTPS through a proxy.
1117
+ *
1118
+ * Wired through to two surfaces:
1119
+ *
1120
+ * 1. `gh` / `glab` CLI subprocesses get `HTTPS_PROXY` and
1121
+ * `HTTP_PROXY` set on their env so they tunnel through the
1122
+ * proxy exactly as if the operator had exported the vars
1123
+ * manually.
1124
+ *
1125
+ * 2. Every internal `fetch()` call (registry probes in
1126
+ * version-actions/{cargo,python,maven,container}.ts and the
1127
+ * shared `safeFetchVersionMetadata` helper) attaches an undici
1128
+ * `ProxyAgent` via the `dispatcher` option, so Node's built-in
1129
+ * fetch routes through the proxy as well.
1130
+ *
1131
+ * Node 22's bundled undici handles the proxy plumbing — no
1132
+ * `https-proxy-agent` dep needed.
1133
+ */
1134
+ httpProxy?: string;
1135
+ /** Globs of packages to exclude from release entirely. */
1136
+ ignore?: string[];
1137
+ /** Globs that override `ignore` and `private` exclusion. */
1138
+ include?: string[];
1139
+ /**
1140
+ * Linked groups: members share bump levels but only changed members
1141
+ * publish. Accepts the same dual-shape format as `fixed` — see the
1142
+ * `ReleaseGroupConfig` doc comment for details.
1143
+ */
1144
+ linked?: ReleaseGroupConfig[];
1145
+ /**
1146
+ * Notifications — post-release fan-out to chat / webhook
1147
+ * destinations. See {@link NotificationsConfig}. Each channel
1148
+ * runs in parallel; per-channel failures log a warning but do NOT
1149
+ * fail the publish.
1150
+ */
1151
+ notifications?: NotificationsConfig;
1152
+ /**
1153
+ * Emit one release commit per package (a `release(channel): pkg@version
1154
+ * [skip ci]` message) instead of a single aggregate commit for the whole
1155
+ * wave (RFC §19.5). Mirrors the per-package commit history that
1156
+ * multi-semantic-release produced — useful for projects migrating off it
1157
+ * that want to preserve `git log` shape. Only honoured when
1158
+ * `aggregateRelease` is falsy. Shared artifacts (lockfile + consumed
1159
+ * change-file deletions) ride along in the final package's commit.
1160
+ *
1161
+ * Default: `false` (one aggregate commit per wave).
1162
+ */
1163
+ oneCommitPerPackage?: boolean;
1164
+ /** Per-package overrides (matches `package.json["vis-release"]`). */
1165
+ packages?: Record<string, PerPackageReleaseConfig>;
1166
+ /** Shell command run after all publishes complete. */
1167
+ postPublishCommand?: string;
1168
+ /** Shell command run after versioning, before publish. */
1169
+ postVersionCommand?: string;
1170
+ /** Shell command run after versioning, before publish. */
1171
+ prePublishCommand?: string;
1172
+ /** Shell command run before any versioning. */
1173
+ preVersionCommand?: string;
1174
+ /** Whether to version + tag private packages. */
1175
+ privatePackages?: {
1176
+ tag: boolean;
1177
+ version: boolean;
1178
+ };
1179
+ /** Forge provider for remote operations (PR comments, releases, version PRs). */
1180
+ provider?: "github" | "gitlab" | "auto";
1181
+ /** Publish-related config. */
1182
+ publish?: PublishConfig;
1183
+ /**
1184
+ * Wrap each per-package GitHub / GitLab release body with operator-
1185
+ * supplied header / footer text. Common use: link a migration guide
1186
+ * above the auto-generated body, or paste a sponsorship blurb below.
1187
+ *
1188
+ * Both fields are template strings supporting tokens:
1189
+ * - `{name}` — package name
1190
+ * - `{version}` — new version
1191
+ * - `{previousVersion}` — previous version
1192
+ * - `{date}` — `YYYY-MM-DD`
1193
+ * - `{repo}` — `owner/repo` slug
1194
+ * - `{contributors}` — bullet list of authors collected from the
1195
+ * entire wave's change-file `author:` frontmatter (release-please
1196
+ * #292). Wave-scoped — every per-package release in the wave
1197
+ * sees the same set, so cascade and dependency-only bumps still
1198
+ * credit the upstream author. Block-only — keep this token on
1199
+ * its own line, typically under a heading; inline use like
1200
+ * `Thanks {contributors}!` will produce broken markdown.
1201
+ * Authors are de-duplicated case-insensitively, markdown-escaped,
1202
+ * and filtered through the github formatter's `internalAuthors`
1203
+ * list (when configured). Empty string when no change file in
1204
+ * the wave declared an author.
1205
+ *
1206
+ * When set, the rendered body is composed as `header\n\n&lt;body>\n\nfooter`.
1207
+ * Empty / unset fields are skipped (no leading / trailing blank line).
1208
+ *
1209
+ * > **Aggregate-release mode (`release.aggregateRelease: true`)**: the
1210
+ * > header and footer are NOT applied. The aggregate release body is
1211
+ * > already operator-templated via `release.aggregateRelease.title`
1212
+ * > and the per-package list is auto-rendered. If you want a custom
1213
+ * > prefix/suffix on the aggregate body, override
1214
+ * > `release.aggregateRelease.title` directly.
1215
+ *
1216
+ * Release-please parity: #1274.
1217
+ */
1218
+ releaseNoteTemplate?: {
1219
+ footer?: string;
1220
+ header?: string;
1221
+ };
1222
+ /**
1223
+ * Git tag template — overridable per-package via
1224
+ * `package.json["vis-release"]["releaseTagPattern"]`.
1225
+ * Tokens: `{name}`, `{unscopedName}`, `{version}`, `{major}`, `{minor}`,
1226
+ * `{patch}`, `{date}`, `{channel}`. Default: `"{name}@{version}"`.
1227
+ */
1228
+ releaseTagPattern?: string;
1229
+ /**
1230
+ * Sign release tags. Wraps `git tag -s` / `-u &lt;key>` and adds a
1231
+ * `gitsign`-based code path for sigstore-style keyless signing.
1232
+ *
1233
+ * Modes:
1234
+ * - `"gpg"` — `git tag -s` (or `-u &lt;key>` when `key` is set).
1235
+ * Relies on `user.signingkey` in git config.
1236
+ * - `"ssh"` — Same `-s` flag, but the operator must have
1237
+ * `gpg.format=ssh` + `user.signingkey=&lt;path-to-key>`
1238
+ * configured. Doctor surfaces missing config with a
1239
+ * warning at preflight.
1240
+ * - `"sigstore"` — Experimental ("preview"). Uses `gitsign` when on
1241
+ * PATH, otherwise falls back to GPG with a warning.
1242
+ *
1243
+ * Per-package signing is not supported (release tags are a workspace-
1244
+ * wide artefact). Default: undefined (no signing).
1245
+ *
1246
+ * Release-please parity: #1738, #1314.
1247
+ */
1248
+ signing?: {
1249
+ key?: string;
1250
+ mode: "gpg" | "sigstore" | "ssh";
1251
+ };
1252
+ /** Snapshot config. */
1253
+ snapshot?: SnapshotConfig;
1254
+ /**
1255
+ * Post-release notification walk. Configures the
1256
+ * "🎉 This is included in version X.Y.Z" comment + `released` label
1257
+ * pass that runs after a successful publish wave.
1258
+ *
1259
+ * **Default OFF.** Leave undefined and the walk never runs — vis
1260
+ * will not touch third-party PRs referenced in changelog bodies.
1261
+ * Set to `{}` to opt in with defaults, or pass an object to override
1262
+ * the comment template / labels / prerelease behaviour.
1263
+ */
1264
+ successWalk?: SuccessWalkConfig;
1265
+ /** Dep-propagation mode. Default: `"out-of-range"`. */
1266
+ updateInternalDependencies?: UpdateInternalDependenciesMode;
1267
+ /** Version-PR config. */
1268
+ versionPr?: VersionPrConfig;
1269
+ /**
1270
+ * Workspace-level changelog config (RFC §6.1 / nx parity).
1271
+ * When set, renders one CHANGELOG.md at the workspace root in addition
1272
+ * to per-package files.
1273
+ */
1274
+ workspaceChangelog?: false | {
1275
+ file?: string;
1276
+ waveHeading?: string;
1277
+ };
1278
+ }
1279
+ interface LockInfo {
1280
+ acquiredAt: string;
1281
+ /**
1282
+ * `os.hostname()` of the process that acquired the lock. PIDs are
1283
+ * meaningless across hosts (CI runners reuse PIDs across containers),
1284
+ * so foreign-host lockfiles are treated as automatically stale.
1285
+ */
1286
+ hostname?: string;
1287
+ pid: number;
1288
+ /** `process.platform` — recorded for debugging stale lock takeovers. */
1289
+ platform?: string;
1290
+ }
1291
+ interface StateFile {
1292
+ /** Versions written to disk. */
1293
+ applied: string[];
1294
+ channel?: string;
1295
+ /**
1296
+ * Packages already notified to chat / webhook channels in a prior
1297
+ * wave. Keyed by `${name}@${version}` so a `--resume` after a
1298
+ * partial failure doesn't re-fire Slack pings for releases that
1299
+ * already shipped + notified on run 1. Empty on a fresh wave.
1300
+ */
1301
+ notified?: string[];
1302
+ plan: PlannedRelease[];
1303
+ /** Tarballs uploaded to the registry. */
1304
+ published: string[];
1305
+ /** Whether `git push --tags` succeeded. */
1306
+ pushed: boolean;
1307
+ startedAt: string;
1308
+ /** Local git tags created. */
1309
+ tagged: string[];
1310
+ version: 1;
1311
+ /**
1312
+ * Packages whose successWalk (per-PR sticky comment + label) has
1313
+ * already fired. Tracked alongside `notified` for the same reason:
1314
+ * `--resume` after a partial failure should not re-walk the PRs
1315
+ * for releases already commented on. The sticky-comment marker
1316
+ * provides idempotency at the forge level too, but skipping the
1317
+ * walk entirely saves the rate-limited API calls.
1318
+ */
1319
+ walked?: string[];
1320
+ }
1321
+ /**
1322
+ * One pending staged publish — a tarball uploaded to npm but not yet
1323
+ * approved by a maintainer. Tracked across runs so a follow-up wave
1324
+ * can refuse to re-version the same package, and so
1325
+ * `vis release stage approve --all` can drain everything from a single
1326
+ * file regardless of which CI run created the stage.
1327
+ */
1328
+ interface PendingStage {
1329
+ /** Stage id returned by `npm stage publish`. */
1330
+ id: string;
1331
+ /** Package name (e.g. `@scope/pkg`). */
1332
+ name: string;
1333
+ /** Reason the stage is still pending. */
1334
+ reason: "rejected" | "timeout";
1335
+ /** ISO-8601 timestamp when the stage was recorded. */
1336
+ stagedAt: string;
1337
+ /** dist-tag the stage targets (`latest`, `next`, …). */
1338
+ tag?: string;
1339
+ /** Version being staged. */
1340
+ version: string;
1341
+ }
1342
+ /**
1343
+ * Tracked, committed file: `.vis/release/staged.json`.
1344
+ *
1345
+ * Lives in git so pending stages survive CI runner churn and branch
1346
+ * switches. The release flow auto-commits this file after every publish
1347
+ * wave with `[skip ci]` to avoid loops.
1348
+ */
1349
+ interface StagedRegistryFile {
1350
+ pending: PendingStage[];
1351
+ /**
1352
+ * Packages already notified to chat / webhook channels — survives
1353
+ * CI runner churn (a fresh runner clones the repo and reads this
1354
+ * tracked file, instead of relying on the gitignored `.state.json`
1355
+ * which only the originating runner can see).
1356
+ *
1357
+ * Keyed by `${name}@${version}`. Pruned to the last 30 days OR last
1358
+ * 100 entries per write, whichever is smaller, so the registry
1359
+ * doesn't grow unboundedly on long-lived workspaces.
1360
+ */
1361
+ recentlyNotified?: {
1362
+ at: string;
1363
+ key: string;
1364
+ }[];
1365
+ /**
1366
+ * Packages already walked (PR/issue sticky comment + `released`
1367
+ * label posted) — same cross-runner concern as `recentlyNotified`.
1368
+ */
1369
+ recentlyWalked?: {
1370
+ at: string;
1371
+ key: string;
1372
+ }[];
1373
+ /** ISO-8601 timestamp of the last write. */
1374
+ updatedAt: string;
1375
+ version: 1;
1376
+ }
1377
+ export { BUMP_LEVELS, BumpAs, BumpLevel, BumpReason, BumpSource, CatalogResolutionMode, ChangeFile, ChangeFileNested, ChangeFileSimple, ChannelConfig, ChannelMode, CleanPackageJsonConfig, DependencyBumpRule, DependencyBumpRules, DependencyKind, DependentInfo, DiscordConfig, ExtraFileAnnotationRule, ExtraFileRegexRule, ExtraFileRule, GitUserConfig, LockInfo, NotificationsConfig, PackManager, PackageManifest, PendingStage, PerPackageReleaseConfig, PlannedRelease, ProtocolResolutionMode, PublishConfig, PublishGuardsConfig, PublishStrategy, ReleaseAssetsConfig, ReleaseGroupChangelogConfig, ReleaseGroupConfig, ReleasePlan, SlackConfig, SnapshotBackend, SnapshotConfig, SnapshotTagKind, StagedRegistryFile, StateFile, SuccessWalkConfig, UpdateInternalDependenciesMode, VersionPrConfig, VisReleaseConfig, WebhookConfig, WorkspacePackage, bumpRank, maxBump, normaliseGroup };