@visulima/vis 1.0.0-alpha.9 → 1.0.0

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 (278) hide show
  1. package/CHANGELOG.md +1844 -3
  2. package/LICENSE.md +13515 -10
  3. package/README.md +215 -39
  4. package/bin/resolve-binary.mjs +85 -0
  5. package/bin/vis.mjs +76 -0
  6. package/dashboard/dist/index.html +152 -0
  7. package/dist/bin.d.ts +1 -0
  8. package/dist/bin.js +1 -2
  9. package/dist/binx.js +3 -0
  10. package/dist/config/index.d.ts +3276 -0
  11. package/dist/config/index.js +1 -0
  12. package/dist/generate/index.d.ts +1 -1
  13. package/dist/generate/index.js +1 -1
  14. package/dist/packem_chunks/CONFIG_FILES.js +8 -0
  15. package/dist/packem_chunks/DEFAULT_CLEAN_KEEP.js +1 -0
  16. package/dist/packem_chunks/agent-instructions.js +11 -0
  17. package/dist/packem_chunks/bloom-status.js +2 -0
  18. package/dist/packem_chunks/bloom-sync.js +2 -0
  19. package/dist/packem_chunks/cache-attestation.js +1 -0
  20. package/dist/packem_chunks/catalog-detector.js +1 -0
  21. package/dist/packem_chunks/catalog.js +114 -0
  22. package/dist/packem_chunks/cli-exec.js +1 -0
  23. package/dist/packem_chunks/cli-main.js +268 -0
  24. package/dist/packem_chunks/defineReleasePlugin.js +3 -0
  25. package/dist/packem_chunks/detect.js +3 -0
  26. package/dist/packem_chunks/detect2.js +8 -0
  27. package/dist/packem_chunks/devtools.js +4 -0
  28. package/dist/packem_chunks/discord.js +4 -0
  29. package/dist/packem_chunks/dispatch.js +4 -0
  30. package/dist/packem_chunks/doctor-probe.js +2 -0
  31. package/dist/packem_chunks/dynamic-import.js +1 -0
  32. package/dist/packem_chunks/extra-files.js +3 -0
  33. package/dist/packem_chunks/fix.js +11 -0
  34. package/dist/packem_chunks/git.js +3 -0
  35. package/dist/packem_chunks/group-tags.js +1 -0
  36. package/dist/packem_chunks/handler.js +1 -1
  37. package/dist/packem_chunks/handler10.js +5 -1
  38. package/dist/packem_chunks/handler11.js +1 -1
  39. package/dist/packem_chunks/handler12.js +26 -152
  40. package/dist/packem_chunks/handler13.js +5 -1
  41. package/dist/packem_chunks/handler14.js +1 -3
  42. package/dist/packem_chunks/handler15.js +1 -1
  43. package/dist/packem_chunks/handler16.js +1 -2
  44. package/dist/packem_chunks/handler17.js +1 -7
  45. package/dist/packem_chunks/handler18.js +1 -1
  46. package/dist/packem_chunks/handler19.js +5 -19
  47. package/dist/packem_chunks/handler2.js +1 -1
  48. package/dist/packem_chunks/handler20.js +2 -428
  49. package/dist/packem_chunks/handler21.js +2 -22
  50. package/dist/packem_chunks/handler22.js +14 -3
  51. package/dist/packem_chunks/handler23.js +1 -5
  52. package/dist/packem_chunks/handler24.js +1 -1
  53. package/dist/packem_chunks/handler25.js +1 -20
  54. package/dist/packem_chunks/handler26.js +5 -1
  55. package/dist/packem_chunks/handler27.js +1 -1
  56. package/dist/packem_chunks/handler28.js +3 -1
  57. package/dist/packem_chunks/handler29.js +1 -2
  58. package/dist/packem_chunks/handler3.js +4 -2
  59. package/dist/packem_chunks/handler30.js +1 -22
  60. package/dist/packem_chunks/handler31.js +2 -1
  61. package/dist/packem_chunks/handler32.js +2 -1
  62. package/dist/packem_chunks/handler33.js +2 -37
  63. package/dist/packem_chunks/handler34.js +3 -3
  64. package/dist/packem_chunks/handler35.js +6 -23
  65. package/dist/packem_chunks/handler36.js +1 -5
  66. package/dist/packem_chunks/handler37.js +36 -21
  67. package/dist/packem_chunks/handler38.js +8 -1
  68. package/dist/packem_chunks/handler39.js +9 -2
  69. package/dist/packem_chunks/handler4.js +4 -5
  70. package/dist/packem_chunks/handler40.js +75 -1
  71. package/dist/packem_chunks/handler41.js +5 -5
  72. package/dist/packem_chunks/handler42.js +4 -1
  73. package/dist/packem_chunks/handler43.js +3 -24
  74. package/dist/packem_chunks/handler44.js +2 -3
  75. package/dist/packem_chunks/handler45.js +1 -1
  76. package/dist/packem_chunks/handler46.js +1 -0
  77. package/dist/packem_chunks/handler47.js +1 -0
  78. package/dist/packem_chunks/handler48.js +3 -0
  79. package/dist/packem_chunks/handler49.js +1 -0
  80. package/dist/packem_chunks/handler5.js +6 -4
  81. package/dist/packem_chunks/handler50.js +7 -0
  82. package/dist/packem_chunks/handler51.js +33 -0
  83. package/dist/packem_chunks/handler52.js +3 -0
  84. package/dist/packem_chunks/handler53.js +8 -0
  85. package/dist/packem_chunks/handler54.js +4 -0
  86. package/dist/packem_chunks/handler55.js +1 -0
  87. package/dist/packem_chunks/handler56.js +12 -0
  88. package/dist/packem_chunks/handler57.js +11 -0
  89. package/dist/packem_chunks/handler58.js +5 -0
  90. package/dist/packem_chunks/handler59.js +11 -0
  91. package/dist/packem_chunks/handler6.js +8 -2
  92. package/dist/packem_chunks/handler60.js +3 -0
  93. package/dist/packem_chunks/handler61.js +22 -0
  94. package/dist/packem_chunks/handler62.js +61 -0
  95. package/dist/packem_chunks/handler63.js +3 -0
  96. package/dist/packem_chunks/handler64.js +6 -0
  97. package/dist/packem_chunks/handler65.js +9 -0
  98. package/dist/packem_chunks/handler66.js +2 -0
  99. package/dist/packem_chunks/handler67.js +24 -0
  100. package/dist/packem_chunks/handler68.js +25 -0
  101. package/dist/packem_chunks/handler69.js +153 -0
  102. package/dist/packem_chunks/handler7.js +1 -24
  103. package/dist/packem_chunks/handler70.js +10 -0
  104. package/dist/packem_chunks/handler71.js +23 -0
  105. package/dist/packem_chunks/handler72.js +322 -0
  106. package/dist/packem_chunks/handler73.js +708 -0
  107. package/dist/packem_chunks/handler74.js +48 -0
  108. package/dist/packem_chunks/handler75.js +27 -0
  109. package/dist/packem_chunks/handler76.js +3 -0
  110. package/dist/packem_chunks/handler77.js +190 -0
  111. package/dist/packem_chunks/handler78.js +38 -0
  112. package/dist/packem_chunks/handler8.js +1 -6
  113. package/dist/packem_chunks/handler9.js +1 -8
  114. package/dist/packem_chunks/heal-accept.js +10 -0
  115. package/dist/packem_chunks/heal.js +14 -0
  116. package/dist/packem_chunks/help-command.js +31 -0
  117. package/dist/packem_chunks/index.js +1 -7
  118. package/dist/packem_chunks/index2.js +802 -0
  119. package/dist/packem_chunks/index3.js +7 -0
  120. package/dist/packem_chunks/index4.js +135 -0
  121. package/dist/packem_chunks/index5.js +74 -0
  122. package/dist/packem_chunks/interface.js +2 -0
  123. package/dist/packem_chunks/keys-refresh.js +4 -0
  124. package/dist/packem_chunks/lean.js +4 -0
  125. package/dist/packem_chunks/list.js +3 -0
  126. package/dist/packem_chunks/loader.js +4 -1
  127. package/dist/packem_chunks/loader2.js +1 -0
  128. package/dist/packem_chunks/orchestrator.js +42 -0
  129. package/dist/packem_chunks/pre-mode.js +2 -0
  130. package/dist/packem_chunks/print-config.js +2 -0
  131. package/dist/packem_chunks/prompts.js +7 -0
  132. package/dist/packem_chunks/prune.js +3 -0
  133. package/dist/packem_chunks/publish-guards.js +1 -0
  134. package/dist/packem_chunks/registry.js +48 -0
  135. package/dist/packem_chunks/resolveFormatter.js +9 -0
  136. package/dist/packem_chunks/run.js +1 -0
  137. package/dist/packem_chunks/security.js +1 -0
  138. package/dist/packem_chunks/shell-runner.js +1 -0
  139. package/dist/packem_chunks/slack.js +2 -0
  140. package/dist/packem_chunks/snapshot.js +2 -0
  141. package/dist/packem_chunks/stage-publisher.js +1 -0
  142. package/dist/packem_chunks/staged-registry.js +2 -0
  143. package/dist/packem_chunks/state.js +3 -0
  144. package/dist/packem_chunks/status.js +2 -0
  145. package/dist/packem_chunks/success-walk.js +8 -0
  146. package/dist/packem_chunks/sync.js +2 -0
  147. package/dist/packem_chunks/sync2.js +2 -0
  148. package/dist/packem_chunks/tar.js +3 -0
  149. package/dist/packem_chunks/tripwire.js +2 -0
  150. package/dist/packem_chunks/ts-loader.js +22 -0
  151. package/dist/packem_chunks/verify-lockfile.js +2 -0
  152. package/dist/packem_chunks/version-resolver.js +2 -0
  153. package/dist/packem_chunks/webhook.js +1 -0
  154. package/dist/packem_chunks/workflow-templates.js +167 -0
  155. package/dist/packem_chunks/workspace.js +2 -0
  156. package/dist/packem_shared/AfterAllProjectsVersioned-CAKI2nWf.js +1 -0
  157. package/dist/packem_shared/MultiSpinner-B9U0-aE3-B-gIXhFk.js +3 -0
  158. package/dist/packem_shared/ReleaseClient-BY4OZNCK.js +1 -0
  159. package/dist/packem_shared/Table-CcVkyULl-DLWu6XHL.js +34 -0
  160. package/dist/packem_shared/VisReleaseError-DMGRBTNO.js +1 -0
  161. package/dist/packem_shared/_commonjsHelpers-B5Y90VFO.js +1 -0
  162. package/dist/packem_shared/advisories-B76fBVL-.js +1 -0
  163. package/dist/packem_shared/affected-shas-CCxG4tvm.js +1 -0
  164. package/dist/packem_shared/ai-analysis-BpVdn20h.js +68 -0
  165. package/dist/packem_shared/ai-fix-CeGzAT9m.js +43 -0
  166. package/dist/packem_shared/anolilab-text-CAM_E6uK.js +13 -0
  167. package/dist/packem_shared/api.d-BPftyU9r.d.ts +27 -0
  168. package/dist/packem_shared/augment-DaSS2Lgs.js +4 -0
  169. package/dist/packem_shared/bin-BlGVEhl8.js +1 -0
  170. package/dist/packem_shared/build-scripts-q__dKE2y.js +1 -0
  171. package/dist/packem_shared/command-runtime-3FTGuUsK.js +1 -0
  172. package/dist/packem_shared/compile-cache-B_Vf_WxT.js +3 -0
  173. package/dist/packem_shared/createAdapter-bU4DIP3F.js +1 -0
  174. package/dist/packem_shared/createVersionActions-BK43SNDH.js +1 -0
  175. package/dist/packem_shared/cyclonedx-CmrYQ0vx.js +4 -0
  176. package/dist/packem_shared/defineFormatter-D5dCp6Kv.js +1 -0
  177. package/dist/packem_shared/definePlugin-DoUcoYSy.js +1 -0
  178. package/dist/packem_shared/dependency-scan-DpOFiZuI.js +1 -0
  179. package/dist/packem_shared/docker-BYqiD711.js +59 -0
  180. package/dist/packem_shared/env-DdQRnEIy.js +27 -0
  181. package/dist/packem_shared/failure-log-CKMhqLWr.js +2 -0
  182. package/dist/packem_shared/giget-DVTFJlbR.js +2 -0
  183. package/dist/packem_shared/glob-fqg4KepW-1S3z30c8.js +1 -0
  184. package/dist/packem_shared/index-B0EsgdzO.js +1 -0
  185. package/dist/packem_shared/index-CE6MsgcV.js +22 -0
  186. package/dist/packem_shared/index-Cg0IHaFI.js +1 -0
  187. package/dist/packem_shared/index-Cg71MisW.js +1 -0
  188. package/dist/packem_shared/index-DjTWo3sH.js +1 -0
  189. package/dist/packem_shared/index-jJNulo5i.js +28 -0
  190. package/dist/packem_shared/index.server-J83sowC4.js +2 -0
  191. package/dist/packem_shared/interface.d-B7VK2rcH.d.ts +148 -0
  192. package/dist/packem_shared/interface.d-Cezzifoh.d.ts +106 -0
  193. package/dist/packem_shared/license-t5KnNX6v.js +1 -0
  194. package/dist/packem_shared/lifecycle-aDTZ8dW1.js +2 -0
  195. package/dist/packem_shared/lockfile-C1qCKGH6.js +1 -0
  196. package/dist/packem_shared/main-B3juSU5z.js +1 -0
  197. package/dist/packem_shared/manifests-DSBr3-dw.js +1 -0
  198. package/dist/packem_shared/min-release-age-C71MO72F.js +34 -0
  199. package/dist/packem_shared/missing-package-json-CTF71tE5.js +1 -0
  200. package/dist/packem_shared/native-config-sync-D-z2Uwqu.js +21 -0
  201. package/dist/packem_shared/osv-bloom-DMhXP184.js +2 -0
  202. package/dist/packem_shared/otelPlugin-DmKDBaPo.js +1 -0
  203. package/dist/packem_shared/packument-aGzYwXKn.js +1 -0
  204. package/dist/packem_shared/peer-warnings-BXAzXqY3.js +1 -0
  205. package/dist/packem_shared/plugins.d-ND23R9I3.d.ts +4 -0
  206. package/dist/packem_shared/pm-runner-CQcraCcu.js +1 -0
  207. package/dist/packem_shared/prompt-DjXHVgYU.js +1 -0
  208. package/dist/packem_shared/provenance-S7y0BRAt.js +1 -0
  209. package/dist/packem_shared/public-api-WqUCiyIe.js +131 -0
  210. package/dist/packem_shared/readJsonSync-DuMMeB3s-ihoybKvs.js +1 -0
  211. package/dist/packem_shared/registry-keys-CRnXATt2.js +1 -0
  212. package/dist/packem_shared/resolve-explicit-CJGazevw.js +5 -0
  213. package/dist/packem_shared/resolve-runtime-QRaQucfL.js +1 -0
  214. package/dist/packem_shared/run-file-DD7Ne23Z.js +1 -0
  215. package/dist/packem_shared/runtime-check-qnrPTlma.js +1 -0
  216. package/dist/packem_shared/runtime-process-Dmz0vCJy-DUwTvH1J.js +1 -0
  217. package/dist/packem_shared/s1ngularity-BLj4Jy8z.js +1 -0
  218. package/dist/packem_shared/scan-progress-BDcl7Kty.js +2 -0
  219. package/dist/packem_shared/selectors-D4iCvITE.js +3 -0
  220. package/dist/packem_shared/signatures-DoNG2hEr.js +2 -0
  221. package/dist/packem_shared/slug-DoueYuLo.js +1 -0
  222. package/dist/packem_shared/spinner-DuJJvFTl.js +1 -0
  223. package/dist/packem_shared/sticky-comment-D6_7-w8T.js +1 -0
  224. package/dist/packem_shared/subtree-C7bZuiSQ.js +2 -0
  225. package/dist/packem_shared/symbols-DPTlrJ3B.js +1 -0
  226. package/dist/packem_shared/tabs-CgxCvjCY.js +1 -0
  227. package/dist/packem_shared/target-merge-Dg25Izl5.js +11 -0
  228. package/dist/packem_shared/target-options-CR0OuYJr.js +1 -0
  229. package/dist/packem_shared/toolchain-Zb3VzZb4.js +5 -0
  230. package/dist/packem_shared/typosquats-C12CP_2G.js +1 -0
  231. package/dist/packem_shared/use-measured-height-CjS7Tks7.js +1 -0
  232. package/dist/packem_shared/utils-CRueU43T.js +1 -0
  233. package/dist/packem_shared/verify-DStfg3nb.js +1 -0
  234. package/dist/packem_shared/vis-update-app-BlocL713.js +1 -0
  235. package/dist/packem_shared/watch-BXNI7dC6.js +1 -0
  236. package/dist/packem_shared/watch-loop-BZudYfcl.js +11 -0
  237. package/dist/release/core/changelog/index.d.ts +5 -0
  238. package/dist/release/core/changelog/index.js +1 -0
  239. package/dist/release/core/package-managers/index.d.ts +6 -0
  240. package/dist/release/core/package-managers/index.js +1 -0
  241. package/dist/release/core/version-actions/index.d.ts +14 -0
  242. package/dist/release/core/version-actions/index.js +1 -0
  243. package/dist/release/index.d.ts +233 -0
  244. package/dist/release/index.js +1 -0
  245. package/dist/release/plugin-sdk.d.ts +128 -0
  246. package/dist/release/plugin-sdk.js +1 -0
  247. package/dist/release/presets.d.ts +225 -0
  248. package/dist/release/presets.js +1 -0
  249. package/dist/release/types.d.ts +1493 -0
  250. package/dist/release/types.js +1 -0
  251. package/dist/runtime/preload.d.ts +1 -0
  252. package/dist/runtime/preload.js +1 -0
  253. package/index.d.ts +450 -0
  254. package/index.js +80 -57
  255. package/package.json +87 -44
  256. package/schemas/project.schema.json +872 -225
  257. package/schemas/vis-config.schema.json +6309 -264
  258. package/schemas/vis-release-config.schema.json +1423 -0
  259. package/skills/vis/SKILL.md +96 -0
  260. package/templates/buildkite-ci/.buildkite/pipeline.yml.tera +85 -0
  261. package/templates/buildkite-ci/template.yml +20 -0
  262. package/dist/config.d.ts +0 -1087
  263. package/dist/config.js +0 -1
  264. package/dist/packem_shared/VisUpdateApp-BBx3idMI.js +0 -1
  265. package/dist/packem_shared/ai-analysis-DDqXRFxY.js +0 -67
  266. package/dist/packem_shared/bin-BaZZ32BK.js +0 -93
  267. package/dist/packem_shared/cache-directory-DL8hfXeG.js +0 -1
  268. package/dist/packem_shared/catalog-CuSpuB_R.js +0 -12
  269. package/dist/packem_shared/dependency-scan-BoLG2Fez.js +0 -1
  270. package/dist/packem_shared/docker-BcfqH4Av.js +0 -2
  271. package/dist/packem_shared/flakiness-DSIHZGBT.js +0 -1
  272. package/dist/packem_shared/otelPlugin-DxyvBcXO.js +0 -1
  273. package/dist/packem_shared/runtime-check-CGHal8SO.js +0 -1
  274. package/dist/packem_shared/selectors-CfH9ZY08.js +0 -3
  275. package/dist/packem_shared/symbols-CIMw60-G.js +0 -1
  276. package/dist/packem_shared/toolchain-C3ZG0o_X.js +0 -5
  277. package/dist/packem_shared/typosquats-Bpq4zcWL.js +0 -1
  278. package/dist/packem_shared/utils-DrNg0XTR.js +0 -1
@@ -4,341 +4,988 @@
4
4
  "title": "vis project.json",
5
5
  "description": "Per-project configuration for @visulima/vis. Place a project.json in each workspace package root.",
6
6
  "type": "object",
7
- "additionalProperties": false,
8
7
  "properties": {
9
- "$schema": {
10
- "type": "string",
11
- "description": "JSON Schema reference for editor autocomplete."
12
- },
13
- "projectType": {
14
- "type": "string",
15
- "enum": ["library", "application"],
16
- "description": "Whether this project is a library (consumed by others) or an application (deployment target)."
17
- },
18
- "sourceRoot": {
19
- "type": "string",
20
- "description": "Source root directory, relative to this project's root. Used for display and language inference.",
21
- "default": "src"
22
- },
23
- "tags": {
8
+ "implicitDependencies": {
24
9
  "type": "array",
25
- "items": { "type": "string" },
26
- "description": "Filterable tags. Used by query language (--query \"tag=frontend\"), scoped task defaults, and tag-relationship constraints."
10
+ "items": {
11
+ "type": "string"
12
+ },
13
+ "description": "Implicit dependencies on other projects."
27
14
  },
28
- "layer": {
15
+ "language": {
29
16
  "type": "string",
30
- "enum": ["configuration", "library", "scaffolding", "tool", "automation", "application"],
31
- "description": "Project layer in the dependency hierarchy. When enforceLayerRelationships is enabled, projects may only depend on the same or lower layer: configuration < library < scaffolding < tool < automation < application."
17
+ "description": "Primary language — informational and query-able."
32
18
  },
33
- "stack": {
19
+ "layer": {
34
20
  "type": "string",
35
- "enum": ["backend", "frontend", "data", "infrastructure", "systems"],
36
- "description": "Technology stack classification. Used by query language and scoped task defaults."
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."
37
30
  },
38
- "language": {
31
+ "name": {
39
32
  "type": "string",
40
- "description": "Primary programming language (e.g. \"typescript\", \"rust\", \"go\"). Used by query language and scoped task defaults.",
41
- "examples": ["typescript", "javascript", "rust", "go", "python"]
42
- },
43
- "implicitDependencies": {
44
- "type": "array",
45
- "items": { "type": "string" },
46
- "description": "Workspace project names this project implicitly depends on (not expressed in package.json)."
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."
47
34
  },
48
35
  "owners": {
49
36
  "type": "array",
50
- "description": "Code ownership declarations. Aggregated by `vis sync codeowners` to generate a CODEOWNERS file.",
51
37
  "items": {
52
- "type": "object",
53
- "required": ["path", "owners"],
54
- "additionalProperties": false,
55
- "properties": {
56
- "path": {
57
- "type": "string",
58
- "description": "File or glob pattern relative to this project root (e.g. \"src/**\", \".\")."
59
- },
60
- "owners": {
61
- "type": "array",
62
- "items": { "type": "string" },
63
- "description": "Owner handles (e.g. \"@org/team\", \"user@example.com\")."
64
- },
65
- "channel": {
66
- "type": "string",
67
- "description": "Optional notification channel (e.g. Slack channel). Emitted as a trailing comment in CODEOWNERS."
68
- }
69
- }
70
- }
38
+ "$ref": "#/$defs/OwnersEntry"
39
+ },
40
+ "description": "Code owners for paths inside this project."
71
41
  },
72
42
  "project": {
73
43
  "type": "object",
74
- "description": "Human-readable project metadata.",
75
- "additionalProperties": false,
76
44
  "properties": {
77
- "title": {
78
- "type": "string",
79
- "description": "Display name for the project."
45
+ "channel": {
46
+ "type": "string"
80
47
  },
81
48
  "description": {
82
- "type": "string",
83
- "description": "Short description of the project's purpose."
49
+ "type": "string"
84
50
  },
85
- "channel": {
86
- "type": "string",
87
- "description": "Primary support channel (e.g. Slack, Teams)."
51
+ "maintainers": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "string"
55
+ }
88
56
  },
89
57
  "owner": {
90
- "type": "string",
91
- "description": "Primary owner or team handle."
58
+ "type": "string"
92
59
  },
93
- "maintainers": {
94
- "type": "array",
95
- "items": { "type": "string" },
96
- "description": "List of maintainer handles."
60
+ "title": {
61
+ "type": "string"
97
62
  }
98
- }
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."
99
102
  },
100
103
  "targets": {
101
104
  "type": "object",
102
- "description": "Named build/test/run targets. Merged on top of package.json scripts — the command from scripts is used as the default if no command is set here.",
103
105
  "additionalProperties": {
104
- "$ref": "#/$defs/targetConfiguration"
105
- }
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."
106
113
  }
107
114
  },
115
+ "additionalProperties": false,
108
116
  "$defs": {
109
- "targetConfiguration": {
117
+ "OwnersEntry": {
110
118
  "type": "object",
111
- "description": "Configuration for a single target.",
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
+ ],
112
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",
113
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
+ },
114
173
  "command": {
115
174
  "type": "string",
116
- "description": "The shell command to execute. Overrides the package.json script of the same name."
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 `&lt;= 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"
117
243
  },
118
244
  "executor": {
119
245
  "type": "string",
120
- "description": "Alternative to command — an executor identifier."
246
+ "description": "The executor/command to run"
121
247
  },
122
- "cache": {
123
- "type": "boolean",
124
- "description": "Whether this target's results are cacheable. Defaults based on type: build=true, test=true, run=false."
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."
125
255
  },
126
256
  "inputs": {
127
257
  "type": "array",
128
- "description": "Input patterns for cache invalidation. Supports file globs, @filegroup:<name> references, and structured input definitions.",
129
258
  "items": {
130
- "oneOf": [
131
- { "type": "string" },
132
- { "$ref": "#/$defs/fileSetInput" },
133
- { "$ref": "#/$defs/environmentInput" },
134
- { "$ref": "#/$defs/runtimeInput" },
135
- { "$ref": "#/$defs/externalDependencyInput" }
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
+ }
136
350
  ]
137
- }
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 `&lt;= 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."
138
357
  },
139
358
  "outputs": {
140
359
  "type": "array",
141
- "items": { "type": "string" },
142
- "description": "Output file/directory patterns produced by this target (e.g. \"dist/**\")."
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."
143
382
  },
144
- "dependsOn": {
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": {
145
656
  "type": "array",
146
- "description": "Other targets this target depends on. Can be plain target names (same project) or dependency config objects.",
147
657
  "items": {
148
- "oneOf": [{ "type": "string" }, { "$ref": "#/$defs/targetDependencyConfig" }]
149
- }
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."
150
661
  },
151
- "configurations": {
152
- "type": "object",
153
- "description": "Named configuration variants (e.g. \"production\", \"development\").",
154
- "additionalProperties": {
155
- "type": "object",
156
- "additionalProperties": true
157
- }
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 &lt;target> -- --flag value`) are validated against it, surfaced by per-task `--help`, and exposed to the command as `VIS_ARG_&lt;NAME>` environment variables."
158
668
  },
159
- "parallelism": {
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": {
160
674
  "type": "boolean",
161
- "description": "Whether this target supports parallel execution.",
162
- "default": true
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."
163
684
  },
164
685
  "type": {
165
- "type": "string",
166
- "enum": ["build", "test", "run"],
167
- "description": "Semantic task type. Affects caching defaults and CI filtering. build/test are cached by default; run is not.",
686
+ "$ref": "#/$defs/TargetType",
687
+ "description": "Semantic task type. Affects caching defaults and CI filtering.",
168
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 } ."
169
700
  },
170
- "preset": {
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": {
171
713
  "type": "string",
172
- "enum": ["server", "utility"],
173
- "description": "Preset that pre-fills a bundle of options. 'server': persistent, no cache, no CI. 'utility': no cache, no CI."
714
+ "description": "One-line help text surfaced by per-task `--help`."
174
715
  },
175
- "options": {
176
- "$ref": "#/$defs/targetOptions"
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\"`."
177
731
  }
178
- }
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."
179
746
  },
180
- "targetOptions": {
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": {
181
758
  "type": "object",
182
- "description": "Vis-specific target options controlling execution behavior.",
183
- "additionalProperties": false,
184
759
  "properties": {
185
- "persistent": {
186
- "type": "boolean",
187
- "description": "Long-running/never-ending process. Scheduled last, never cached.",
760
+ "affectedFiles": {
761
+ "$ref": "#/$defs/AffectedFilesMode",
762
+ "description": "How to forward affected files to the task process. Only used when invoked via `vis affected &lt;target>`.",
188
763
  "default": false
189
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
+ },
190
782
  "interactive": {
191
783
  "type": "boolean",
192
- "description": "Serialized with respect to parallel execution; claims stdin for terminal input.",
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.",
193
785
  "default": false
194
786
  },
195
787
  "internal": {
196
788
  "type": "boolean",
197
- "description": "Hidden from CLI listings. Can only be invoked as a dependency of another task.",
789
+ "description": "When true, the task is hidden from CLI listings and can only be invoked as a dependency of another task.",
198
790
  "default": false
199
791
  },
200
- "runInCI": {
201
- "oneOf": [{ "type": "boolean" }, { "type": "string", "enum": ["affected", "always"] }],
202
- "description": "Controls whether this task runs in CI. true=always, false=never, 'affected'=only when project is affected, 'always'=even if unaffected.",
203
- "default": true
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
204
796
  },
205
- "retryCount": {
206
- "type": "integer",
207
- "minimum": 0,
208
- "description": "Number of times to retry on failure.",
209
- "default": 0
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)."
210
800
  },
211
- "retryDelay": {
212
- "oneOf": [
213
- { "type": "integer", "minimum": 0 },
214
- { "type": "string", "const": "exponential" }
801
+ "outputStyle": {
802
+ "type": "string",
803
+ "enum": [
804
+ "normal",
805
+ "quiet"
215
806
  ],
216
- "description": "Delay between retries in ms, or \"exponential\" for 2^attempt * 1000ms.",
217
- "default": "exponential"
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."
218
808
  },
219
- "affectedFiles": {
220
- "oneOf": [
221
- { "type": "boolean", "const": false },
222
- { "type": "string", "enum": ["args", "env", "both"] }
223
- ],
224
- "description": "How to forward affected files to the task. false=don't, 'args'=as command arguments, 'env'=via VIS_AFFECTED_FILES, 'both'=both.",
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.",
225
812
  "default": false
226
813
  },
227
- "envFile": {
228
- "type": "string",
229
- "description": "Dotenv file to load before running. Path relative to the project root.",
230
- "examples": [".env", ".env.local", ".env.production"]
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."
231
817
  },
232
- "mutex": {
233
- "type": "string",
234
- "description": "Named mutex. All tasks sharing the same mutex name are serialized.",
235
- "examples": ["db-migration"]
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
236
822
  },
237
- "osType": {
238
- "oneOf": [
239
- { "type": "string", "enum": ["linux", "macos", "windows"] },
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": [
240
830
  {
241
- "type": "array",
242
- "items": { "type": "string", "enum": ["linux", "macos", "windows"] }
831
+ "type": "number"
832
+ },
833
+ {
834
+ "type": "string",
835
+ "const": "exponential"
243
836
  }
244
837
  ],
245
- "description": "Restrict execution to specific operating systems. Tasks on non-matching OS are skipped."
838
+ "description": "Delay between retry attempts in milliseconds, or `\"exponential\"` for 2^attempt * 1000 ms.",
839
+ "default": "exponential"
246
840
  },
247
841
  "runFromWorkspaceRoot": {
248
842
  "type": "boolean",
249
- "description": "Execute from the workspace root instead of the project root.",
843
+ "description": "When true, the command executes with the workspace root as CWD instead of the project root.",
250
844
  "default": false
251
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 &lt;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
+ },
252
862
  "shell": {
253
863
  "type": "string",
254
- "description": "Per-target shell override (cross-platform).",
255
- "examples": ["/bin/bash", "/bin/zsh"]
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."
256
880
  },
257
881
  "unixShell": {
258
882
  "type": "string",
259
- "description": "Shell override for Linux and macOS. Takes precedence over 'shell'."
883
+ "description": "Per-target unix shell override, used on Linux and macOS. Takes precedence over `shell` on unix-like systems."
260
884
  },
261
885
  "windowsShell": {
262
886
  "type": "string",
263
- "description": "Shell override for Windows. Takes precedence over 'shell'.",
264
- "examples": ["powershell.exe", "cmd.exe"]
265
- },
266
- "preset": {
267
- "type": "string",
268
- "enum": ["server", "utility"],
269
- "description": "Preset applied before user options."
887
+ "description": "Per-target windows shell override, used on Windows. Takes precedence over `shell` on Windows."
270
888
  }
271
- }
272
- },
273
- "targetDependencyConfig": {
274
- "type": "object",
275
- "description": "Structured dependency on another target.",
276
- "required": ["target"],
889
+ },
277
890
  "additionalProperties": false,
278
- "properties": {
279
- "target": {
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
+ {
280
917
  "type": "string",
281
- "description": "The target name to depend on."
918
+ "const": "affected"
282
919
  },
283
- "dependencies": {
284
- "type": "boolean",
285
- "description": "When true, run this target on all dependency projects first (equivalent to turbo's ^target)."
286
- },
287
- "projects": {
288
- "oneOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
289
- "description": "Specific project name(s) to run this target on."
290
- },
291
- "params": {
292
- "type": "string",
293
- "enum": ["forward", "ignore"],
294
- "description": "Whether to forward or ignore parameters from the parent task."
295
- }
296
- }
297
- },
298
- "fileSetInput": {
299
- "type": "object",
300
- "required": ["fileset"],
301
- "additionalProperties": false,
302
- "properties": {
303
- "fileset": {
920
+ {
304
921
  "type": "string",
305
- "description": "Glob pattern for input files (e.g. \"src/**/*.ts\")."
922
+ "const": "always"
923
+ },
924
+ {
925
+ "type": "boolean"
306
926
  }
307
- }
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."
308
929
  },
309
- "environmentInput": {
930
+ "ServiceConfig": {
310
931
  "type": "object",
311
- "required": ["env"],
312
- "additionalProperties": false,
313
932
  "properties": {
314
933
  "env": {
315
- "type": "string",
316
- "description": "Environment variable name to include in cache key."
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."
317
976
  }
318
- }
319
- },
320
- "runtimeInput": {
321
- "type": "object",
322
- "required": ["runtime"],
977
+ },
323
978
  "additionalProperties": false,
324
- "properties": {
325
- "runtime": {
326
- "type": "string",
327
- "description": "Shell command whose output is included in cache key (e.g. \"node --version\")."
328
- }
329
- }
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."
330
980
  },
331
- "externalDependencyInput": {
332
- "type": "object",
333
- "required": ["externalDependencies"],
334
- "additionalProperties": false,
335
- "properties": {
336
- "externalDependencies": {
337
- "type": "array",
338
- "items": { "type": "string" },
339
- "description": "npm package names whose resolved versions are included in cache key."
340
- }
341
- }
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."
342
989
  }
343
990
  }
344
991
  }