@getvitops/cli 4.1.0 → 6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,257 @@
1
1
  # @getvitops/cli
2
2
 
3
+ ## 6.0.0
4
+
5
+ **No consumer-facing change in this package.** The major is the toolchain's shared version, bumped
6
+ in lockstep for the carousel rework in `@getvitops/core` / `generator` / `astro`. Every command
7
+ behaves as it did in 5.0.0; `vitops docs components` and `vitops docs css` will report the new
8
+ carousel vocabulary, because they render live from the generator.
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies
13
+ - @getvitops/generator@6.0.0
14
+ - @getvitops/utils@6.0.0
15
+
16
+ ## 5.0.0
17
+
18
+ ### Major Changes
19
+
20
+ - **Dangling token references are now a build failure.** `validate()` resolves every `var(--…)` a
21
+ config authors — in `patterns.defaults` / `radii` / `groups` / `items.*.{base,overrides,states}`,
22
+ `typography.roles` and `shadows` — against the tokens that config actually emits. A reference to a
23
+ token that does not exist used to validate, generate, minify and ship, then resolve to nothing in
24
+ the browser: one downstream config shipped a `.cta` whose `color` fell back to `inherit` on a brand
25
+ fill (unreadable text on every filled button), and two of its four dead references had been dead for
26
+ several releases with nothing ever reporting them.
27
+
28
+ The check is deliberately anchored to the namespaces the generator owns — `--color-*`, `--shadow-*`,
29
+ `--z-tier-*`, `--surface-glass`, `--overlay` — the same discipline `vitops lint` follows. A pattern
30
+ may legitimately reference a framework token from `@getvitops/core` or a hook of your own, and
31
+ enumerating "every valid token" would make those false positives. A reference carrying a fallback
32
+ (`var(--x, 0.25rem)`) is never flagged: that is you saying what happens when the token is absent.
33
+ Errors name the config path and suggest the nearest token that does exist.
34
+
35
+ Two related diagnostics ship with it:
36
+ - **Pre-1.0 colour-grammar references are reported as one rename table**, not as a dozen separate
37
+ "no such token" errors — the shape the 3.0 flat-config detector uses, applied to the 1.0 colour
38
+ change. It is built from your own role names, and it says to apply the renames _simultaneously_,
39
+ because several of them rotate (`--surface-bg` → `--color-bg-surface-muted`,
40
+ `--surface-bg-bold` → `--color-bg-surface`) and sequential replacement compounds them.
41
+ - **A surface-shaped role declared chromatic now warns.** A bare hue string is shorthand for
42
+ `kind: "chromatic"`, which emits no bare `--color-bg-<role>` and no `.bg-<role>` — so writing
43
+ `"surface": "ink"` silently removed `--color-bg-surface` and the 36 references the framework's own
44
+ CSS makes to it. Relatedly, `--surface-glass`, `--overlay` and `.glass` are no longer emitted when
45
+ `surface` is chromatic: they read `--color-bg-surface`, so emitting them pointed at nothing.
46
+
47
+ **`vitops lint --fix` is now the migration tool.** It reads `var(--…)` out of CSS and `<style>`
48
+ blocks (not just `class` attributes) and rewrites pre-1.0 token references in a **single pass**, so
49
+ the rotating renames cannot compound. Nothing else is rewritten — every other finding it reports is
50
+ a judgement call. Run it after a major bump.
51
+
52
+ **`--help` works on every subcommand.** `vitops lint --help` used to exit non-zero with
53
+ `Unknown option '--help'`; every leaf subcommand parsed its own argv strictly and none declared the
54
+ option. It is now answered before dispatch, so no command can forget it, and a drift guard fails the
55
+ build if a command has no documented options. (`validate`'s options were genuinely undocumented and
56
+ now are.)
57
+
58
+ **The Astro integration reads `site.tracking` and `site.legal.cookieConsent`.** These drive the
59
+ generated cookie notice, while `vitops({ consent, tracking })` drove the runtime — two hand-synced
60
+ declarations of the same fact with nothing comparing them, so a site could ship a notice naming
61
+ categories its banner never offered, or disclosing an `_ac` cookie no capture script ever wrote, and
62
+ the build was clean. The config blocks are now defaults (as `css` / `fonts` / `favicon` / `ads`
63
+ already were) and a genuine contradiction — `true` against `false` on the same fact — **fails the
64
+ build**, naming both sides. An absent option is not a contradiction; it just takes the config's
65
+ value.
66
+
67
+ Also fixed, each from a downstream report:
68
+ - **`@getvitops/astro/tracking`** re-exports `@getvitops/utils/tracking` (plus `TRACKING_ENDPOINT`),
69
+ so the documented conversion flow works with one install. Under strict pnpm app code cannot
70
+ resolve a transitive dependency, and the obvious workaround — importing the same symbols from the
71
+ package index — is the one that drags the integration's Node builtins toward a Worker bundle. This
72
+ entry and `./routes` are both clean.
73
+ - **`createConversionRoute`'s example was broken on every supported Astro.** It read the binding off
74
+ `locals.runtime.env`, removed in Astro v6, while the package peers on `>= 7` — and because the
75
+ throw precedes the response, Astro re-reads the request and reports a misleading "Body has already
76
+ been used". It also called a `toNotifyContext()` helper that does not exist. The example now uses
77
+ `import { env } from 'cloudflare:workers'` and a plain `NotifyContext`.
78
+ - **`/api/track` is exported as `TRACKING_ENDPOINT`**, and the integration warns at build when
79
+ tracking is on and no route answers it. It was a bare literal inside the inlined capture script:
80
+ name the route file anything else and every `tel:` beacon 404s, conversions vanish, and nothing
81
+ errors anywhere.
82
+ - **`describeEvent` no longer reports "from Unknown"** for forms that don't have a field literally
83
+ named `name`. It now falls back through `first_name`/`last_name`, `full_name`, and finally the
84
+ email address.
85
+ - **`sendEmail` takes `timeoutMs` (default 10s).** `binding.send()` had no deadline, so one hung
86
+ attempt hung the request that produced it — indefinitely, in the one module otherwise built on
87
+ always saying why. A timeout is retried, like any other transient failure.
88
+ - **`vitops search notify` warns when the sitemap's URLs aren't on the configured origin.** A 404
89
+ fails loudly; a well-formed sitemap belonging to someone else did not — a route collision served a
90
+ valid document listing another site's pages and the run reported a healthy submission. Surfaces at
91
+ `--dry`.
92
+ - **`require()` warns when the page has no `<wc-consent>`.** The demand can never be granted, so
93
+ whatever waited on it never runs — silently. Hit by rendering `<Tracking />` on pages where
94
+ `<CookieConsent />` wasn't.
95
+ - **`vitops agents` no longer writes a path it guessed.** It used to warn and then write "tokens
96
+ live in `design-system.json`" into a project whose tokens are in `company.json`, with the four
97
+ emitted `vitops generate` commands hard-coded to match — copy-paste-broken in exactly the projects
98
+ that most need the block to be right. It now finds the config by shape, interpolates the resolved
99
+ path into every emitted command, and fails rather than guessing when there is nothing to name.
100
+ - **`vitops search setup --dry` and `vitops ads setup --dry` run without credentials.** A dry run
101
+ that mutates nothing should not demand the token to mutate; with none set it plans from scratch
102
+ and says so. (`--check` still needs them — drift is a comparison against live state.) Both now
103
+ also mention that the Cloudflare token needs `Zone:Read` alongside `Zone:DNS:Edit` — the
104
+ zone-by-name lookup uses it, and its absence read as "the zone isn't in this account".
105
+ - **`vitops legal` names the files it wrote and flags new ones.** Enabling `cookieConsent` silently
106
+ produced a `cookie-notice` document that then needs a page, a route, a link and a `policyUrl`; the
107
+ command said only "3 files". The review reminder is also printed on the stdout path, where it was
108
+ missing entirely.
109
+ - **`vitops init` writes a versioned `$schema`** — `./node_modules/@getvitops/generator/schema.json`,
110
+ following wrangler — instead of an unpinned unpkg URL that resolved to whatever was newest, so an
111
+ editor validated a pinned project against a schema it wasn't built with.
112
+ - **`favicon.backgroundColor` and `favicon.name` are described accurately.** `backgroundColor` is
113
+ not manifest-only: it fills the opaque `apple-touch-icon.png` and `icon-mask.png`, which are
114
+ written whether or not a manifest is. `name` documents that it and `themeColor` **together** are
115
+ what make a site installable. The missing-background warning now also fires for a dark opaque mark,
116
+ not only a transparent source — `apple-touch-icon` insets the logo and fills the surround either
117
+ way.
118
+
119
+ - **The framework now says out loud which patterns are foundational, and reports it when you
120
+ reach past them.** From repeated downstream reports: sites were inventing a `.wrap` class and
121
+ using it everywhere instead of `.centered`, and `.subgrid` — the class for any set of cards —
122
+ was going essentially unused. Neither failure is visible in a build: every class involved is
123
+ real, nothing errors, and the page renders.
124
+
125
+ **`.subgrid` was missing from the generated class reference entirely.** So was `.cluster`, and
126
+ so was `.region`. `vitops docs classes` is the doc an agent is told to fetch for "which class
127
+ do I apply", and the framework's answer for a set of cards was not in it — which is most of why
128
+ it never got used. All three are now documented, along with `grid-auto`, and the reference opens
129
+ with a **Foundations** section that states the six substitutions as
130
+ _temptation → what to write instead_ rather than as a vocabulary list. The same table is now in
131
+ the shipped agent skill and in the `@getvitops/create` template's `AGENTS.md`, because a pointer
132
+ to a doc only helps someone who already suspects there is something to look up. (`css`/`bricks`
133
+ and `tailwind` alike — this is documentation and the `TIERS` manifest, not emitted CSS.)
134
+
135
+ **`vitops lint` gained three reuse rules and a markup pass.** The existing `.centered` rule only
136
+ fired when the hand-written CSS already referenced `--width-measure`, which is precisely the
137
+ author who was never going to hand-roll a container. It now also catches a page-scale
138
+ `max-width` (≥ 48rem, or a `ch` reading measure) with auto margins, and a
139
+ container-shaped class name — `wrap`, `wrapper`, `container`, `inner`, `shell`, … — carrying any
140
+ width cap at all. Reading the cap out of `min()` / `clamp()` too. New rules report a
141
+ hand-written `repeat()` grid as `.subgrid` (or `.grid-auto`), and a new **markup** pass reports a
142
+ repeated card set laid out without either — a loop that renders a card, or three or more cards
143
+ written out. That last one is the only check that can see this drift at all, since a card list
144
+ built from utility classes contains no bad class and no hand-written CSS.
145
+
146
+ All of these are `suggestion` severity, so they do not fail your build unless you pass
147
+ `--strict`. They found five real instances in this repo's own docs site.
148
+
149
+ **`vitops lint [files...]`** now takes explicit paths instead of scanning `--src`, so it can be
150
+ wired into a pre-commit hook — `vp`'s `staged` key appends the staged files to whatever it runs,
151
+ and a command that refused positionals could not be put in the one place the feedback lands at
152
+ the moment the code is written. Unreadable and non-source paths are skipped rather than fatal. The
153
+ `@getvitops/create` emdash template wires it up with `--strict` and adds a `lint:design` script.
154
+
155
+ **Two answers for "the whole card is a link", because one cannot exist.** Reported downstream:
156
+ agents dislike the `<li>` wrapper when a card is a link and write `<li><a class="card">` instead.
157
+ That shape is **wrong in a way that renders fine**, which is why it survives review — the `<li>`
158
+ is the grid item, so the anchor is an ordinary block inside it and the tranches within the anchor
159
+ never reach the parent's shared row lines. The alignment `.subgrid` exists for silently does not
160
+ happen, and the anchor does not fill the cell either. Putting the anchor in the grid's place
161
+ (`<ul><a></ul>`) is invalid HTML, so there was genuinely no correct shape to reach for.
162
+
163
+ There are now two, and they trade against each other because **no CSS-only technique can make a
164
+ whole card clickable and leave its text selectable** — a transparent overlay necessarily receives
165
+ the pointer-drag:
166
+
167
+ | Want | Use |
168
+ | ---------------------------------------- | ------------------------------------------- |
169
+ | zero JS, whole card clickable | `.stretched-link` — **text not selectable** |
170
+ | selectable text **and** a clickable card | `<Cards>` / `<wc-cards>` — needs JS |
171
+
172
+ `.stretched-link` goes on a link inside the card; its `::after` covers the card.
173
+ **`<wc-cards>` is a new tier-2 element** that adds no overlay and instead tells a click apart from
174
+ the end of a drag, so text selection survives. Its fallback is the card's own link, fully usable
175
+ with no JS, and the pointer cursor is applied by the element — so the affordance never appears
176
+ without the behaviour. `<Cards>` emits it for you. They are alternatives, never layered: with an
177
+ overlay present the JS has nothing to do, and `vitops lint` reports the combination. (All formats
178
+ — pattern partials, deliberately not `utilities.css`, which the tailwind format skips on the
179
+ invariant that everything left in it is a name Tailwind ships itself.)
180
+
181
+ ### Breaking
182
+ - **`<Subgrid />` renders its slot verbatim — author the `<li>` items yourself.**
183
+
184
+ ```diff
185
+ <Subgrid>
186
+ - <article class="card">…</article>
187
+ + <li class="card subgrid-card">…</li>
188
+ </Subgrid>
189
+ ```
190
+
191
+ It used to parse the slotted HTML and rebuild each child as an `<li>`, carrying over only
192
+ `class` and `style`. That existed solely because a `<ul>` may contain nothing else, and it cost
193
+ more than it bought: the child's tag was discarded, `id`/`data-*`/`aria-*` were silently
194
+ dropped, and `href` could not survive at all. Nothing is copied now, so nothing is lost. `as`
195
+ picks the container (`ul` by default, `ol`, `div`), and all other props are forwarded — they
196
+ were previously discarded, including `role`.
197
+
198
+ - **`<Subgrid />` and `<Tree />` now emit `role="list"`,** as does the Bricks `sitenav` element.
199
+ `list-style: none` stops Safari + VoiceOver announcing a `<ul>` as a list, so every marker-less
200
+ framework list was silently losing the semantics its `<ul>` was chosen for. If you hand-write
201
+ `.subgrid`, `.list`, `.facet-list`, `.nav-items`, `.collapse-menu` or `.tree` markup, add
202
+ `role="list"` yourself — the framework cannot add it to markup it does not render, and each
203
+ partial now says so at the `list-style` reset.
204
+ - **`<Cards />` no longer adds `class="card"` to slotted children,** because it no longer parses
205
+ them. Write the class on the item. It now emits `<wc-cards>` around a `<Subgrid>`, which is what
206
+ makes the whole card clickable — and like `<Tree />`, **it emits its own element, so do not wrap
207
+ it in `<wc-cards>` yourself.** It also previously passed a `role="list"` that `<Subgrid>` silently
208
+ discarded, so that never took effect.
209
+ - **`.subgrid-card` now sets `position: relative`**, so `stretched-link` inside it needs no extra
210
+ class. If you were absolutely positioning a descendant of a `.subgrid-card` against an ancestor
211
+ _outside_ that card, it will now resolve against the card. Move the positioning context
212
+ explicitly. (`css`/`bricks`/`tailwind` — the pattern partial is inlined into all three.) Not
213
+ reachable by `vitops lint --fix`: the fix depends on which ancestor you meant, which the
214
+ linter cannot know.
215
+
216
+ ### Fixed
217
+ - **`packages/generator/src/docs.ts` contained a literal NUL byte** (`CODE_SLOT`, written as the
218
+ raw character rather than an escape). libmagic classified the file as `data` rather than text, so
219
+ grep and ripgrep treated the largest doc emitter in the repo as **binary and silently skipped
220
+ it** — every search for a string in it returned nothing, with no error. It is now written as the `\u0000` escape.
221
+ Behaviour is identical; the file is searchable.
222
+ - **`.grid-auto` is documented.** It was a real framework class for auto-fit card grids with no
223
+ entry in the class reference, so the honest alternative to `subgrid` was as invisible as
224
+ `subgrid` itself.
225
+ - **`.raised` replaces the advice to use `.relative` above a `stretched-link` overlay**, which
226
+ could not work: a positioned element at `z-index: auto` does not rise above an explicit
227
+ `z-index` regardless of DOM order, so a second link or button in the card stayed underneath and
228
+ unclickable. `.raised` sets both, against the same `--z-tier-raised` token the overlay now uses
229
+ instead of a hard-coded `1`.
230
+
231
+ ### Patch Changes
232
+
233
+ - **Astro and Bricks are documented as the same tier, because they are.** Both are platform
234
+ wrappers that generate HTML from the classes and elements of tiers 1 and 2 — siblings chosen by
235
+ which platform you are on, not steps in a ladder. No project uses both, and neither outranks the
236
+ other.
237
+
238
+ They were published as tier 3 and **tier 4**, in `vitops docs components`, the shipped agent
239
+ skill and the docs site. The cause was a projection axis being read as a hierarchy: `Tier` has
240
+ four keys (`css` `wc` `astro` `bricks`) because there are four tables to render, and the tier
241
+ number was being derived from that key order — so the last key became "tier 4". The advice next
242
+ to it inherited the error, telling readers to "use the highest-**numbered** tier your stack has",
243
+ which reads as Bricks outranking Astro.
244
+
245
+ Nothing about which patterns each tier provides has changed; this is the numbering and the prose
246
+ around it. `Tier` keeps its four keys — that part was never wrong — and now says in its own type
247
+ docs why four keys are three levels, so the next renderer cannot repeat the derivation.
248
+
249
+ - Updated dependencies
250
+ - Updated dependencies
251
+ - Updated dependencies
252
+ - @getvitops/generator@5.0.0
253
+ - @getvitops/utils@5.0.0
254
+
3
255
  ## 4.1.0
4
256
 
5
257
  ### Minor Changes