@visulima/vis 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (172) hide show
  1. package/CHANGELOG.md +1117 -24
  2. package/LICENSE.md +11958 -0
  3. package/README.md +344 -20
  4. package/dashboard/dist/index.html +152 -0
  5. package/dist/bin.js +1 -146
  6. package/dist/binx.js +3 -0
  7. package/dist/config/index.d.ts +3154 -0
  8. package/dist/config/index.js +1 -0
  9. package/dist/generate/index.d.ts +157 -0
  10. package/dist/generate/index.js +1 -0
  11. package/dist/packem_chunks/bin.js +1415 -0
  12. package/dist/packem_chunks/bloom-status.js +2 -0
  13. package/dist/packem_chunks/bloom-sync.js +2 -0
  14. package/dist/packem_chunks/cache-attestation.js +1 -0
  15. package/dist/packem_chunks/config.js +19 -0
  16. package/dist/packem_chunks/devtools.js +82 -0
  17. package/dist/packem_chunks/doctor-probe.js +2 -0
  18. package/dist/packem_chunks/fix.js +11 -0
  19. package/dist/packem_chunks/handler.js +1 -0
  20. package/dist/packem_chunks/handler10.js +1 -0
  21. package/dist/packem_chunks/handler11.js +5 -0
  22. package/dist/packem_chunks/handler12.js +1 -0
  23. package/dist/packem_chunks/handler13.js +27 -0
  24. package/dist/packem_chunks/handler14.js +5 -0
  25. package/dist/packem_chunks/handler15.js +1 -0
  26. package/dist/packem_chunks/handler16.js +1 -0
  27. package/dist/packem_chunks/handler17.js +1 -0
  28. package/dist/packem_chunks/handler18.js +1 -0
  29. package/dist/packem_chunks/handler19.js +1 -0
  30. package/dist/packem_chunks/handler2.js +4 -0
  31. package/dist/packem_chunks/handler20.js +5 -0
  32. package/dist/packem_chunks/handler21.js +2 -0
  33. package/dist/packem_chunks/handler22.js +2 -0
  34. package/dist/packem_chunks/handler23.js +1 -0
  35. package/dist/packem_chunks/handler24.js +1 -0
  36. package/dist/packem_chunks/handler25.js +5 -0
  37. package/dist/packem_chunks/handler26.js +1 -0
  38. package/dist/packem_chunks/handler27.js +3 -0
  39. package/dist/packem_chunks/handler28.js +1 -0
  40. package/dist/packem_chunks/handler29.js +7 -0
  41. package/dist/packem_chunks/handler3.js +4 -0
  42. package/dist/packem_chunks/handler30.js +33 -0
  43. package/dist/packem_chunks/handler31.js +3 -0
  44. package/dist/packem_chunks/handler32.js +8 -0
  45. package/dist/packem_chunks/handler33.js +1 -0
  46. package/dist/packem_chunks/handler34.js +5 -0
  47. package/dist/packem_chunks/handler35.js +11 -0
  48. package/dist/packem_chunks/handler36.js +3 -0
  49. package/dist/packem_chunks/handler37.js +22 -0
  50. package/dist/packem_chunks/handler38.js +61 -0
  51. package/dist/packem_chunks/handler39.js +3 -0
  52. package/dist/packem_chunks/handler4.js +6 -0
  53. package/dist/packem_chunks/handler40.js +6 -0
  54. package/dist/packem_chunks/handler41.js +24 -0
  55. package/dist/packem_chunks/handler42.js +153 -0
  56. package/dist/packem_chunks/handler43.js +25 -0
  57. package/dist/packem_chunks/handler44.js +10 -0
  58. package/dist/packem_chunks/handler45.js +708 -0
  59. package/dist/packem_chunks/handler46.js +24 -0
  60. package/dist/packem_chunks/handler47.js +322 -0
  61. package/dist/packem_chunks/handler48.js +48 -0
  62. package/dist/packem_chunks/handler49.js +3 -0
  63. package/dist/packem_chunks/handler5.js +8 -0
  64. package/dist/packem_chunks/handler50.js +27 -0
  65. package/dist/packem_chunks/handler51.js +195 -0
  66. package/dist/packem_chunks/handler52.js +34 -0
  67. package/dist/packem_chunks/handler6.js +1 -0
  68. package/dist/packem_chunks/handler7.js +1 -0
  69. package/dist/packem_chunks/handler8.js +1 -0
  70. package/dist/packem_chunks/handler9.js +1 -0
  71. package/dist/packem_chunks/heal-accept.js +10 -0
  72. package/dist/packem_chunks/heal.js +14 -0
  73. package/dist/packem_chunks/help-command.js +8 -0
  74. package/dist/packem_chunks/index.js +7 -0
  75. package/dist/packem_chunks/keys-refresh.js +4 -0
  76. package/dist/packem_chunks/list.js +3 -0
  77. package/dist/packem_chunks/loader.js +4 -0
  78. package/dist/packem_chunks/loader2.js +1 -0
  79. package/dist/packem_chunks/prune.js +3 -0
  80. package/dist/packem_chunks/run.js +1 -0
  81. package/dist/packem_chunks/status.js +2 -0
  82. package/dist/packem_chunks/sync.js +2 -0
  83. package/dist/packem_chunks/sync2.js +2 -0
  84. package/dist/packem_chunks/tar.js +3 -0
  85. package/dist/packem_chunks/tripwire.js +2 -0
  86. package/dist/packem_chunks/verify-lockfile.js +2 -0
  87. package/dist/packem_shared/Table-DoSoazT6-DwnyTUsA.js +12 -0
  88. package/dist/packem_shared/_commonjsHelpers-CLblCigl.js +1 -0
  89. package/dist/packem_shared/advisories-BxXiKFbL.js +1 -0
  90. package/dist/packem_shared/affected-shas-BdnlfiV1.js +1 -0
  91. package/dist/packem_shared/ai-analysis-KP8b5lc0.js +68 -0
  92. package/dist/packem_shared/ai-fix-BkPUHA0z.js +43 -0
  93. package/dist/packem_shared/anolilab-text-CAM_E6uK.js +13 -0
  94. package/dist/packem_shared/applyDefaults-BogleaFi.js +1 -0
  95. package/dist/packem_shared/build-scripts-DE6U8jVq.js +1 -0
  96. package/dist/packem_shared/cyclonedx-BpGVHqSW.js +4 -0
  97. package/dist/packem_shared/definePlugin-CWm4Dv_t.js +1 -0
  98. package/dist/packem_shared/dependency-scan-BUbOcMwX.js +1 -0
  99. package/dist/packem_shared/docker-CTE3s4LW.js +60 -0
  100. package/dist/packem_shared/failure-log-34Wl3npC.js +2 -0
  101. package/dist/packem_shared/giget-CcEy_Elm.js +2 -0
  102. package/dist/packem_shared/glob-D_7bct6p-D8itOHsr.js +1 -0
  103. package/dist/packem_shared/index-D1xC1Y_R.js +1 -0
  104. package/dist/packem_shared/index-DH-5hsrC.js +1 -0
  105. package/dist/packem_shared/index-hoWfZmNo.js +30 -0
  106. package/dist/packem_shared/license-zZU7aavK.js +1 -0
  107. package/dist/packem_shared/lifecycle-CXaqPGAQ.js +2 -0
  108. package/dist/packem_shared/lockfile-CrT86D6d.js +1 -0
  109. package/dist/packem_shared/lockfile-Cu2BH6bl.js +1 -0
  110. package/dist/packem_shared/manifests-BzWpKW8F.js +1 -0
  111. package/dist/packem_shared/min-release-age-BPVXwPUg.js +34 -0
  112. package/dist/packem_shared/native-config-sync-BRZZetn3.js +21 -0
  113. package/dist/packem_shared/osv-bloom-DSZcHLsM.js +2 -0
  114. package/dist/packem_shared/otelPlugin-CJR2T_lk.js +1 -0
  115. package/dist/packem_shared/peer-warnings-EvSJ18gE.js +1 -0
  116. package/dist/packem_shared/pm-runner-DmKT2FqF.js +1 -0
  117. package/dist/packem_shared/provenance-DkCA8BrN.js +1 -0
  118. package/dist/packem_shared/readFileSync-DseCu8sg-DEq4Fn3a.js +1 -0
  119. package/dist/packem_shared/registry-keys-Mixm4eAY.js +1 -0
  120. package/dist/packem_shared/resolve-explicit-D5E72FfN.js +5 -0
  121. package/dist/packem_shared/runtime-check-CilFOqUU.js +1 -0
  122. package/dist/packem_shared/s1ngularity-Qxc6tRRI.js +1 -0
  123. package/dist/packem_shared/scan-progress-DVtCtI2z.js +2 -0
  124. package/dist/packem_shared/selectors-DkgYFzdq.js +3 -0
  125. package/dist/packem_shared/signatures-byuFrtAH.js +2 -0
  126. package/dist/packem_shared/spinner-C8xs6QZv.js +1 -0
  127. package/dist/packem_shared/spinners-f91Rbo99-Bjf3NcO0.js +1 -0
  128. package/dist/packem_shared/symbols-CQmER5MT.js +1 -0
  129. package/dist/packem_shared/tabs-xZkm6Y_J.js +1 -0
  130. package/dist/packem_shared/toolchain-DoG6b_G_.js +5 -0
  131. package/dist/packem_shared/typosquats-BiDxQj7R.js +1 -0
  132. package/dist/packem_shared/use-measured-height-Lea6TCVD.js +1 -0
  133. package/dist/packem_shared/utils-DrNg0XTR.js +1 -0
  134. package/dist/packem_shared/verify-cLcZwKqe.js +1 -0
  135. package/dist/packem_shared/vis-update-app-BCKzlqj8.js +1 -0
  136. package/dist/packem_shared/watch-DEL0yol9.js +1 -0
  137. package/dist/packem_shared/watch-loop-C31Ar7BX.js +11 -0
  138. package/index.d.ts +436 -0
  139. package/index.js +613 -0
  140. package/package.json +71 -26
  141. package/schemas/project.schema.json +991 -0
  142. package/schemas/vis-config.schema.json +4958 -0
  143. package/skills/vis/SKILL.md +96 -0
  144. package/templates/buildkite-ci/.buildkite/pipeline.yml.tera +85 -0
  145. package/templates/buildkite-ci/template.yml +20 -0
  146. package/dist/ai-analysis.d.ts +0 -40
  147. package/dist/ai-cache.d.ts +0 -21
  148. package/dist/bin.d.ts +0 -1
  149. package/dist/catalog.d.ts +0 -110
  150. package/dist/commands/affected.d.ts +0 -3
  151. package/dist/commands/ai.d.ts +0 -3
  152. package/dist/commands/analyze.d.ts +0 -3
  153. package/dist/commands/check.d.ts +0 -3
  154. package/dist/commands/graph.d.ts +0 -3
  155. package/dist/commands/hook/constants.d.ts +0 -8
  156. package/dist/commands/hook/index.d.ts +0 -3
  157. package/dist/commands/hook/install.d.ts +0 -7
  158. package/dist/commands/hook/migrate.d.ts +0 -27
  159. package/dist/commands/hook/uninstall.d.ts +0 -3
  160. package/dist/commands/migrate/constants.d.ts +0 -12
  161. package/dist/commands/migrate/deps.d.ts +0 -32
  162. package/dist/commands/migrate/index.d.ts +0 -3
  163. package/dist/commands/migrate/json.d.ts +0 -20
  164. package/dist/commands/migrate/lint-staged.d.ts +0 -62
  165. package/dist/commands/migrate/types.d.ts +0 -20
  166. package/dist/commands/run.d.ts +0 -3
  167. package/dist/commands/staged.d.ts +0 -3
  168. package/dist/commands/update.d.ts +0 -3
  169. package/dist/config.d.ts +0 -40
  170. package/dist/config.js +0 -1
  171. package/dist/package-manager.d.ts +0 -23
  172. package/dist/workspace.d.ts +0 -58
@@ -0,0 +1,991 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://visulima.com/schemas/project.schema.json",
4
+ "title": "vis project.json",
5
+ "description": "Per-project configuration for @visulima/vis. Place a project.json in each workspace package root.",
6
+ "type": "object",
7
+ "properties": {
8
+ "implicitDependencies": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "string"
12
+ },
13
+ "description": "Implicit dependencies on other projects."
14
+ },
15
+ "language": {
16
+ "type": "string",
17
+ "description": "Primary language — informational and query-able."
18
+ },
19
+ "layer": {
20
+ "type": "string",
21
+ "enum": [
22
+ "application",
23
+ "automation",
24
+ "configuration",
25
+ "library",
26
+ "scaffolding",
27
+ "tool"
28
+ ],
29
+ "description": "Project layer, used for constraint inheritance and query filtering."
30
+ },
31
+ "name": {
32
+ "type": "string",
33
+ "description": "Project name. When set, takes precedence over `package.json#name` as the project's identity in the workspace graph and CLI filters. Falls back to `package.json#name` when omitted."
34
+ },
35
+ "owners": {
36
+ "type": "array",
37
+ "items": {
38
+ "$ref": "#/$defs/OwnersEntry"
39
+ },
40
+ "description": "Code owners for paths inside this project."
41
+ },
42
+ "project": {
43
+ "type": "object",
44
+ "properties": {
45
+ "channel": {
46
+ "type": "string"
47
+ },
48
+ "description": {
49
+ "type": "string"
50
+ },
51
+ "maintainers": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "string"
55
+ }
56
+ },
57
+ "owner": {
58
+ "type": "string"
59
+ },
60
+ "title": {
61
+ "type": "string"
62
+ }
63
+ },
64
+ "additionalProperties": false,
65
+ "description": "Project-level metadata."
66
+ },
67
+ "projectType": {
68
+ "type": "string",
69
+ "enum": [
70
+ "application",
71
+ "library",
72
+ "service",
73
+ "tool"
74
+ ],
75
+ "description": "Project type — `library`, `application`, `service`, or `tool`.\n\n- `library` — reusable code consumed by other workspace projects.\n- `application` — end-user-facing build target (web app, mobile app).\n- `service` — long-running HTTP / worker process deployed independently.\n- `tool` — CLI or developer tooling shipped as an executable."
76
+ },
77
+ "restricted": {
78
+ "type": "boolean",
79
+ "description": "Marks the project as write-restricted. Consumed by `vis sync codeowners --write-guard` to scope the generated Write Guard workflow to this project's paths."
80
+ },
81
+ "sourceRoot": {
82
+ "type": "string",
83
+ "description": "Source root, used for display and language inference."
84
+ },
85
+ "stack": {
86
+ "type": "string",
87
+ "enum": [
88
+ "backend",
89
+ "data",
90
+ "frontend",
91
+ "infrastructure",
92
+ "systems"
93
+ ],
94
+ "description": "Tech stack."
95
+ },
96
+ "tags": {
97
+ "type": "array",
98
+ "items": {
99
+ "type": "string"
100
+ },
101
+ "description": "Filterable tags."
102
+ },
103
+ "targets": {
104
+ "type": "object",
105
+ "additionalProperties": {
106
+ "$ref": "#/$defs/VisTargetConfiguration"
107
+ },
108
+ "description": "Vis-style target definitions (merged on top of package.json scripts)."
109
+ },
110
+ "$schema": {
111
+ "type": "string",
112
+ "description": "JSON Schema reference for editor autocomplete."
113
+ }
114
+ },
115
+ "additionalProperties": false,
116
+ "$defs": {
117
+ "OwnersEntry": {
118
+ "type": "object",
119
+ "properties": {
120
+ "channel": {
121
+ "type": "string",
122
+ "description": "Optional notification channel (e.g. Slack, Teams)."
123
+ },
124
+ "owners": {
125
+ "type": "array",
126
+ "items": {
127
+ "type": "string"
128
+ },
129
+ "description": "Owner handles (e.g. `@visulima/core-team`)."
130
+ },
131
+ "path": {
132
+ "type": "string",
133
+ "description": "File/glob pattern relative to the project root."
134
+ }
135
+ },
136
+ "required": [
137
+ "owners",
138
+ "path"
139
+ ],
140
+ "additionalProperties": false,
141
+ "description": "Declared code-owner assignment for a path glob within a project. Mirrors moon's `owners` shape so migrations can round-trip cleanly."
142
+ },
143
+ "VisTargetConfiguration": {
144
+ "type": "object",
145
+ "properties": {
146
+ "always": {
147
+ "type": "boolean",
148
+ "description": "When `true`, this target runs after the main task graph completes — even if upstream tasks failed. Useful for cleanup, teardown, notifications, or anything that should fire regardless of build outcome. Always-tasks are not part of the normal dependency graph and never block other tasks."
149
+ },
150
+ "cache": {
151
+ "type": "boolean",
152
+ "description": "Whether this target is cacheable"
153
+ },
154
+ "cacheOnWarning": {
155
+ "type": "boolean",
156
+ "description": "When `false`, exit-0 runs whose terminal output matched any {@link TargetConfiguration.warningPattern } are not seeded into the cache. Defaults to `true` — warnings are surfaced on the result (`hadWarnings: true`) but caching still happens, matching the \"succeeded with warnings is incremental\" behaviour rush, lage and wireit users have repeatedly asked for."
157
+ },
158
+ "cacheRestore": {
159
+ "type": "object",
160
+ "properties": {
161
+ "preserveMtime": {
162
+ "type": "boolean",
163
+ "description": "Restore each file's modification time from the captured tar header (second precision). When `false`, restored files take the current wall-clock time, matching the legacy behaviour."
164
+ },
165
+ "preservePerms": {
166
+ "type": "boolean",
167
+ "description": "Restore each file's POSIX mode bits (rwx triplets, low 12 bits). When `false`, restored files take the process umask. Only meaningful on POSIX hosts; Windows ignores tar mode."
168
+ }
169
+ },
170
+ "additionalProperties": false,
171
+ "description": "Fine-grained controls over how cached outputs are rehydrated. See {@link CacheRestoreOptions } . Both fields default to `true` (faithful restore); flip individually when downstream tooling needs the legacy \"now\"-stamped behaviour."
172
+ },
173
+ "command": {
174
+ "type": "string",
175
+ "description": "The command to run (alternative to executor)"
176
+ },
177
+ "concurrencyGroup": {
178
+ "type": "string",
179
+ "description": "Workspace-level concurrency group this target opts into. The scheduler caps the *combined* in-flight count of every task whose target carries the same group name to the value declared in {@link TaskRunnerOptions.concurrencyGroups } . Use this when several targets share an external resource (a single Postgres, a developer's Docker daemon, an account-wide deploy lock) so the cap follows the resource, not any single target name.\n\nTargets that name a group not declared in `concurrencyGroups` run uncapped — a typo shouldn't deadlock the graph. Caps don't apply to tasks marked `always: true`; those run in a separate finalisation phase outside the scheduler."
180
+ },
181
+ "concurrencyWeight": {
182
+ "type": "number",
183
+ "description": "Per-task slot weight against the global `parallel` cap. Defaults to `1`. A task with `concurrencyWeight: 2` consumes two slots; with `parallel: 4` only two such tasks can run concurrently (or one weight-2 plus two weight-1). Use for CPU-pinning tasks — bundlers, `tsc`, native compiles — where the runner shouldn't keep over-subscribing the box just because slots are nominally free.\n\nThe scheduler always lets a single task run even if its weight exceeds the remaining budget; otherwise a heavy task on a `parallel: 1` pool would deadlock. Values `<= 0`, non-finite, or non-integer are ignored (treated as `1`)."
184
+ },
185
+ "configurations": {
186
+ "type": "object",
187
+ "additionalProperties": {
188
+ "type": "object",
189
+ "additionalProperties": {}
190
+ },
191
+ "description": "Named configurations (e.g., \"production\", \"development\")"
192
+ },
193
+ "dependsOn": {
194
+ "type": "array",
195
+ "items": {
196
+ "anyOf": [
197
+ {
198
+ "type": "string"
199
+ },
200
+ {
201
+ "type": "object",
202
+ "properties": {
203
+ "dependencies": {
204
+ "type": "boolean",
205
+ "description": "Whether this is a dependency on the same project"
206
+ },
207
+ "params": {
208
+ "type": "string",
209
+ "enum": [
210
+ "forward",
211
+ "ignore"
212
+ ],
213
+ "description": "Params to pass through"
214
+ },
215
+ "projects": {
216
+ "anyOf": [
217
+ {
218
+ "type": "string"
219
+ },
220
+ {
221
+ "type": "array",
222
+ "items": {
223
+ "type": "string"
224
+ }
225
+ }
226
+ ],
227
+ "description": "The project name (if different from the current project)"
228
+ },
229
+ "target": {
230
+ "type": "string",
231
+ "description": "The target name"
232
+ }
233
+ },
234
+ "required": [
235
+ "target"
236
+ ],
237
+ "additionalProperties": false,
238
+ "description": "Defines a dependency on another target."
239
+ }
240
+ ]
241
+ },
242
+ "description": "Other targets this target depends on"
243
+ },
244
+ "executor": {
245
+ "type": "string",
246
+ "description": "The executor/command to run"
247
+ },
248
+ "hashMode": {
249
+ "type": "string",
250
+ "enum": [
251
+ "declared",
252
+ "trace"
253
+ ],
254
+ "description": "How this target's cache key is derived.\n\n- `\"declared\"` (default): the Nx-style path — the hash is built up-front from explicitly declared `inputs` (plus named/global inputs and the lockfile). Deterministic and portable across machines: two runners with the same workspace state produce the same key regardless of OS or syscall surface.\n- `\"trace\"`: the task is run under the file-access tracker (strace on Linux, an fs preload shim elsewhere) and the cache key is derived from the files it actually *read* during execution — no `inputs` declaration required. Mirrors the shipped `{ auto: true }` output capture, but for the input side. Use for compound or opaque commands whose real input set is impractical to enumerate.\n\nOpt-in per target precisely because trace mode trades reproducibility for convenience: the observed read set can differ across runners with different syscall surfaces (a static binary on a host without strace records nothing), so a trace key is **not** guaranteed portable between machines. Leave targets on `\"declared\"` whenever the input set can reasonably be listed.\n\nEquivalent to flipping {@link TaskRunnerOptions.autoFingerprint } on for this one target while every other target stays declared."
255
+ },
256
+ "inputs": {
257
+ "type": "array",
258
+ "items": {
259
+ "anyOf": [
260
+ {
261
+ "type": "string"
262
+ },
263
+ {
264
+ "anyOf": [
265
+ {
266
+ "type": "object",
267
+ "properties": {
268
+ "fileset": {
269
+ "anyOf": [
270
+ {
271
+ "type": "object",
272
+ "properties": {
273
+ "base": {
274
+ "type": "string",
275
+ "enum": [
276
+ "package",
277
+ "workspace"
278
+ ],
279
+ "description": "Anchor for the pattern."
280
+ },
281
+ "pattern": {
282
+ "type": "string",
283
+ "description": "Glob pattern (may start with `!` for negation)."
284
+ }
285
+ },
286
+ "required": [
287
+ "base",
288
+ "pattern"
289
+ ],
290
+ "additionalProperties": false,
291
+ "description": "Object form of a fileset pattern, for anchoring to the workspace root."
292
+ },
293
+ {
294
+ "type": "string"
295
+ }
296
+ ]
297
+ }
298
+ },
299
+ "required": [
300
+ "fileset"
301
+ ],
302
+ "additionalProperties": false,
303
+ "description": "An input based on file patterns.\n\n`fileset` may be a bare glob string (package-root relative) or an object form `{ pattern, base }` to anchor explicitly to the workspace root. Negation (`!` prefix) works in both forms."
304
+ },
305
+ {
306
+ "type": "object",
307
+ "properties": {
308
+ "runtime": {
309
+ "type": "string"
310
+ }
311
+ },
312
+ "required": [
313
+ "runtime"
314
+ ],
315
+ "additionalProperties": false,
316
+ "description": "An input based on a runtime command."
317
+ },
318
+ {
319
+ "type": "object",
320
+ "properties": {
321
+ "env": {
322
+ "type": "string"
323
+ }
324
+ },
325
+ "required": [
326
+ "env"
327
+ ],
328
+ "additionalProperties": false,
329
+ "description": "An input based on environment variables."
330
+ },
331
+ {
332
+ "type": "object",
333
+ "properties": {
334
+ "externalDependencies": {
335
+ "type": "array",
336
+ "items": {
337
+ "type": "string"
338
+ }
339
+ }
340
+ },
341
+ "required": [
342
+ "externalDependencies"
343
+ ],
344
+ "additionalProperties": false,
345
+ "description": "An input based on external dependency versions."
346
+ }
347
+ ],
348
+ "description": "Defines an input for cache invalidation."
349
+ }
350
+ ]
351
+ },
352
+ "description": "Input patterns for cache invalidation"
353
+ },
354
+ "maxConcurrent": {
355
+ "type": "number",
356
+ "description": "Maximum number of in-flight instances of this target across the whole graph. When set, the scheduler refuses to start an additional task whose `target.target` equals this target's name once the running count reaches `maxConcurrent`. Independent of `--parallel`: the global cap still bounds total in-flight tasks, and `maxConcurrent` further bounds the per-target subset.\n\nUse for tests/deploys that share an external resource (DB, port, mock server). Set to `1` to serialize. Values `<= 0` are ignored.\n\nIf multiple projects declare different values for the same target name, the runner uses the smallest declared cap. Caps don't apply to tasks marked `always: true`; those run in a separate finalisation phase outside the scheduler."
357
+ },
358
+ "outputs": {
359
+ "type": "array",
360
+ "items": {
361
+ "anyOf": [
362
+ {
363
+ "type": "string"
364
+ },
365
+ {
366
+ "type": "object",
367
+ "properties": {
368
+ "auto": {
369
+ "type": "boolean",
370
+ "const": true
371
+ }
372
+ },
373
+ "required": [
374
+ "auto"
375
+ ],
376
+ "additionalProperties": false
377
+ }
378
+ ],
379
+ "description": "A single entry in a task's `outputs` list.\n\n- `string` — a literal path *or* a glob pattern relative to the workspace root. Prefix with `!` to exclude files the positive patterns would otherwise include (e.g. `\"!dist/cache/**\"`).\n- `{ auto: true }` — use whatever files the task actually wrote during execution (resolved from the file-access tracker). Lets authors who don't know their exact output layout cache results without listing every path. Silently behaves as \"no outputs\" when tracking isn't active for this task."
380
+ },
381
+ "description": "Output patterns produced by this target. Each entry is a literal path, a glob (`\"dist/**\"`), a negative glob (`\"!dist/cache/**\"`), or `{ auto: true }` to cache whatever files the task actually wrote during execution (resolved from the file-access tracker). `{ auto: true }` lets a build script cache zero-config without the author enumerating its output layout; it contributes nothing — and the runner declines to seed the cache — when write tracking isn't available for the task, so a hit can never restore a missing artifact."
382
+ },
383
+ "parallelism": {
384
+ "type": "boolean",
385
+ "description": "Whether this target supports parallel execution"
386
+ },
387
+ "pty": {
388
+ "type": "boolean",
389
+ "description": "Per-target PTY override. When `true`, every task spawned from this target runs inside a pseudo-terminal (so `isatty()` returns true and the child preserves color / progress UI). When `false`, the workspace-level PTY toggle is suppressed for this target. Useful when most targets are happy with piped stdio but one tool (vitest, prettier, a colorising linter) needs a real TTY, or vice versa.\n\nAbsent means \"follow the workspace default\" — the executor decides based on its own toggles."
390
+ },
391
+ "warningPattern": {
392
+ "anyOf": [
393
+ {
394
+ "type": "string"
395
+ },
396
+ {
397
+ "type": "array",
398
+ "items": {
399
+ "type": "string"
400
+ }
401
+ }
402
+ ],
403
+ "description": "Regex source string(s) that mark a successful task as having emitted warnings. The orchestrator scans the task's combined terminal output after a 0-exit and, on first match, sets `hadWarnings` on the result. Combine with `cacheOnWarning: false` to skip caching for warning-tainted runs. Both bare strings and arrays are accepted; arrays are tested in order.\n\n ```ts warningPattern: [\"\\\\bwarning\\\\b\", \"TS\\\\d{4}\"] ```"
404
+ },
405
+ "when": {
406
+ "type": "object",
407
+ "properties": {
408
+ "branch": {
409
+ "anyOf": [
410
+ {
411
+ "type": "string"
412
+ },
413
+ {
414
+ "type": "array",
415
+ "items": {
416
+ "type": "string"
417
+ }
418
+ }
419
+ ],
420
+ "description": "Match against the current git branch (HEAD)."
421
+ },
422
+ "ci": {
423
+ "type": "boolean",
424
+ "description": "Run only when invoked inside CI when `true`, only outside CI when `false`. Detects CI via the `CI` env var (the convention GitHub Actions, GitLab, CircleCI, Jenkins, etc. all share)."
425
+ },
426
+ "env": {
427
+ "anyOf": [
428
+ {
429
+ "anyOf": [
430
+ {
431
+ "type": "string"
432
+ },
433
+ {
434
+ "type": "object",
435
+ "properties": {
436
+ "equals": {
437
+ "type": "string",
438
+ "description": "Match this exact value. Mutually exclusive with `exists`."
439
+ },
440
+ "exists": {
441
+ "type": "boolean",
442
+ "description": "Assert the variable is set & non-empty (`true`) or unset/empty (`false`)."
443
+ },
444
+ "name": {
445
+ "type": "string",
446
+ "description": "Variable name."
447
+ }
448
+ },
449
+ "required": [
450
+ "name"
451
+ ],
452
+ "additionalProperties": false
453
+ }
454
+ ],
455
+ "description": "An environment-variable match. The string form is shorthand for `{ name, exists: true }` (set + non-empty). The object form supports either presence assertions or exact-value matching."
456
+ },
457
+ {
458
+ "type": "array",
459
+ "items": {
460
+ "anyOf": [
461
+ {
462
+ "type": "string"
463
+ },
464
+ {
465
+ "type": "object",
466
+ "properties": {
467
+ "equals": {
468
+ "type": "string",
469
+ "description": "Match this exact value. Mutually exclusive with `exists`."
470
+ },
471
+ "exists": {
472
+ "type": "boolean",
473
+ "description": "Assert the variable is set & non-empty (`true`) or unset/empty (`false`)."
474
+ },
475
+ "name": {
476
+ "type": "string",
477
+ "description": "Variable name."
478
+ }
479
+ },
480
+ "required": [
481
+ "name"
482
+ ],
483
+ "additionalProperties": false
484
+ }
485
+ ],
486
+ "description": "An environment-variable match. The string form is shorthand for `{ name, exists: true }` (set + non-empty). The object form supports either presence assertions or exact-value matching."
487
+ }
488
+ }
489
+ ],
490
+ "description": "Match against environment variables. A bare string asserts the variable is set and non-empty; the object form lets you match an exact value or just assert presence/absence."
491
+ },
492
+ "not": {
493
+ "type": "object",
494
+ "properties": {
495
+ "branch": {
496
+ "anyOf": [
497
+ {
498
+ "type": "string"
499
+ },
500
+ {
501
+ "type": "array",
502
+ "items": {
503
+ "type": "string"
504
+ }
505
+ }
506
+ ]
507
+ },
508
+ "ci": {
509
+ "type": "boolean"
510
+ },
511
+ "env": {
512
+ "anyOf": [
513
+ {
514
+ "anyOf": [
515
+ {
516
+ "type": "string"
517
+ },
518
+ {
519
+ "type": "object",
520
+ "properties": {
521
+ "equals": {
522
+ "type": "string",
523
+ "description": "Match this exact value. Mutually exclusive with `exists`."
524
+ },
525
+ "exists": {
526
+ "type": "boolean",
527
+ "description": "Assert the variable is set & non-empty (`true`) or unset/empty (`false`)."
528
+ },
529
+ "name": {
530
+ "type": "string",
531
+ "description": "Variable name."
532
+ }
533
+ },
534
+ "required": [
535
+ "name"
536
+ ],
537
+ "additionalProperties": false
538
+ }
539
+ ],
540
+ "description": "An environment-variable match. The string form is shorthand for `{ name, exists: true }` (set + non-empty). The object form supports either presence assertions or exact-value matching."
541
+ },
542
+ {
543
+ "type": "array",
544
+ "items": {
545
+ "anyOf": [
546
+ {
547
+ "type": "string"
548
+ },
549
+ {
550
+ "type": "object",
551
+ "properties": {
552
+ "equals": {
553
+ "type": "string",
554
+ "description": "Match this exact value. Mutually exclusive with `exists`."
555
+ },
556
+ "exists": {
557
+ "type": "boolean",
558
+ "description": "Assert the variable is set & non-empty (`true`) or unset/empty (`false`)."
559
+ },
560
+ "name": {
561
+ "type": "string",
562
+ "description": "Variable name."
563
+ }
564
+ },
565
+ "required": [
566
+ "name"
567
+ ],
568
+ "additionalProperties": false
569
+ }
570
+ ],
571
+ "description": "An environment-variable match. The string form is shorthand for `{ name, exists: true }` (set + non-empty). The object form supports either presence assertions or exact-value matching."
572
+ }
573
+ }
574
+ ]
575
+ },
576
+ "os": {
577
+ "anyOf": [
578
+ {
579
+ "type": "string",
580
+ "enum": [
581
+ "aix",
582
+ "darwin",
583
+ "freebsd",
584
+ "linux",
585
+ "openbsd",
586
+ "sunos",
587
+ "windows",
588
+ "win32"
589
+ ],
590
+ "description": "Aliased platform list — `\"windows\"` is sugar for Node's `\"win32\"`."
591
+ },
592
+ {
593
+ "type": "array",
594
+ "items": {
595
+ "type": "string",
596
+ "enum": [
597
+ "aix",
598
+ "darwin",
599
+ "freebsd",
600
+ "linux",
601
+ "openbsd",
602
+ "sunos",
603
+ "windows",
604
+ "win32"
605
+ ],
606
+ "description": "Aliased platform list — `\"windows\"` is sugar for Node's `\"win32\"`."
607
+ }
608
+ }
609
+ ]
610
+ }
611
+ },
612
+ "additionalProperties": false,
613
+ "description": "Negative mirrors. A task runs only when *all* `not.*` clauses fail."
614
+ },
615
+ "os": {
616
+ "anyOf": [
617
+ {
618
+ "type": "string",
619
+ "enum": [
620
+ "aix",
621
+ "darwin",
622
+ "freebsd",
623
+ "linux",
624
+ "openbsd",
625
+ "sunos",
626
+ "windows",
627
+ "win32"
628
+ ],
629
+ "description": "Aliased platform list — `\"windows\"` is sugar for Node's `\"win32\"`."
630
+ },
631
+ {
632
+ "type": "array",
633
+ "items": {
634
+ "type": "string",
635
+ "enum": [
636
+ "aix",
637
+ "darwin",
638
+ "freebsd",
639
+ "linux",
640
+ "openbsd",
641
+ "sunos",
642
+ "windows",
643
+ "win32"
644
+ ],
645
+ "description": "Aliased platform list — `\"windows\"` is sugar for Node's `\"win32\"`."
646
+ }
647
+ }
648
+ ],
649
+ "description": "Match `process.platform` (`\"linux\" | \"darwin\" | \"win32\" | \"freebsd\" | \"openbsd\" | \"sunos\" | \"aix\"`). Pass `\"windows\"` as an alias for `\"win32\"` — easier to remember and matches what people type."
650
+ }
651
+ },
652
+ "additionalProperties": false,
653
+ "description": "Predicate that gates execution. When the condition evaluates to `false` for the current environment, the task is skipped (marked `\"skipped\"`, not failed). Combine with `os`, `env`, `branch`, and `ci` clauses for granular control:\n\n ```ts when: { os: \"linux\", ci: true, env: \"DEPLOY_TOKEN\" } ```"
654
+ },
655
+ "aliases": {
656
+ "type": "array",
657
+ "items": {
658
+ "type": "string"
659
+ },
660
+ "description": "Alternate names that resolve to this target on the CLI. Useful for shortening long canonical names (`test` ↔ `t`) or for offering migration-friendly aliases when renaming targets. Aliases must be globally unique within the workspace."
661
+ },
662
+ "arguments": {
663
+ "type": "array",
664
+ "items": {
665
+ "$ref": "#/$defs/TaskArgument"
666
+ },
667
+ "description": "Declarative argument schema for this target. Forwarded CLI args (`vis run <target> -- --flag value`) are validated against it, surfaced by per-task `--help`, and exposed to the command as `VIS_ARG_<NAME>` environment variables."
668
+ },
669
+ "description": {
670
+ "type": "string",
671
+ "description": "One-line description surfaced by `vis list` and per-task `--help`. Kept short — longer docs belong in project READMEs or vis.config.ts comments."
672
+ },
673
+ "inferred": {
674
+ "type": "boolean",
675
+ "description": "True when the target was synthesized by a Project Crystal-style detector (see {@link ../inference } ) rather than declared by a package.json script, project.json, or vis.task.ts file. Surfaced by `vis list --inferred` and used by tooling to distinguish implicit defaults from explicit user intent."
676
+ },
677
+ "options": {
678
+ "$ref": "#/$defs/VisTargetOptions",
679
+ "description": "Vis-specific target options."
680
+ },
681
+ "preset": {
682
+ "$ref": "#/$defs/TargetPreset",
683
+ "description": "Preset applied before user-specified options."
684
+ },
685
+ "type": {
686
+ "$ref": "#/$defs/TargetType",
687
+ "description": "Semantic task type. Affects caching defaults and CI filtering.",
688
+ "default": "test"
689
+ }
690
+ },
691
+ "additionalProperties": false,
692
+ "description": "An extended target configuration that adds the vis-specific options on top of task-runner's `TargetConfiguration`."
693
+ },
694
+ "TaskArgument": {
695
+ "type": "object",
696
+ "properties": {
697
+ "alias": {
698
+ "type": "string",
699
+ "description": "Short single-character alias (e.g. `r` for `--reporter`, used as `-r`). Must be exactly one character — enforced at run time by {@link validateArgumentSchema } ."
700
+ },
701
+ "choices": {
702
+ "type": "array",
703
+ "items": {
704
+ "type": "string"
705
+ },
706
+ "description": "Allowed values when {@link TaskArgument.type } is `\"enum\"`. Must be non-empty (and is required) for `enum` — enforced at run time by {@link validateArgumentSchema } ."
707
+ },
708
+ "default": {
709
+ "$ref": "#/$defs/TaskArgumentValue",
710
+ "description": "Value applied when the argument is omitted. Skips the required check."
711
+ },
712
+ "description": {
713
+ "type": "string",
714
+ "description": "One-line help text surfaced by per-task `--help`."
715
+ },
716
+ "name": {
717
+ "type": "string",
718
+ "description": "Canonical name, without the leading `--` (kebab-case by convention). Must start with a letter and contain only letters, digits, `-`, `_` — enforced at run time by {@link validateArgumentSchema } ."
719
+ },
720
+ "positional": {
721
+ "type": "boolean",
722
+ "description": "Consume the value from the next free positional argument instead of a `--flag`. Positional args are filled in declaration order."
723
+ },
724
+ "required": {
725
+ "type": "boolean",
726
+ "description": "Fail the task when the argument is absent and has no `default`."
727
+ },
728
+ "type": {
729
+ "$ref": "#/$defs/TaskArgumentType",
730
+ "description": "Value type for coercion + validation. Defaults to `\"string\"`."
731
+ }
732
+ },
733
+ "required": [
734
+ "name"
735
+ ],
736
+ "additionalProperties": false,
737
+ "description": "A single declared argument for a task target."
738
+ },
739
+ "TaskArgumentValue": {
740
+ "type": [
741
+ "boolean",
742
+ "number",
743
+ "string"
744
+ ],
745
+ "description": "A coerced task-argument value."
746
+ },
747
+ "TaskArgumentType": {
748
+ "type": "string",
749
+ "enum": [
750
+ "boolean",
751
+ "enum",
752
+ "number",
753
+ "string"
754
+ ],
755
+ "description": "Value type a {@link TaskArgument } coerces to and validates against."
756
+ },
757
+ "VisTargetOptions": {
758
+ "type": "object",
759
+ "properties": {
760
+ "affectedFiles": {
761
+ "$ref": "#/$defs/AffectedFilesMode",
762
+ "description": "How to forward affected files to the task process. Only used when invoked via `vis affected <target>`.",
763
+ "default": false
764
+ },
765
+ "envFile": {
766
+ "anyOf": [
767
+ {
768
+ "type": "boolean"
769
+ },
770
+ {
771
+ "type": "string"
772
+ },
773
+ {
774
+ "type": "array",
775
+ "items": {
776
+ "type": "string"
777
+ }
778
+ }
779
+ ],
780
+ "description": "Load environment variables from dotenv file(s) before running.\n- `string`: a single file path (relative to project root).\n- `string[]`: multiple files — later entries override earlier ones, so put more-specific files last (e.g. `[\".env\", \".env.local\"]`).\n- `true`: auto-cascade in the Next/Vite order: `.env` → `.env.{NODE_ENV}` → `.env.local` → `.env.{NODE_ENV}.local`. Skips `.env.local` when NODE_ENV is `test`, matching Next.js."
781
+ },
782
+ "interactive": {
783
+ "type": "boolean",
784
+ "description": "When true, the task is serialized with respect to parallel execution and must be run on the main process (claims stdin). Used for commands that read from the terminal.",
785
+ "default": false
786
+ },
787
+ "internal": {
788
+ "type": "boolean",
789
+ "description": "When true, the task is hidden from CLI listings and can only be invoked as a dependency of another task.",
790
+ "default": false
791
+ },
792
+ "killGracePeriodMs": {
793
+ "type": "number",
794
+ "description": "Milliseconds the timeout watchdog waits between sending SIGTERM and SIGKILL when the `timeout` budget fires. Tasks that ignore SIGTERM (e.g. test runners holding open child processes) get force-killed after this grace window so a stuck task can't outlive its budget.\n\nSet to `0` to skip escalation and rely on SIGTERM only.",
795
+ "default": 5000
796
+ },
797
+ "mutex": {
798
+ "type": "string",
799
+ "description": "Serializes all tasks that share the same mutex name. Useful for tasks that contend on a shared resource (e.g., a database migration)."
800
+ },
801
+ "outputStyle": {
802
+ "type": "string",
803
+ "enum": [
804
+ "normal",
805
+ "quiet"
806
+ ],
807
+ "description": "Per-target output verbosity. Overrides the global `--output-style` flag for this specific target.\n\n- `\"normal\"` (default): print every task's terminal output\n- `\"quiet\"`: only print output when the task fails. Successful and cached tasks contribute their status line and timing, but their captured stdout/stderr is suppressed.\n\nUseful when a routinely-noisy task (a linter or test runner with verbose progress output) should stay quiet during green builds but reveal everything when it fails."
808
+ },
809
+ "persistent": {
810
+ "type": "boolean",
811
+ "description": "When true, the task is a long-running / never-ending process. Persistent tasks are scheduled last, execute after all cacheable tasks complete, and are never cached.",
812
+ "default": false
813
+ },
814
+ "preset": {
815
+ "$ref": "#/$defs/TargetPreset",
816
+ "description": "A preset that pre-fills a common bundle of options. User-provided fields always take precedence over the preset."
817
+ },
818
+ "pty": {
819
+ "type": "boolean",
820
+ "description": "Run the task through a pseudo-terminal so color-aware tools (vitest, eslint, biome, …) render as if attached to a real TTY instead of a pipe. Output is captured via task-runner's `TerminalBuffer` so ANSI escapes are normalized into the final rendered state before reaching the reporter.\n\nForces cache to off — PTY output can include timing-dependent frames (spinners) that aren't safe to replay from a cache.",
821
+ "default": false
822
+ },
823
+ "retryCount": {
824
+ "type": "number",
825
+ "description": "Number of times to retry the task on failure. Uses an exponential backoff by default (1s, 2s, 4s, ...).",
826
+ "default": 0
827
+ },
828
+ "retryDelay": {
829
+ "anyOf": [
830
+ {
831
+ "type": "number"
832
+ },
833
+ {
834
+ "type": "string",
835
+ "const": "exponential"
836
+ }
837
+ ],
838
+ "description": "Delay between retry attempts in milliseconds, or `\"exponential\"` for 2^attempt * 1000 ms.",
839
+ "default": "exponential"
840
+ },
841
+ "runFromWorkspaceRoot": {
842
+ "type": "boolean",
843
+ "description": "When true, the command executes with the workspace root as CWD instead of the project root.",
844
+ "default": false
845
+ },
846
+ "runInCI": {
847
+ "$ref": "#/$defs/RunInCI",
848
+ "description": "Controls whether the task runs in CI environments.",
849
+ "default": true
850
+ },
851
+ "runnerTags": {
852
+ "type": "array",
853
+ "items": {
854
+ "type": "string"
855
+ },
856
+ "description": "Capability tags that gate this task to runners advertising the same tag. The CLI's `--runner-tags=gpu,slow` flag (or `VIS_RUNNER_TAGS` env var) tells vis what the current runner supports; tasks whose `runnerTags` share at least one tag with the runner set are eligible. Untagged tasks (no `runnerTags` or an empty array) are general-purpose and always run.\n\nUse this for special-purpose CI lanes — e.g. a GPU runner that should only pick up visual-regression suites, or a nightly job that runs `slow` integration tests. When neither flag nor env is set, the filter is inactive and every task runs."
857
+ },
858
+ "service": {
859
+ "$ref": "#/$defs/ServiceConfig",
860
+ "description": "Marks this target as a long-lived service that can be started via `vis service start <id>` and auto-attached when other tasks declare it in `dependsOn`. Implies persistent + non-cacheable behaviour (set `preset: \"server\"` to inherit the rest of the bundle).\n\nThe presence of this block — not `preset: \"server\"` alone — is what makes a target eligible for the cross-invocation registry. `preset: \"server\"` without `service` keeps today's in-run-only behaviour."
861
+ },
862
+ "shell": {
863
+ "type": "string",
864
+ "description": "Per-target shell override. When set, the command runs through this shell instead of the platform default."
865
+ },
866
+ "shellArgs": {
867
+ "type": "array",
868
+ "items": {
869
+ "type": "string"
870
+ },
871
+ "description": "Arguments passed to the per-target shell/interpreter before the command string. Defaults to `[\"-c\"]` (POSIX shells, pwsh). Set this to run the command under an interpreter that uses a different flag — e.g. `shell: \"node\", shellArgs: [\"-e\"]` runs the command as inline JS (\"script mode\"), or `shellArgs: [\"-lc\"]` for a login shell. Only applies when `shell`/`unixShell`/`windowsShell` resolves to a custom shell.\n\nMust be non-empty when set — an empty array would drop the interpreter flag entirely, so the runtime falls back to `-c` defensively."
872
+ },
873
+ "strictEnv": {
874
+ "type": "boolean",
875
+ "description": "Override the workspace `strictEnv` setting for this target. When truthy, the target fails if its command references an env var that resolves to neither the task's effective env nor `process.env`. When `false`, the target opts out of a workspace `strictEnv: true` (e.g. for a one-off command that legitimately tolerates an unset variable)."
876
+ },
877
+ "timeout": {
878
+ "type": "number",
879
+ "description": "Maximum wall-clock milliseconds a single task run is allowed to take before being killed. `0` / `undefined` means no timeout.\n\nWhen the timeout fires the task is sent SIGTERM and, if it has not exited within `killGracePeriodMs`, SIGKILL. The task exits with a failure status carrying the `[timeout]` marker in `terminalOutput`. Retries count per-attempt, not cumulatively.\n\nUse this to prevent runaway tasks from eating CI wall-clock time up to the job-level cutoff."
880
+ },
881
+ "unixShell": {
882
+ "type": "string",
883
+ "description": "Per-target unix shell override, used on Linux and macOS. Takes precedence over `shell` on unix-like systems."
884
+ },
885
+ "windowsShell": {
886
+ "type": "string",
887
+ "description": "Per-target windows shell override, used on Windows. Takes precedence over `shell` on Windows."
888
+ }
889
+ },
890
+ "additionalProperties": false,
891
+ "description": "Vis-specific target options that extend the task-runner's base `TargetConfiguration`. These live under `target.options` and are interpreted by vis before handing the task off to task-runner.\n\nConditional execution (`when:`) and finally tasks (`always:`) live at the target top level, not under `options` — they're handled by the task-runner orchestrator. See `@visulima/task-runner`'s `WhenCondition`."
892
+ },
893
+ "AffectedFilesMode": {
894
+ "type": [
895
+ "string",
896
+ "boolean"
897
+ ],
898
+ "enum": [
899
+ "args",
900
+ "both",
901
+ "env",
902
+ false
903
+ ],
904
+ "description": "Controls how affected files are forwarded to a task.\n- `false` (default): Do not forward.\n- `\"args\"`: Append affected paths as additional command arguments.\n- `\"env\"`: Expose them via `VIS_AFFECTED_FILES` environment variable.\n- `\"both\"`: Both of the above."
905
+ },
906
+ "TargetPreset": {
907
+ "type": "string",
908
+ "enum": [
909
+ "server",
910
+ "utility"
911
+ ],
912
+ "description": "Preset bundles of target options.\n- `server`: Long-running local dev server — caching off, not in CI, interactive, persistent.\n- `utility`: Short-lived helper — caching off, not in CI."
913
+ },
914
+ "RunInCI": {
915
+ "anyOf": [
916
+ {
917
+ "type": "string",
918
+ "const": "affected"
919
+ },
920
+ {
921
+ "type": "string",
922
+ "const": "always"
923
+ },
924
+ {
925
+ "type": "boolean"
926
+ }
927
+ ],
928
+ "description": "Controls whether a target runs in CI.\n- `true` (default): Always run.\n- `false`: Never run in CI (local-only).\n- `\"affected\"`: Only when the project is affected by the current change set.\n- `\"always\"`: Always run, even if unaffected."
929
+ },
930
+ "ServiceConfig": {
931
+ "type": "object",
932
+ "properties": {
933
+ "env": {
934
+ "type": "object",
935
+ "additionalProperties": {
936
+ "type": "string"
937
+ },
938
+ "description": "Env vars to expose to dependent tasks when this service is registered. Merged into the dependent task's env after the task's own envFile and before the task's explicit `env` overrides — the dependent task wins on key collisions.\n\nNote: only this `env` map propagates to dependents. The service target's own `envFile` is loaded into the **service process** at start time but is *not* forwarded — dependents must declare any shared values they need either here or in their own envFile. This boundary is intentional: envFiles often contain operator-only secrets (deploy keys, admin tokens) that should not leak into downstream test commands."
939
+ },
940
+ "killGracePeriodMs": {
941
+ "type": "number",
942
+ "description": "Grace period in milliseconds between SIGTERM and SIGKILL when the service is stopped.",
943
+ "default": 5000
944
+ },
945
+ "port": {
946
+ "type": "number",
947
+ "description": "Optional port the service listens on. Used as the default for `readiness.tcp.port` when no explicit probe is configured, and surfaced by `vis service list`."
948
+ },
949
+ "readiness": {
950
+ "type": "object",
951
+ "properties": {
952
+ "tcp": {
953
+ "type": "object",
954
+ "properties": {
955
+ "host": {
956
+ "type": "string"
957
+ },
958
+ "port": {
959
+ "type": "number"
960
+ },
961
+ "timeoutMs": {
962
+ "type": "number"
963
+ }
964
+ },
965
+ "required": [
966
+ "port"
967
+ ],
968
+ "additionalProperties": false
969
+ }
970
+ },
971
+ "required": [
972
+ "tcp"
973
+ ],
974
+ "additionalProperties": false,
975
+ "description": "Readiness probe configuration. v1 supports TCP only."
976
+ }
977
+ },
978
+ "additionalProperties": false,
979
+ "description": "Configuration block declared on a target to mark it as a long-lived \"service\" — eligible to be started/stopped via `vis service` and auto-attached when other tasks depend on it.\n\nTargets must also carry `preset: \"server\"` (or the equivalent `persistent: true`) for the service-mode lifecycle to apply."
980
+ },
981
+ "TargetType": {
982
+ "type": "string",
983
+ "enum": [
984
+ "build",
985
+ "run",
986
+ "test"
987
+ ],
988
+ "description": "Semantic classification for a target.\n- `build`: Generates one or more artifacts; cached by default.\n- `test`: Validation task (lint, typecheck, unit test). Default type.\n- `run`: One-off or long-running process. Not cached by default."
989
+ }
990
+ }
991
+ }